17. Mybatis 查询操作-select


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 的一个
<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">
  
</insert>

1.2 返回值
Mybatis 的查询结果集封装着实很强大, 同一个sql片段, 会根据接口方法定义时返回值的不同, 而做自动封装. 笔者介绍一下常见的几种返回类型.

返回值类型    返回描述
String/Integer/Float…    返回单个的基本类型, Mybatis为基本类型内置了别名, resultType 可直接写别名.
List/Set<String/Integer…>    返回基本类型的集合
VO    单个的java 类对象, 不局限于PO, VO, DTO 等均可
List/Set    java 对象集合
Map<String, Object>    单个对象的字段名, 与值构成的Map
Map<Object, VO>    单个对象的某个属性和对象构成key=value 键值对的map, 如 Map<PK, PO>; 需要注意两点: 第一, 需要借助于@Mapper 注解指定key的字段; 第二, 如果PK类型指定为Long, 那么当id较小时, 便会返回Integer, 而报错.
2. Select 标签返回举例
2.1 Mapper 方法定义

public interface DepartmentMapper {

    // 返回单个基本类型
    String queryDepartmentName(Long id);

    // 返回基本类型集合
    List<Long> queryAllIds();

    // 返回单一对象
    DepartmentPO findById(Long id);

    // 返回对象集合
    List<DepartmentPO> queryAll();

    // 返回单个对象的所有属性
    Map<String , Object> queryProperties(Long id);

    // 返回id和对象组成的map
    //  -需要通过@MapKey 注解指定map中key从哪个字段获取
    //  -当key类型设置为Long时, 一般会返回Integer, 会报错
    @MapKey("id")
    Map<Object, DepartmentPO> queryMap();
}

2.2 sql 片段
<!-- 命名空间使用对应的Mapper类全限定名称 -->
<mapper namespace="org.zongf.learn.mybatis3.l01.mapper.DepartmentMapper">

    <!-- 返回单个基本类型 -->
    <select id="queryDepartmentName" resultType="string">
        select name from t_department where id = #{id};
    </select>

    <!-- 返回基本类型集合 -->
    <select id="queryAllIds" resultType="long">
        select id from t_department;
    </select>

    <!-- 返回单一对象 -->
    <select id="findById" resultType="DepartmentPO">
        select * from t_department where id = #{id};
    </select>

    <!-- 返回对象集合 -->
    <select id="queryAll" resultType="DepartmentPO">
        select * from t_department;
    </select>

    <!-- 返回单个对象的所有属性 -->
    <select id="queryProperties" resultType="map">
        select * from t_department where id = #{id};
    </select>

    <!-- 返回id和对象组成的map -->
    <select id="queryMap" resultType="DepartmentPO">
        select * from t_department;
    </select>

</mapper>

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<Long> ids = this.departmentMapper.queryAllIds();
        ids.forEach(System.out::println);
    }

    // 返回单一对象
    @Test
    public void findById(){
        DepartmentPO dep = this.departmentMapper.findById(1L);
        System.out.println(dep);
    }

    // 返回对象集合
    @Test
    public void queryAll(){
        List<DepartmentPO> departmentPOS = this.departmentMapper.queryAll();
        departmentPOS.forEach(System.out::println);
    }

    // 返回单个对象的所有属性
    @Test
    public void queryProperties(){
        Map<String, Object> properties = this.departmentMapper.queryProperties(1L);
        System.out.println(properties);
        properties.forEach((key,val)->{
            System.out.println(key + "=" + val);
        });
    }

    // 返回id和对象组成的map
    @Test
    public void queryMap(){
        Map<Object, DepartmentPO> map = this.departmentMapper.queryMap();
        map.forEach((key, val)->{
            System.out.println(key + "=" + val);
        });
    }
}

3. 缓存测试
缓存测试需要主要通过观察日志, 看相同条件的第二次查询是否发送sql.

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);
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值