@Select注解

在 tk.mybatis.simple.mapper.RoleMapper 中添加如下注解方法。

@Select({"select id,role_name roleName,enabled,create_by createBy,create_time createTime",
    "from sys_role ",
    "where id = #{id}"})
SysRole selectById(Long id);

也可以写成下面这种形式。

@Select({"select id,role_name roleName,enabled,create_by createBy,create_time createTime from sys_role where id = #{id}"})
SysRole selectById(Long id);

为了使代码更适合阅读,本章对代码进行了合理的换行。对于过长的字符串,虽然分成了多行,但大家在书写时仍需按照规范将字符串双引号范围内的内容写在同一行。

使用注解就是在接口方法基础上添加需要的注解,并写上相应的 SQL 语句。@Select、@Insert、@Update 和 @Delete 这 4 个基本注解的参数可以是字符串数组类型,也可以是字符串类型。

使用注解方式同样需要考虑表字段和 Java 属性字段映射的问题,在第 2 章中已经讲过 XML 方式是如何实现字段映射的,接下来看一下注解方式是如何实现的。第一种是通过 SQL 语句使用别名来实现,上面的例子中已经使用过。除此之外还有另外两种方式分别是使用 mapUnderscoreToCamelCase 配置以及使用 resultMap 方式,下面详细说明。

使用mapUnderscoreToCamelCase配置

mapUnderscoreToCamelCase 配置方式可以参考 2.3 节 select 用法的相关内容。

使用这种配置方式不需要手动指定别名,MyBatis 字段按照 “下画线转驼峰” 的方式自动映射,@Select 注解中的 SQL 可以写成如下两种方式。

select * from sys_role where id=#{id}

或者

select id,role_name,enabled,create_by,create_time from sys_role where id = #{id}

使用resultMap方式

XML 中的 resultMap 元素有一个对应的 Java 注解 @Results,使用这个注解来实现属性映射,新增一个 selectById2 方法,代码如下。

@Results(id = "baseResultMap", value = {
        @Result(property = "id", column = "id", id = true),
        @Result(property = "roleName", column = "role_name"),
        @Result(property = "enabled", column = "enabled"),
        @Result(property = "createBy", column = "create_by"),
        @Result(property = "createTime", column = "create_time"),
})
@Select({"select id,role_name,enabled,create_by,create_time from sys_role where id = #{id}"})
SysRole selectById2(Long id);

这里的 @Result 注解对应着 XML 文件中的 <result> 元素,而参数中写上 id=true 时就对应 <id> 元素。

使用 @Results 注解的时候,大家可能会担心,是不是要在每一个方法上都这么写。在 MyBatis 3.3.0 及以前版本中,注解定义的 @Results 不能共用,使用很不方便,确实是要在每一个方法上都写一遍。但从 MyBatis 3.3.1 版本开始,@Results 注解增加了一个 id 属性,设置了 id 属性后,就可以通过 id 属性引用同一个 @Results 配置了,示例代码如下。

@Results(id = "roleResultMap", value = {
        @Result(property = "id", column = "id", id = true),
        // 其它...
})

如何引用这个 @Results 呢?新增一个 selectAll 方法,代码如下。

@ResultMap("roleResultMap")
@Select("select * from sys_role")
List<SysRole> selectAll();

使用 @ResultMap 注解引用即可,注解的参数值就是上面代码中设置的 id 的值,当配合着使用 XML 方式的时候,还可以是 XML 中 <resultMap> 元素的 id 属性值。

在 RoleMapperTest 中写出以上示例方法的测试方法。selectById 方法的测试代码如下。

@Test
public void testSelectById(){
    // 获取 sqlSession
    SqlSession sqlSession = getSqlSession();
    try {
        // 获取 RoleMapper 接口
        RoleMapper roleMapper = (RoleMapper)sqlSession.getMapper(RoleMapper.class);
        // 调用 selectById 方法,查询 id = 1 的角色
        SysRole role = roleMapper.selectById(1L);
        // role 不为空
        Assert.assertNotNull(role);
        // roleName = 管理员
        Assert.assertEquals("管理员", role.getRoleName());
    } finally {
        // 不要忘记关闭 sqlSession
        sqlSession.close();
    }
}

测试输出日志如下。

selectById2 方法的测试代码如下。

@Test
public void testSelectById2(){
    // 获取 sqlSession
    SqlSession sqlSession = getSqlSession();
    try {
        // 获取 RoleMapper 接口
        RoleMapper roleMapper = (RoleMapper)sqlSession.getMapper(RoleMapper.class);
        // 调用 selectById2 方法,查询 id = 1 的角色
        SysRole role = roleMapper.selectById2(1L);
        // role 不为空
        Assert.assertNotNull(role);
        // roleName = 管理员
        Assert.assertEquals("管理员", role.getRoleName());
    } finally {
        // 不要忘记关闭 sqlSession
        sqlSession.close();
    }
}

测试输出日志如下。

两个方法的区别是,后者的 SQL 中没有别名,需要通过 @Result 注解配置映射。

selectAll 方法的测试代码如下。

@Test
public void testSelectAll(){
    SqlSession sqlSession = getSqlSession();
    try {
        RoleMapper roleMapper = (RoleMapper)sqlSession.getMapper(RoleMapper.class);
        // 调用 selectAll 方法查询所有角色
        List<SysRole> role = roleMapper.selectAll();
        // 结果不为空
        Assert.assertNotNull(role);
        // 角色数量大于0个
        Assert.assertTrue(role.size() > 0);
        // 验证下划线字段是否映射成功
        Assert.assertNotNull(roleList.get(0).getRoleName());
    } finally {
        // 不要忘记关闭 sqlSession
        sqlSession.close();
    }
}

测试输出日志如下。

以上是 @Select 注解的使用方式,可以发现,注解方式和 XML 方式可以实现相同的功能,具有相同含义的配置。