MyBatis 核心知识点详解:题目与解析
MyBatis 核心知识点详解:题目与解析
MyBatis 是一个强大的持久层框架,广泛应用于 Java 开发中。本文将结合具体的题目,详细解析 MyBatis 的核心知识点,包括事务控制、自增主键回填、参数获取、结果映射以及动态 SQL,帮助大家更好地掌握这些内容。
题目1:MyBatis 控制事务
关于 MyBatis 控制事务,下列描述正确的是( )
选项:
- A. MyBatis 控制事务默认是自动提交事务
- B. MyBatis 控制事务默认是手动提交事务
- C. 如果执行增删改语句,MyBatis 中需要执行:会话工厂对象.openSession(true);
- D. 如果执行增删改语句,MyBatis 中需要执行:会话对象.commit();
解析:
1. MyBatis 的默认事务行为
- MyBatis 的
SqlSession
默认是手动提交事务的,即需要显式调用commit()
方法才能提交事务。 - 如果希望自动提交事务,可以在创建
SqlSession
时传入参数true
,例如:sqlSessionFactory.openSession(true)
。 - 因此,选项 A 错误,选项 B 正确。
2. 增删改操作的事务控制
- 对于增删改操作,MyBatis 默认不会自动提交事务,必须显式调用
commit()
方法。 - 如果希望自动提交事务,可以在创建
SqlSession
时使用openSession(true)
。 - 因此,选项 C 和 D 都是正确的。
正确答案:B、C、D
示例代码:
// 手动提交事务
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
sqlSession.insert("insertUser", user);
sqlSession.commit(); // 显式提交事务
} finally {
sqlSession.close();
}
// 自动提交事务
SqlSession sqlSession = sqlSessionFactory.openSession(true);
sqlSession.insert("insertUser", user); // 不需要显式调用 commit()
题目2:MyBatis 实现自增主键回填
关于 MyBatis 实现自增主键回填,下列描述正确的是( )
选项:
- A. 自增主键回填表示新增一条数据成功后,将这条数据的主键封装到实体类中,并查看主键的值。
- B. 想实现自增主键回填 insert 标签的属性 useGeneratedKeys 的属性值为 false
- C. 想实现自增主键回填 insert 标签的属性 keyColumn 的属性值书写主键字段名
- D. 想实现自增主键回填 insert 标签的属性 keyProperty 的属性值书写主键的成员变量名
解析:
1. 自增主键回填的作用
- 自增主键回填是指在插入数据后,将数据库生成的主键值回填到实体类中,方便后续操作使用。
- 因此,选项 A 正确。
2. useGeneratedKeys 属性
useGeneratedKeys
属性用于指示是否使用数据库生成的主键。其值应为true
,表示启用自增主键回填。- 因此,选项 B 错误。
3. keyColumn 属性
keyColumn
属性用于指定数据库表中主键字段的名称。- 因此,选项 C 正确。
4. keyProperty 属性
keyProperty
属性用于指定实体类中主键字段的属性名。- 因此,选项 D 正确。
正确答案:A、C、D
示例代码:
<insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>
useGeneratedKeys="true"
:启用自增主键回填。keyColumn="id"
:指定数据库表中的主键字段名。keyProperty="id"
:指定实体类中的主键属性名。
题目3:#{} 获取数据
关于 #{参数名} 获取数据,下列描述正确的是( )
选项:
- A. 如果接口方法形参只有一个简单类型的数据,那么 #{参数名},参数名随便书写
- B. 如果接口方法形参只有一个简单类型的数据,并且在方法上使用 @Param("参数名") 修饰形参,那么 #{参数名},参数名随便书写
- C. 如果接口方法形参有多个简单类型的数据,那么可以使用 #{arg0}, #{arg1}... 等来获取数据
- D. 如果接口方法形参是 POJO 类型的数据,那么可以使用 #{参数名} 来获取数据,参数名需要和 POJO 类的成员变量名或者 getXxxx() 方法去掉 get, X 变为 x 即 xxxx 一致
解析:
1. 单个简单类型参数
- 如果方法只有一个简单类型参数(如
int
、String
等),#{}
中的参数名可以随意书写。 - 因此,选项 A 正确。
2. 使用 @Param 注解
- 如果方法参数使用了
@Param
注解,#{}
中的参数名必须与注解中指定的名称一致。 - 因此,选项 B 错误。
3. 多个简单类型参数
- 如果方法有多个简单类型参数,可以通过
#{arg0}
、#{arg1}
等方式获取参数。 - 因此,选项 C 正确。
4. POJO 类型参数
- 如果参数是 POJO 类型,
#{}
中的参数名必须与 POJO 类的成员变量名或对应的 getter 方法名一致。 - 因此,选项 D 正确。
正确答案:A、C、D
示例代码:
// 单个简单类型参数
User selectUserById(int id);
// 多个简单类型参数
User selectUserByNameAndAge(String name, int age);
// POJO 类型参数
int insertUser(User user);
<select id="selectUserById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="selectUserByNameAndAge" resultType="User">
SELECT * FROM user WHERE name = #{arg0} AND age = #{arg1}
</select>
<insert id="insertUser">
INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>
题目4:#{} 和 ${} 取值
关于 #{} 和 ${} 取值,下列描述错误的是( )
选项:
- A. #{} 可以防止 SQL 注入问题
- B. ${} 不能防止 SQL 注入问题
- C. ${} 不会添加引号
- D. #{} 可以完成拼接 SQL
解析:
1. #{} 的作用
#{}
是预编译的,会将参数值安全地绑定到 SQL 中,防止 SQL 注入。- 因此,选项 A 正确。
2. ${} 的作用
${}
是直接拼接 SQL,存在 SQL 注入风险。- 因此,选项 B 正确。
3. ${} 的特性
${}
不会自动添加引号,适合用于表名、列名等非字符串类型的拼接。- 因此,选项 C 正确。
4. #{} 的特性
#{}
是预编译的,不能用于拼接 SQL,拼接 SQL 应使用${}
。- 因此,选项 D 错误。
正确答案:D
示例代码:
<select id="selectUserByTableName" resultType="User">
SELECT * FROM ${tableName} WHERE id = #{id}
</select>
${tableName}
:直接拼接表名。#{id}
:预编译绑定参数值。
题目5:结果映射
关于结果映射,下列描述错误的是( )
选项:
- A. 如果接口中的方法返回值是单列集合,那么 resultType 中书写集合类型
- B. resultMap 可以完成多表查询
- C. 如果接口中的方法返回值是 POJO 类型,那么 resultType 中书写 POJO 类名
- D. resultMap 可以解决 POJO 属性名和表结构字段名不一致的问题
解析:
1. 单列集合的返回值
- 如果方法返回值是单列集合(如
List<User>
),resultType
应写集合中元素的类型(如User
),而不是集合类型本身。 - 因此,选项 A 错误。
2. resultMap 的作用
resultMap
可以处理复杂的多表查询结果映射。- 因此,选项 B 正确。
3. POJO 类型的返回值
- 如果方法返回值是 POJO 类型,
resultType
应写 POJO 类的全限定名。 - 因此,选项 C 正确。
4. 属性名与字段名不一致
resultMap
可以解决 POJO 属性名和数据库字段名不一致的问题。- 因此,选项 D 正确。
正确答案:A
示例代码:
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
</resultMap>
<select id="selectUser" resultMap="userResultMap">
SELECT user_id, user_name FROM user
</select>
题目6:动态 SQL
关于动态 SQL,下列描述错误的是( )
选项:
- A. if 标签表示判断的,如果 test 属性值中的 OGNL 表达式的值为 true,则执行标签文本
- B. 多分支标签使用 choose, when, otherwise,只会执行满足一个条件的标签
- C. where 标签作用能够添加 where 关键字同时能够去除多余的 and 或者 or 关键字
- D. set 标签作用只能添加 set 关键字
解析:
1. if 标签
if
标签用于条件判断,当test
属性中的 OGNL 表达式为true
时,执行标签内的 SQL。- 因此,选项 A 正确。
2. choose 标签
choose
、when
、otherwise
标签用于多分支条件判断,只会执行第一个满足条件的when
标签。- 因此,选项 B 正确。
3. where 标签
where
标签会自动添加WHERE
关键字,并去除多余的AND
或OR
。- 因此,选项 C 正确。
4. set 标签
set
标签不仅会添加SET
关键字,还会去除多余的逗号。- 因此,选项 D 错误。
正确答案:D
示例代码:
<update id="updateUser">
UPDATE user
<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</set>
WHERE id = #{id}
</update>
总结
通过以上题目的详细解析,我们对 MyBatis 的核心知识点有了更深入的理解。掌握这些内容,能够帮助我们在实际开发中更加高效地使用 MyBatis,编写出安全、灵活的 SQL 语句。如果还有任何疑问,欢迎留言讨论! 😊
希望这篇博客对你有所帮助!如果有其他问题,欢迎随时提问!