1. select 标签
select 标签是用于定义插入语句的, select 标签是Mybatis 中最复杂的标签了.
1.1 常用属性
select 的属性和子标签比较多, 常用属性有:
id: sql 片段在命名空间内的唯一标识. 和mapper 中方法名保持一致
useGeneratedKeys: 是否回填自动生成的主键
keyProperty: 主键回填到哪个属性
keyColumn: 主键回填的字段名, 可省略
parameterType: 参数类型, 通常都可以省略.
flushCache: 是否刷新(清空)一级缓存和二级缓存, 默认为false.
useCache: 是否将查询结果存入二级缓存, 默认为true. 对一级缓存无效.
timeout: sql 执行超时时间, 默认未设置, 由数据库驱动决定.
resultType: 指定结果集中每一行的封装类型, 支持自动封装为java中定义的类对象. 默认使用类的全限定名称, 配置别名后, 支持类的简单名称.
resultMap: 指定结果集中每一行的封装类型, 是使用resultMap 标签定义的类型.
statementType: 执行sql时使用的statement类型, 默认为PREPARED. 可选值为:STATEMENT,PREPARED 或 CALLABLE 的一个
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20">
1.2 返回值
Mybatis 的查询结果集封装着实很强大, 同一个sql片段, 会根据接口方法定义时返回值的不同, 而做自动封装. 笔者介绍一下常见的几种返回类型.
返回值类型 返回描述
String/Integer/Float… 返回单个的基本类型, Mybatis为基本类型内置了别名, resultType 可直接写别名.
List/Set
VO 单个的java 类对象, 不局限于PO, VO, DTO 等均可
List/Set java 对象集合
Map
Map
public interface DepartmentMapper {
// 返回单个基本类型
String queryDepartmentName(Long id);
// 返回基本类型集合
List
// 返回单一对象
DepartmentPO findById(Long id);
// 返回对象集合
List
// 返回单个对象的所有属性
Map
// 返回id和对象组成的map
// -需要通过@MapKey 注解指定map中key从哪个字段获取
// -当key类型设置为Long时, 一般会返回Integer, 会报错
@MapKey("id")
Map
2.3 测试类
public class Test_DepartmentMapper {
DepartmentMapper departmentMapper;
@Before
public void setUp(){
departmentMapper = SqlSessionUtil.getMapper(DepartmentMapper.class, false);
}
// 返回单个基本类型
@Test
public void queryDepartmentName(){
String departmentName = this.departmentMapper.queryDepartmentName(1L);
System.out.println(departmentName);
}
// 返回基本类型集合
@Test
public void queryAllIds(){
List
ids.forEach(System.out::println);
}
// 返回单一对象
@Test
public void findById(){
DepartmentPO dep = this.departmentMapper.findById(1L);
System.out.println(dep);
}
// 返回对象集合
@Test
public void queryAll(){
List
departmentPOS.forEach(System.out::println);
}
// 返回单个对象的所有属性
@Test
public void queryProperties(){
Map
System.out.println(properties);
properties.forEach((key,val)->{
System.out.println(key + "=" + val);
});
}
// 返回id和对象组成的map
@Test
public void queryMap(){
Map
3.1 测试一级缓存
影响一级缓存的属性只有flushCache
一级缓存是同一个sqlSession中到缓存, 默认查询结果会存放在一级缓存中.
测试时, 通过设置flushCache=true 来清空缓存
测试结果:
默认条件下: 一级缓存生效, 第二次查询不会发出sql查询日志
修改flushCache=true: 一级缓存被清空, 第二次查询重新发送sql查询日志
@Test
public void testCache() {
// 第一次查询
DepartmentPO dep1 = this.departmentMapper.findById(1L);
System.out.println("开始第二次查询");
DepartmentPO dep2 = this.departmentMapper.findById(1L);
}
3.2 测试二级缓存属性
影响二级缓存的属性有: flushCache 和 useCache
二级缓存默认不开启, 且缓存对象需要实现序列化接口:
DepartmentMapper.xml 开启二级缓存, 即添加标签
DepartmentPO 实现序列化接口: Serializable
测试结果:
默认情况下, 第二次查询不发送sql, 而是从二级缓存中获取
当设置flushCache=true, 或useCache=false时, 第二次查询均会发送sql
@Test
public void testCache2(){
SqlSession sqlSession1 = SqlSessionUtil.openSession(false);
SqlSession sqlSession2 = SqlSessionUtil.openSession(false);
DepartmentMapper depMapper1 = sqlSession1.getMapper(DepartmentMapper.class);
DepartmentMapper depMapper2 = sqlSession2.getMapper(DepartmentMapper.class);
DepartmentPO dep1 = depMapper1.findById(1L);
// sqlSession 关闭时, 会将一级缓存存放到二级缓存中
sqlSession1.close();
System.out.println("开始第二次查询");
DepartmentPO dep2 = depMapper2.findById(1L);
}