MyBatis面试题

1. #{}与${}的区别是什么?

MyBatis在处理#{}的时候会对SQL语句进行预编译处理,把#{}的内容解析成,在之后赋值时还会在外层加双引号;
而在处理${}的时候,会直接把SQL语句中的${}解析成参数值,并且不会加双引号。

2. 当实体类中的属性名与表中的字段名不一样,怎么办?

  • 在SQL语句中指定字段别名;
  • 使用<resultMap>将属性名和字段名一一映射。

3. Mybatis是如何将SQL执行结果封装成目标对象并返回的,都有哪些映射形式?

和题目2一样,只是问法不同。

  • 在SQL语句中指定字段别名;
  • 使用<resultMap>将属性名和字段名一一映射。
<resultMap type="cn.com.mybatis.pojo.User" id="UserResult">
    <result property="username" column="name"/>
</resultMap>
<select id="findUserById" parameterType="java.lang.Long" resultMap="UserResult">
    select id,name,email from t_user where id=#{id}
</select>

MyBatis在通过以上两种方式将属性名和字段名对应上后,通过<resultMap>type属性得知应该创建哪种类型的对象,进而通过反射创建对象,并且对对象的属性一一赋值。

4. 怎么利用Mybatis实现批量数据的插入?

  • XML文件里用<foreach>标签;
  • 代码里用for循环;
  • 代码里用sqlsessionExecutorType.BATCH模式。
SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

5. 在mapper中如何传多个参数?

  • #{0}#{1}…接受函数中的参数
public User selectUser(String name, int deptId);

<select id="selectUser" resultMap="UserResultMap">
    select * from user
    where user_name = #{0} and dept_id = #{1}
</select>
  • @Param将函数中参数和SQL中参数绑定
public User selectUser(@Param("userName") String name, int @Param("deptId") deptId);

<select id="selectUser" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>
  • Map传参
public User selectUser(Map<String, Object> params);

<select id="selectUser" parameterType="java.util.Map" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

userName、deptIdMap的key,还要注意parameterType的值。

  • 用对象传参
public User selectUser(User user);

<select id="selectUser" parameterType="com.jourwon.pojo.User" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

userName、deptId是对象User的属性,还要注意parameterType的值。

6. Mybatis有哪些动态的SQL? 执行原理?

动态SQL类似于Java的判断流程。
Mybatis 提供了 9 种动态 sql 标签:trim | where | set | foreach | if | choose | when | otherwise | bind

7. MyBatis中不同的XML映射文件,是否可以存在相同的语句id,为什么?

  • 如果不同的XML映射文件具有不同的namespace,那么可以用相同的id
  • 如果不同的XML映射文件使用相同的namespace,或者同一XML文件中是不能用相同的id的,因为namespace+id等同于类的全限定名+方法名,不能重复。

8. 通常一个XML映射文件,都会写一个DAO/Mapper接口与之对应,请问,这个DAO/Mapper接口的工作原理是什么?DAO接口里的方法能重载嘛?

DAO/Mapper接口的工作原理是JDK动态代理,MyBatis运行时会使用JDK动态代理为接口生成代理对象,代理对象会拦截接口方法,然后根据接口的全限定名+方法名定位到XML映射文件中的MapperStatement(在MyBatis中,每个<select><insert><delete><update>标签都会被解析成一个MapperStatement对象),进而执行,然后将sql执行结果返回,填充到实际对象中。

DAO/Mapper接口的全限定名,就是XML映射文件里面的namespace;
接口的方法名就是XML映射文件里的MapperStatement的id值;
接口方法内的参数就是传递给sql的参数。
因此接口内的方法不能重载。

9. Mybatis加载Mapper的方式有哪些?

  • package
<mappers>
    <package name="com.lsj.Mapper" />
</mappers>
  • url
  • resource
<mappers>
    <mapper resource="com/lsj/mapper/UserMapper.xml"/>
</mappers>
  • class
<mappers>
    <mapper class="com.lsj.Mapper.UserMapper" />
</mappers>

10. 如何获取自动生成的主键id值?

  • 使用<selectKey>+SELECT LAST_INSERT_ID();
<insert id="insertById" parameterType="com.lsj.pojo.User">
    <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
        SELECT LAST_INSERT_ID();
    </selectKey>
    insert into user(username,sex,address) values (#{username},#{sex},#{address})
</insert>
  • 使用useGeneratedKey
<insert id=”insertById” usegeneratedkeys=”true” keyproperty=”id”> 
     insert into user(username,sex,address) values (#{username},#{sex},#{address})
</insert>

以上两种方法执行完insert后,主键id值将会填充到对象的id属性中。

11. Mybatis的一对一、一对多查询?

  • <resultMap>标签里配置<association>节点实现一对一,配置<collection>节点实现一对多。
<resultMap id="accounts" type="Account">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <result column="money" property="money"></result>
    <result column="u_id" property="u_id"></result>
    <!--映射user中的属性-->
    <!--映射单个对象-->
    <association property="user" javaType="user">
        <id column="uid" property="id"></id>
        <result column="uname" property="username"></result>
        <result column="address" property="address"></result>
        <result column="birthday" property="birthday"></result>
        <result column="password" property="password"></result>
        <result column="sex" property="sex"></result>
    </association>
</resultMap>
<select id="findAllAccountAssociateUser" resultMap="accounts">
    select * from account a, user u where a.u_id = u.uid
</select>

<resultMap id="users" type="User">
    <id column="uid" property="id"></id>
    <result column="uname" property="username"></result>
    <result column="password" property="password"></result>
    <result column="address" property="address"></result>
    <result column="birthday" property="birthday"></result>
    <result column="sex" property="sex"></result>
    <!--Collection : 映射account的 属性
            property: 对应的属性名 User中包含的Account的属性名
            ofType: 集合中的元素类型: 和association 中javaType效果一致
    -->
    <collection property="account" ofType="account">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="money" property="money" />
        <result column="u_id" property="u_id" />
    </collection>
</resultMap>

<select id="findUserAndAccount" resultMap="users">
    select * from user u left join account a on u.uid = a.u_id
</select>
  • 注解:
    一对一:在@Results注解中的@Result注解中使用@One注解
    一对多:在@Results注解中的@Result注解中使用@Many注解
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值