MyBatis是一款优秀的持久层框架,在Java开发中广受欢迎。下面是一些常见的MyBatis面试题,以及相应的案例分析,希望对你的学习和面试有所帮助。
MyBatis是一款基于Java的持久层框架,它通过XML描述符或注解将对象与存储过程或SQL语句进行映射,实现了面向对象编程与关系数据库的映射。
MyBatis的执行流程主要包括:
动态SQL是MyBatis中的一项强大功能,它可以根据条件判断动态拼接SQL语句,避免硬编码。
例如,动态SQL可以在条件成立时插入WHERE子句:
<select id="getUserList" resultType="User">
SELECT * FROM user
<where>
<if test="id != null">AND id = #{id}if>
<if test="name != null">AND name = #{name}if>
where>
select>
可以使用parameterType
属性指定参数类型,使用#{}
占位符引用参数。例如:
<select id="getUserById" resultType="User" parameterType="int">
SELECT * FROM user WHERE id = #{id}
select>
可以使用foreach
标签进行批量插入。例如:
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO user (name, age) VALUES
<foreach collection="list" item="item" index="index" separator=",">
(#{item.name}, #{item.age})
foreach>
insert>
延迟加载是指在需要使用数据时才真正去查询数据库,而不是立即加载所有关联数据。通过配置lazyLoadingEnabled
实现延迟加载。
MyBatis的乐观锁是通过版本号实现的,即在数据表中增加一个版本号字段。在更新时,比较版本号是否一致,如果一致才更新数据。
@Update("UPDATE user SET name = #{name}, version = #{version + 1} WHERE id = #{id} AND version = #{version}")
int updateUser(User user);
可以使用select
标签调用存储过程,使用resultMap
映射输出参数。
<select id="callProcedure" statementType="CALLABLE" parameterType="Map">
{call my_procedure(
#{inputParam, mode=IN, jdbcType=INTEGER},
#{outputParam, mode=OUT, jdbcType=VARCHAR}
)}
select>
#{}
用于预编译,会将参数进行安全的替换,防止SQL注入。${}
是直接拼接参数,不进行预编译,慎用防止SQL注入。
<select id="getUserById" resultType="User" parameterType="int">
SELECT * FROM user WHERE id = #{id}
select>
<select id="getUserByName" resultType="User" parameterType="String">
SELECT * FROM user WHERE name = '${name}'
select>
逆向工程是指通过数据库表结构自动生成MyBatis的实体类、映射文件以及DAO接口,减少手动编写的工作量。
使用逆向工程工具如MyBatis Generator,可以根据数据库表结构生成对应的Java代码。
ResultMap是MyBatis中用于映射查询结果集的配置,通过ResultMap可以将查询结果映射成复杂的Java对象。
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
resultMap>
<select id="getUserById" resultMap="userResultMap" parameterType="int">
SELECT * FROM user WHERE id = #{id}
select>
用于分支选择,
表示条件满足时执行,
表示所有条件都不满足时执行。
<select id="getUserByCondition" resultType="User">
SELECT * FROM user
<where>
<choose>
<when test="name != null">AND name = #{name}when>
<when test="age != null">AND age = #{age}when>
<otherwise>AND 1=1otherwise>
choose>
where>
select>
使用
标签可以方便地进行批量更新。
<update id="batchUpdate" parameterType="java.util.List">
<foreach collection="list" item="item" separator=";">
UPDATE user SET name = #{item.name}, age = #{item.age} WHERE id = #{item.id}
foreach>
update>
懒加载是指在需要使用关联数据时才去加载,而不是在查询主体数据时就将关联数据一并加载。
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<collection property="orders" ofType="Order" column="user_id" select="getOrdersByUserId" lazyLoading="true"/>
resultMap>
使用
标签判断是否需要拼接分页SQL。
<select id="getUserByPage" resultType="User" parameterType="Map">
SELECT * FROM user
<where>
<if test="name != null">AND name = #{name}if>
<if test="age != null">AND age = #{age}if>
where>
LIMIT #{start}, #{pageSize}
select>
通过resultSets
属性指定多个结果集。
<select id="getUserAndOrder" resultType="User" statementType="CALLABLE" parameterType="Map" resultSets="user,order">
{call get_user_and_order(#{userId, mode=IN, jdbcType=INTEGER})}
select>
MyBatis的缓存分为一级缓存和二级缓存,一级缓存是SqlSession级别的缓存,二级缓存是Mapper级别的缓存。
使用
标签可以方便地动态拼接更新字段。
<update id="dynamicUpdate" parameterType="User">
UPDATE user
<set>
<if test="name != null">name = #{name},if>
<if test="age != null">age = #{age},if>
set>
WHERE id = #{id}
update>
以上是MyBatis经典面试题20题,每个问题都附带有案例分析。希望这些内容对你的学习和面试有所帮助。
感谢阅读!