Skip to content

Commit 0f8b749

Browse files
committed
字节跳动面经
1 parent 6427178 commit 0f8b749

File tree

3 files changed

+322
-172
lines changed

3 files changed

+322
-172
lines changed

docs/sidebar/sanfene/mybatis.md

Lines changed: 185 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -80,126 +80,6 @@ head:
8080
- Hibernate 是标准的 ORM 框架,SQL 编写量较少,但不够灵活,适合于需求相对稳定,中小型的软件项目,比如:办公自动化系统
8181
- MyBatis 是半 ORM 框架,需要编写较多 SQL,但是比较灵活,适合于需求变化频繁,快速迭代的项目,比如:电商网站
8282

83-
### 21.说说 JDBC 的执行步骤?
84-
85-
> 2024 年 03 月 19 日增补
86-
87-
Java 数据库连接(JDBC)是一个用于执行 SQL 语句的 Java API,它为多种关系数据库提供了统一访问的机制。使用 JDBC 操作数据库通常涉及以下步骤:
88-
89-
#### 1. 加载数据库驱动
90-
91-
在与数据库建立连接之前,首先需要通过`Class.forName()`方法加载对应的数据库驱动。这一步确保 JDBC 驱动注册到了`DriverManager`类中。
92-
93-
```java
94-
Class.forName("com.mysql.cj.jdbc.Driver");
95-
```
96-
97-
#### 2. 建立数据库连接
98-
99-
使用`DriverManager.getConnection()`方法建立到数据库的连接。这一步需要提供数据库 URL、用户名和密码作为参数。
100-
101-
```java
102-
Connection conn = DriverManager.getConnection(
103-
"jdbc:mysql://localhost:3306/databaseName", "username", "password");
104-
```
105-
106-
#### 3. 创建`Statement`对象
107-
108-
通过建立的数据库连接对象`Connection`创建`Statement``PreparedStatement``CallableStatement`对象,用于执行 SQL 语句。
109-
110-
```java
111-
Statement stmt = conn.createStatement();
112-
```
113-
114-
或者创建`PreparedStatement`对象(预编译 SQL 语句,适用于带参数的 SQL):
115-
116-
```java
117-
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM tableName WHERE column = ?");
118-
pstmt.setString(1, "value");
119-
```
120-
121-
#### 4. 执行 SQL 语句
122-
123-
使用`Statement``PreparedStatement`对象执行 SQL 语句。
124-
125-
执行查询(SELECT)语句时,使用`executeQuery()`方法,它返回`ResultSet`对象;
126-
127-
执行更新(INSERT、UPDATE、DELETE)语句时,使用`executeUpdate()`方法,它返回一个整数表示受影响的行数。
128-
129-
```java
130-
ResultSet rs = stmt.executeQuery("SELECT * FROM tableName");
131-
```
132-
133-
134-
135-
```java
136-
int affectedRows = stmt.executeUpdate("UPDATE tableName SET column = 'value' WHERE condition");
137-
```
138-
139-
#### 5. 处理结果集
140-
141-
如果执行的是查询操作,需要处理`ResultSet`对象来获取数据。
142-
143-
```java
144-
while (rs.next()) {
145-
String data = rs.getString("columnName");
146-
// 处理每一行数据
147-
}
148-
```
149-
150-
#### 6. 关闭资源
151-
152-
最后,需要依次关闭`ResultSet``Statement``Connection`等资源,释放数据库连接等资源。
153-
154-
```java
155-
if (rs != null) rs.close();
156-
if (stmt != null) stmt.close();
157-
if (conn != null) conn.close();
158-
```
159-
160-
#### 总结
161-
162-
使用 JDBC 操作数据库的过程包括加载驱动、建立连接、创建执行语句、执行 SQL 语句、处理结果集和关闭资源。
163-
164-
在 Java 开发中,通常会使用 JDBC 模板库(如 Spring 的 JdbcTemplate)或 ORM 框架(如 Hibernate、MyBatis、MyBatis-Plus)来简化数据库操作和资源管理。
165-
166-
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 10 后端实习一面的原题:JDBC 的执行步骤
167-
168-
### 22.创建连接拿到的是什么对象?
169-
170-
在 JDBC 的执行步骤中,创建连接后拿到的对象是`java.sql.Connection`对象。这个对象是 JDBC API 中用于表示数据库连接的接口,它提供了执行 SQL 语句、管理事务等一系列操作的方法。
171-
172-
`Connection`对象代表了应用程序和数据库的一个连接会话。
173-
174-
通过调用`DriverManager.getConnection()`方法并传入数据库的 URL、用户名和密码等信息来获得这个对象。
175-
176-
一旦获得`Connection`对象,就可以使用它来创建执行 SQL 语句的`Statement``PreparedStatement``CallableStatement`对象,以及管理事务等。
177-
178-
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 10 后端实习一面的原题:创建连接拿到的是什么对象
179-
180-
### 23.Statement与PreparedStatement的区别
181-
182-
>2024年03月19日增补
183-
184-
`Statement``PreparedStatement`都是用于执行 SQL 语句的接口,但它们之间存在几个关键的区别:
185-
186-
#### 1. 预编译
187-
188-
①、**Statement**:每次执行`Statement`对象的`executeQuery``executeUpdate`方法时,SQL 语句在数据库端都需要重新编译和执行。这适用于一次性执行的 SQL 语句。
189-
190-
②、**PreparedStatement**:代表预编译的 SQL 语句的对象。这意味着 SQL 语句在`PreparedStatement`对象创建时就被发送到数据库进行预编译。
191-
192-
之后,可以通过设置参数值来多次高效地执行这个 SQL 语句。这不仅减少了数据库编译 SQL 语句的开销,也提高了性能,尤其是对于重复执行的 SQL 操作。
193-
194-
#### 2. 参数化查询
195-
196-
- **Statement**:不支持参数化查询。如果需要在 SQL 语句中插入变量,通常需要通过字符串拼接的方式来实现,这会增加 SQL 注入攻击的风险。
197-
- **PreparedStatement**:支持参数化查询,即可以在 SQL 语句中使用问号(?)作为参数占位符。通过`setXxx`方法(如`setString``setInt`)设置参数,可以有效防止 SQL 注入。
198-
199-
总的来说,`PreparedStatement`相比`Statement`有着更好的性能和更高的安全性,是执行 SQL 语句的首选方式,尤其是在处理含有用户输入的动态查询时。
200-
201-
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 10 后端实习一面的原题:statement 和 preparedstatement 的区别
202-
20383
### 3. MyBatis 使用过程?生命周期?
20484

20585
MyBatis 基本使用的过程大概可以分为这么几步:
@@ -1094,10 +974,194 @@ MyBatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集
1094974

1095975
![Mybatis-通用分页拦截器](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/mybatis-0bcdca85-e127-44ff-92e0-368a3f089ec8.png)
1096976

1097-
> 图文详解 23 道 MyBatis 面试高频题,这次吊打面试官,我觉得稳了(手动 dog)。整理:沉默王二,戳[转载链接](https://mp.weixin.qq.com/s/en2RgcVx52Ql3tYGLfv3Kw),作者:三分恶,戳[原文链接](https://mp.weixin.qq.com/s/O_5Id2o9IP4loPazJuiHng)
977+
## 补充
978+
979+
### 21.说说 JDBC 的执行步骤?
980+
981+
> 2024 年 03 月 19 日增补
982+
983+
Java 数据库连接(JDBC)是一个用于执行 SQL 语句的 Java API,它为多种关系数据库提供了统一访问的机制。使用 JDBC 操作数据库通常涉及以下步骤:
984+
985+
第一步,加载数据库驱动
986+
987+
在与数据库建立连接之前,首先需要通过`Class.forName()`方法加载对应的数据库驱动。这一步确保 JDBC 驱动注册到了`DriverManager`类中。
988+
989+
```java
990+
Class.forName("com.mysql.cj.jdbc.Driver");
991+
```
992+
993+
第二步,建立数据库连接
994+
995+
使用`DriverManager.getConnection()`方法建立到数据库的连接。这一步需要提供数据库 URL、用户名和密码作为参数。
996+
997+
```java
998+
Connection conn = DriverManager.getConnection(
999+
"jdbc:mysql://localhost:3306/databaseName", "username", "password");
1000+
```
1001+
1002+
第三步,创建`Statement`对象
1003+
1004+
通过建立的数据库连接对象`Connection`创建`Statement``PreparedStatement``CallableStatement`对象,用于执行 SQL 语句。
1005+
1006+
```java
1007+
Statement stmt = conn.createStatement();
1008+
```
1009+
1010+
或者创建`PreparedStatement`对象(预编译 SQL 语句,适用于带参数的 SQL):
1011+
1012+
```java
1013+
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM tableName WHERE column = ?");
1014+
pstmt.setString(1, "value");
1015+
```
1016+
1017+
第四步,执行 SQL 语句
1018+
1019+
使用`Statement``PreparedStatement`对象执行 SQL 语句。
1020+
1021+
执行查询(SELECT)语句时,使用`executeQuery()`方法,它返回`ResultSet`对象;
1022+
1023+
执行更新(INSERT、UPDATE、DELETE)语句时,使用`executeUpdate()`方法,它返回一个整数表示受影响的行数。
1024+
1025+
```java
1026+
ResultSet rs = stmt.executeQuery("SELECT * FROM tableName");
1027+
```
1028+
1029+
1030+
1031+
```java
1032+
int affectedRows = stmt.executeUpdate("UPDATE tableName SET column = 'value' WHERE condition");
1033+
```
1034+
1035+
第五步,处理结果集
1036+
1037+
如果执行的是查询操作,需要处理`ResultSet`对象来获取数据。
1038+
1039+
```java
1040+
while (rs.next()) {
1041+
String data = rs.getString("columnName");
1042+
// 处理每一行数据
1043+
}
1044+
```
1045+
1046+
第六步,关闭资源
1047+
1048+
最后,需要依次关闭`ResultSet``Statement``Connection`等资源,释放数据库连接等资源。
1049+
1050+
```java
1051+
if (rs != null) rs.close();
1052+
if (stmt != null) stmt.close();
1053+
if (conn != null) conn.close();
1054+
```
1055+
1056+
在 Java 开发中,通常会使用 JDBC 模板库(如 Spring 的 JdbcTemplate)或 ORM 框架(如 Hibernate、MyBatis、MyBatis-Plus)来简化数据库操作和资源管理。
1057+
1058+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 10 后端实习一面的原题:JDBC 的执行步骤
1059+
1060+
### 22.创建连接拿到的是什么对象?
1061+
1062+
在 JDBC 的执行步骤中,创建连接后拿到的对象是`java.sql.Connection`对象。这个对象是 JDBC API 中用于表示数据库连接的接口,它提供了执行 SQL 语句、管理事务等一系列操作的方法。
1063+
1064+
`Connection`对象代表了应用程序和数据库的一个连接会话。
1065+
1066+
通过调用`DriverManager.getConnection()`方法并传入数据库的 URL、用户名和密码等信息来获得这个对象。
1067+
1068+
一旦获得`Connection`对象,就可以使用它来创建执行 SQL 语句的`Statement``PreparedStatement``CallableStatement`对象,以及管理事务等。
1069+
1070+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 10 后端实习一面的原题:创建连接拿到的是什么对象
1071+
1072+
### 23.Statement与PreparedStatement的区别
1073+
1074+
>2024年03月19日增补
1075+
1076+
`Statement``PreparedStatement`都是用于执行 SQL 语句的接口,但它们之间存在几个关键的区别:
1077+
1078+
①、每次执行`Statement`对象的`executeQuery``executeUpdate`方法时,SQL 语句在数据库端都需要重新编译和执行。这适用于一次性执行的 SQL 语句。
1079+
1080+
**Statement** 不支持参数化查询。如果需要在 SQL 语句中插入变量,通常需要通过字符串拼接的方式来实现,这会增加 SQL 注入攻击的风险。
1081+
1082+
②、**PreparedStatement** 代表预编译的 SQL 语句的对象。这意味着 SQL 语句在`PreparedStatement`对象创建时就被发送到数据库进行预编译。
1083+
1084+
之后,可以通过设置参数值来多次高效地执行这个 SQL 语句。这不仅减少了数据库编译 SQL 语句的开销,也提高了性能,尤其是对于重复执行的 SQL 操作。
1085+
1086+
**PreparedStatement** 支持参数化查询,即可以在 SQL 语句中使用问号(`?`)作为参数占位符。通过`setXxx`方法(如`setString``setInt`)设置参数,可以有效防止 SQL 注入。
1087+
1088+
总的来说,`PreparedStatement`相比`Statement`有着更好的性能和更高的安全性,是执行 SQL 语句的首选方式,尤其是在处理含有用户输入的动态查询时。
1089+
1090+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 10 后端实习一面的原题:statement 和 preparedstatement 的区别
1091+
1092+
### 24. 什么是 SQL 注入?如何防止 SQL 注入?
1093+
1094+
SQL 注入是一种代码注入技术,通过在输入字段中插入专用的 SQL 语句,从而欺骗数据库执行恶意 SQL,从而获取敏感数据、修改数据,或者删除数据等。
1095+
1096+
比如说有这样一段代码:
1097+
1098+
```java
1099+
studentId = getRequestString("studentId");
1100+
lookupStudent = "SELECT * FROM students WHERE studentId = " + studentId
1101+
```
1102+
1103+
用户在输入框中输入 117 进行查询:
1104+
1105+
![cloudflare:SQL 查询](https://cdn.tobebetterjavaer.com/stutymore/mybatis-20240418100433.png)
1106+
1107+
实际的 SQL 语句类似于:
1108+
1109+
```sql
1110+
SELECT * FROM students WHERE studentId = 117
1111+
```
1112+
1113+
这是我们期望用户输入的正确方式。但是,如果用户输入了`117 OR 1=1`,那么 SQL 语句就变成了:
1114+
1115+
```sql
1116+
SELECT * FROM students WHERE studentId = 117 OR 1=1
1117+
```
1118+
1119+
由于`1=1`为真,所以这个查询将返回所有学生的信息,而不仅仅是 ID 为 117 的学生。
1120+
1121+
![cloudflare:SQL 注入](https://cdn.tobebetterjavaer.com/stutymore/mybatis-20240418100940.png)
1122+
1123+
为了防止 SQL 注入,可以采取以下措施:
1124+
1125+
①、使用参数化查询
1126+
1127+
使用参数化查询,即使用`PreparedStatement`对象,通过`setXxx`方法设置参数值,而不是通过字符串拼接 SQL 语句。这样可以有效防止 SQL 注入。
1128+
1129+
```java
1130+
String query = "SELECT * FROM users WHERE username = ?";
1131+
PreparedStatement pstmt = connection.prepareStatement(query);
1132+
pstmt.setString(1, userName); // userName 是用户输入
1133+
ResultSet rs = pstmt.executeQuery();
1134+
```
1135+
1136+
`?` 是一个参数占位符,userName 是外部输入。这样即便用户输入了恶意的 SQL 语句,也只会被视为参数的一部分,不会改变查询的结构。
1137+
1138+
②、限制用户输入
1139+
1140+
对用户输入进行验证和过滤,只允许输入预期的数据,不允许输入特殊字符或 SQL 关键字。
1141+
1142+
③、使用 ORM 框架
1143+
1144+
比如,在 MyBatis 中,使用`#{}`占位符来代替直接拼接 SQL 语句,MyBatis 会自动进行参数化处理。
1145+
1146+
```xml
1147+
<select id="selectUser" resultType="User">
1148+
SELECT * FROM users WHERE username = #{userName}
1149+
</select>
1150+
```
1151+
1152+
假如 userName 传入的值是 `9;DROP TABLE SYS_USER;`,传入的删除表 SQL 也不会执行,因为它会被当作参数值。
1153+
1154+
```sql
1155+
SELECT * FROM users WHERE username = '9;DROP TABLE SYS_USER;'
1156+
```
1157+
1158+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动面经同学 13 Java 后端二面面试原题:什么是SQL注入,怎么避免,什么是参数化
1159+
10981160

10991161
---
11001162

1163+
图文详解 23 道 MyBatis 面试高频题,这次吊打面试官,我觉得稳了(手动 dog)。整理:沉默王二,戳[转载链接](https://mp.weixin.qq.com/s/en2RgcVx52Ql3tYGLfv3Kw),作者:三分恶,戳[原文链接](https://mp.weixin.qq.com/s/O_5Id2o9IP4loPazJuiHng)
1164+
11011165
_没有什么使我停留——除了目的,纵然岸旁有玫瑰、有绿荫、有宁静的港湾,我是不系之舟_
11021166

11031167
**系列内容**

0 commit comments

Comments
 (0)