第十六天,7月10日,八股
1、mybatis的延迟加载
需要时才加载关联对象,而不是查询主对象时,立刻加载所有关联对象,这样可以提高查询性能并减少不必要的数据库访问,例如:一个订单表包含着商品列表(一对多),当查询订单对象时,不会立刻从数据库加载商品列表,而是等到第一次真正使用到商品时采取查询数据库
一般一对多,多对多的场景适用延迟加载,如何开启?
(1)局部开启:在<collection ... fetchType="lazy">
(2)全局开启:
mybatis.configuration.lazy-loading-enable=true #开启全局懒加载
mybatis.configuration.aggressiv-lazy-loading=false #关闭立即加载
注意:mybatis的核心在于使用动态代理技术
1、在查询主对象时,MyBatis 并不会直接创建关联对象或集合的实例。
2、而是会为这些关联属性或集合创建一个 代理对象,
3、当用户代码首次访问这个代理对象的属性或方法时,
4、代理对象会拦截这次调用,代理对象内部会检查关联数据是否已经被加载,
5、如果数据尚未加载,代理对象会根据 ResultMap 中 association 或 collection 标签的 select 属性指定的 Mapper 方法和 column 属性提供的参数,发起一个新的数据库查询。
6、查询结果(关联数据)会被加载到代理对象中。
7、代理对象将加载的数据返回给用户。后续对该代理对象的访问将直接返回已加载的数据,不再触发数据库查询(在同一个 SqlSession 生命周期内)
2、谈谈mybatis插件的原理
MyBatis 插件用于拦截 SQL 执行并增强其功能。插件基于 JDK 动态代理机制,在 MyBatis 初始化过程中为指定对象生成代理对象,当拦截对象执行某个方法时,代理会先执行插件中的逻辑,再执行原有逻辑.
(1)插件类需要实现mybatis的interceptor接口,还需要通过注解标注该插件的拦截点
(2)拦截点就是指插件所能拦截的方法,mybtias允许拦截的方法如下:
【1】Executor:执行器的方法(有update(包含了update,insert,delete),query,commit,rollback,close等)
【2】statementHandler:查操作,增删改操作,设置参数,sql的预编译,批处理
【3】ParameterHandler: 获取参数和设置参数
【4】ResultSetHandler:结果的组装
3、如何获取mybatis中自增的主键
在平时开发中,可能会遇到数据库主键是自增的情况,这时我们保存数据时并不需要指定主键,可是很多时候都需要获取保存数据后生成的主键,怎么办呢?
1、在mapper.xml中的insert标签使用useGeneratedKeys="true" keyProPerty="id" keyColumn="id"
- useGeneratedKeys:是否自动生成主键,默认false。
- keyColumn:数据库中的自增主键的列名,默认是数据库表的第一列,当主键列不是表中的第一列的时候需要设置。
- keyProperty:返回的主键值赋给实体类中哪个属性。
2、在insert中嵌套使用selectKey标签
<insert id="insertBook" parameterType="com.learn.entity.Book"><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">SELECT LAST_INSERT_ID()</selectKey>INSERT INTO BOOK(NAME) VALUES(#{name})</insert>
4、不同的Mapper中的id是否可以相同
可以相同,每一个映射文件的namespace都会设置对应的mapper接口的全类路径名称,也就是保证了每个一个mapper文件的namespace都是唯一的,只需要满足同一个映射文件的id是不同即可
5、myabtis中属性名和字段名不一致怎么办?
(1)在sql语句中通过别名来映射到java的属性
(2)通过resultMap配置映射关系
(3)如果是因为下划线转换为驼峰命名造成的不一致:mapUnderscoreToCamelCase
6、谈谈你对mybatis中的Executor理解
在MyBatis中,执行器(Executor)是核心组件之一,负责SQL语句的生成和查询缓存的维护。
Executor的类型有三个
- SIMPLE: 默认 SimpleExecutor,每次操作都是一个新的Statement对象
- REUSE : ReuseExecutor,会根据SQL缓存Statement对象,实现Statement对象的复用,样可以减少数据库的准备和创建Statement的开销
- BATCH: BatchExecutor 批处理,将所有的修改操作,直到调用flushStatements()方法时才一次性发送到数据库执行。这种方式可以减少网络往返次数,提高批量操作的效率。
7、如何设置mybatis中的Executor的类型
(1)可以通过SqlSessionFactory的openSession添加Executor参数
(2)配置文件mybatis.executor-type=batch
8、Mybatis中如何实现多个传参
(1)使用@param
public User selectUser(@Param("userName") String name, @Param("deptId") int deptId);<select id="selectUser" resultMap="UserResultMap">
select * from user
where user_name = #{userName} and dept_id = #{deptId}
</select>
(2)使用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>
(3)使用java bean
public User selectUser(User user);<select id="selectUser" parameterType="com.test.User" resultMap="UserResultMap">
select * from user
where user_name = #{userName} and dept_id = #{deptId}
</select>
(4)基于参数顺序传参
public User selectUser(String name, int deptId);<select id="selectUser" resultMap="UserResultMap">
select * from user
where user_name = #{0} and dept_id = #{1}
</select>