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
循环; - 代码里用
sqlsession
的ExecutorType.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、deptId
是Map的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
注解