Mybatis(四):myBatis面试相关
2019-02-27 本文已影响0人
aix91
1. #{} 和${} 的区别
${}是用来获取properties文件中的配置属性;#{}是Mybatis中的占位符,可以用来防止依赖注入。具体原理是,mybatis在创建prepareStatement时,会用 ?来替换#{}, 然后在执行前sql语句前,通过反射的方式在statement里set 相应的参数。
2. myBatis xml中有哪些标签
标签 | 说明 |
---|---|
select | |
insert | |
update | |
delete | |
resultMap | |
parameterMap | |
sql | |
include | |
selectKey |
3. Mapper 接口
Mapper接口是没有实现类的;mapper 的 namespace和mapper方法名,可以唯一定位一个MappedStatement;同一个mapper里面不能重载方法,因为方法是由namespace+类名+方法名唯一确定的。
Mapper的工作原理是JDK动态代理生成对象,获取sql执行语句,然后根据参数拼接成正确的sql语句进行执行。
4. 当实体类中的属性名和表中的column名不一致时,应该怎样解决?
- 在select时使用别名,别名和实体类的属性名保持一致
- 使用resultMap 或者 @Results注解
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
<!–用id属性来映射主键字段–>
<id property=”id” column=”id”/>
<result property = “descccc” column =”description”/>
<result property=”title222” column=”title” />
</resultMap>
@Results({@Result(column = "description",property = "descccc"),
@Result(column = "title",property = "title222")
})
TestModel select(@Param("uniqueCode") String uniqueCode);
5. Mybatis是如何进行分页操作?
- RowBounds: 性能太差了,不如自己使用limit写分页
- 延迟关联优化
select a.salary from salaries as a inner join (select emp_no from salaries limit 2800000,10) as b using(emp_no);
- 书签优化
select * from salaries where emp_no>=495317 limit 10
6. Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
- 使用<resultMap>
- 在SQL 语句中使用别名
Mybatis通过反射创建对象,并且直接对属性进行赋值(没有用到set方法);要想成功创建对象,要保留对象的无参构造函数,或者创建一个包含所有属性的构造函数
7. 如何执行批量插入?
使用<foreach> 拼接SQL语句,批量插入数据库。
<insert id="insertList" parameterType="java.util.List">
insert into tb_test(
unique_code,
title,
keywords,
description
) values
<foreach collection="list" item="element" open="(" separator="),(" close=")">
#{element.uniqueCode},
#{element.title222},
#{element.keword},
#{element.descccc}
</foreach>
on duplicate key update
unique_code = values(unique_code),
title = values(title),
keywords = values(keywords),
description = values(description)
</insert>
8. 如何获取自动生成的(主)键值?
<insert id="insertOne" parameterType="com.xxx.Test"useGeneratedKeys="true" keyProperty="element.id">
insert into test(
unique_code,
title,
keywords,
description
) values(
#{element.uniqueCode},
#{element.title222},
#{element.keword},
#{element.descccc}
);
</insert>
注意keyProperty = 对象名.id
9. 一对一、一对多的关联查询
- 一对多:使用collection + resultMap
<select id="selectEmployee" resultMap="employeeResultMap">
select a.emp_no, a.last_name, b.salary from employees as a
inner join salaries as b on a.emp_no = b.emp_no
where a.emp_no = #{emp_no}
</select>
<resultMap id="employeeResultMap" type="com.test.Employee">
<result property="empNo" column="emp_no"/>
<result property="lastName" column="last_name"/>
<collection property="salaries" resultMap="salaryResultMap"/>
</resultMap>
<resultMap id="salaryResultMap" type="com.test.Salary">
<result property="empNo" column="emp_no"/>
<result property="salary" column="salary"/>
</resultMap>
- 一对多:collection+select
<select id="selectEmployee" resultMap="employeeResultMap">
select a.emp_no, a.last_name from employees as a
where a.emp_no = #{emp_no}
</select>
<resultMap id="employeeResultMap" type="com.test.Employee">
<result property="empNo" column="emp_no"/>
<result property="lastName" column="last_name"/>
<collection property="salaries"
select="com.test.TestMapper.selectSalary"
column="{emp_num= emp_no}"/>
</resultMap>
<resultMap id="salaryResultMap" type="com.test.Salary">
<result property="empNo" column="emp_no"/>
<result property="salary" column="salary"/>
</resultMap>
<select id="selectSalary" resultMap="salaryResultMap">
select emp_no, salary from salaries where emp_no=#{emp_num}
</select>
- 一对一:使用association+resultMap
<resultMap id="salaryResultMap" type="com.test.Salary">
<result property="empNo" column="emp_no"/>
<result property="salary" column="salary"/>
</resultMap>
<resultMap id="employeeResultMap2" type="com.test.Employee">
<result property="empNo" column="emp_no"/>
<result property="lastName" column="last_name"/>
<association property="salaries" resultMap="salaryResultMap"/>
</resultMap>
<select id="selectCurrentEmployee" resultMap="employeeResultMap2">
select a.emp_no, a.last_name, b.salary from employees as a
inner join salaries as b on a.emp_no = b.emp_no
where a.emp_no = #{1}
and b.to_date='9999-01-01'
</select>
10. 简述Mybatis的插件运行原理,以及如何编写一个插件
11. Mybatis延迟加载
mybatis 仅支持"collection", "association" 的懒加载,且只能用在association/collection+select
模式上。
- 全局设置懒加载模式
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
- 在collection/association 中单独设置 "fetchType = lazy"(eager 禁用懒加载)
<resultMap id="employeeResultMap" type="com.test.Employee">
<result property="empNo" column="emp_no"/>
<result property="lastName" column="last_name"/>
<collection property="salaries"
select="com.test.TestMapper.selectSalary"
column="{emp_num= emp_no}" fetchType="lazy"
/>
</resultMap>
原理: 使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。