1.mybatis中${} 和#{}有什么区别?
#{}:底层会翻译占位符?,将来使用PreparedStatement执行编译sql。形参如果是简单类型,并且只有一个#{随便}
${}:底层是字符串替换,将来会使用PreparedStatement执行sql,可能会出现sql注入。形参如果是简单类型,并且只有一个¥{value};常用于动态表查询
2.mybatis如何执行批量插入?
循环单次插入;
使用SpringBoot项目直接循环插入
MP批量插入功能:
使用三层架构(controller,service,mapper)实现效率比循环单次效率高;
MP插入的核心实现代码是saveBatch方法,调用executeBatch方法进行插入,其实现过程为将插入的数据分成N份,每满1000条就会执行一次批量插入,所以性能要比循环单次插入的性能高。
原生批量插入功能:
原生批量插入方法是依靠MyBatis中的foreach标签,将数据拼接成一条原生的insert语句一次执行,在XML文件中进行操作。
缺点:使用原生方法进行SQL拼接时,若超过默认情况下可以执行的最大SQL(4M)时,程序就会报错。(也是为什么 MP 需要分批执行的原因)
解决措施:可以通过设置可以执行的最大SQL来解决
-- 设置最大执行 SQL 为 10M
set global max_allowed_packet=10*1024*1024;
3.mybatis如何在插入后获得主键 ?
第一种:在xml文件中,insert标签属性中,添加userGenatedKeys和KeyProperty
第二种:在xml文件中添加selectKey标签属性,各个属性值含义:
resiultType:查询结果的类型;
keyProperty:把查询的值赋给谁;
order:在插入前还是后执行,id在insert语句插入之后才会生成id,所以要在插入之后执 行,所以此处order=after
第三种:在dao层用注解的方式,用@SelectKey注解,里面属性含义:
resultType:查询结果的类型
keyProperty:把查询的值赋给谁;
statement:查找最后一个插入的id;
KeyColumn:查询的是哪一列
before:是否在插入之前执行,id在insert语句插入之后才会生成id,所以要在插入之后执 行,所以此处before=false
第四种:在对应的实体类种指定主键id的
@TableId(type = IdType.ASSIGN_ID)
private Long id;
4.mybatis中resultType和resultMap区别?
-
对象不同
resultMap:如查处的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名 之间做一个映射关系
resultType :使用resultType进行输出映射,只有查出的实体类和列名一致,该列才能映射成功
-
描述不同
resultMap:对于一对一表连接的处理方式通常在主表的pojo添加嵌套另一个表的pojo,然后在 mapper.xml中采用associaton节点元素进行对另一个表的连接处理
resultType :该字段无法查询结果结果映射到pojo对象的pojo属性中,根据对结构集查询遍历的 需要选择使用resultType还是resultMap
-
类型不适(二者不可同时使用)
- mybatis中在查询进行select映射的时候,返回值类型二者都可用
resultMap:resultMap是对外部resultMap的引用。
resultType :resultType是直接表示返回类型的。
5.mybatis一级缓存和二级缓存?
一级缓存:
概述:
一级缓存也叫本地会话,对于一个sqlSession,如想要多次执行同一条sql,第一次会把查询结果保存在一级缓存中,再次查询时会直接去一级缓存中获取,不会再次访问数据库,大大减少了数据库的负压,但是此时sqlSession关闭链接之后,一级缓存就会被清理。
一级缓存之中的数据是基于hashmap存储的,是属于sqlSession级别的缓存,在sqlsession对象内部维护Map。
执行流程
当执行sql语句的时候,首先将sql语句和参数作为key,在一级缓存中查找数据,如果有数据:直接返回,如果没有,将sql语句发送到数据库中,数据库执行sql返回语句。将sql语句和参数作为key,将查询到的数据作为value存入一级缓存。
每个sqlSession有自己的一级缓存。
一级缓存的清理:
当执行增删改操作时,sqlSession一级缓存会被清理
当我们调用sqlSession。cleanCache()清理一级缓存
二级缓存:
概述:
也叫全局缓存,当sqlSession关闭连接后,会将一级缓存中的数据转存到二级缓存中。默认情况下时不开启的,但是如是要启用,需要在每个XML文件中添加以配置该级缓存(相应的实体类要序列化)
sqlSessionFactory级别的缓存,可以被所有的sqlSession共享
执行流程:
通过SqlSession查询数据时,这些数据将会放到当前的一级缓存中;如果当前会话关闭,则一级缓存中的数据会被保存到二级缓存中,此后新的sqlSession将会从二级缓存中查找数据;
二级缓存清理:
select标签的useCache属性用于设置是否使用二级缓存,默认时true;
增删改查标签均有flushCache属性,其中增删改默认true,即sql执行以后,会同时清空一级二级缓存,查询默认false。
总结:
mybatis的一级缓存和二级缓存都是基于本地,分布式的环境下必然会出现脏。
二级缓存可以通过实现Cache接口,来集中管理缓存,避免脏读,但是有一定的开发成本,并且在多表查询时,使用不当既有可能会出现脏读数据。