Code前端首页关于Code前端联系我们

MyBatis教程:标注方法的基本使用

terry 2年前 (2023-09-25) 阅读数 48 #后端开发

1. @Select注解

1.1 使用SQL语句设置别名方法

假设现在有一个需求:根据id查询角色信息。如何通过注释来实现这一点?

首先在SysRoleMapper接口中添加如下方法:

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

上面的两个方法都是传递字符串数组的形式。我们还可以使用直接字符串传递。形式:

@Select("SELECT id,role_name roleName,enabled,create_by createBy,create_time createTime FROM sys_role WHERE id = #{id}")
SysRole selectById(Long id);

使用注解方式时,还必须考虑表字段和Java属性字段的映射。注释方法的使用有3种方式。

第一种方式是通过SQL语句设置别名。上面的代码就使用了这个方法。

1.2 使用mapUnderscoreToCamelCase配置方法

打开我们之前在src/main/resources文件夹中创建的mybatis-config.xml文件,添加以下配置:

<settings>
    <!--其他配置-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

此配置打开后,MyBatis按照“下划线转驼峰”规则自动分配,即数据库列角色名自动转换为角色名属性。

目前上述代码可以改成:

@Select("SELECT id,role_name,enabled,create_by,create_time FROM sys_role WHERE id = #{id}")
SysRole selectById(Long id);

虽然也可以写成下面的格式,但不建议这样使用:

@Select("SELECT * FROM sys_role WHERE id = #{id}")
SysRole selectById(Long id);

1.3 使用resultMap方法

xml中我们使用resultMap来配置映射:

<resultMap id="sysUserMap" type="com.zwwhnly.mybatisaction.model.SysUser">
    <id property="id" column="id"/>
    <result property="userName" column="user_name"/>
    <result property="userPassword" column="user_password"/>
    <result property="userEmail" column="user_email"/>
    <result property="userInfo" column="user_info"/>
    <result property="headImg" column="head_img" jdbcType="BLOB"/>
    <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap>

注解模式下有一个对应的注解@Results来配置映射:

@Results({
        @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);

代码简单解释:

1)@Results注解与xml中的resultMap标签匹配

2) @Result 匹配xml中的结果标签

3)@Result(property = "id", column = "id", id = true ) 对应

有人可能会奇怪:我在xml中给resultMap设置了一个id,这样我就可以重新创建resultMap可以使用了。注释方法支持这个吗?

带着这个问题尝试修改代码:

@Results(id = "roleResultMap", 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);

结果发现代码构造错误,找不到id属性。

MyBatis教程:注解方式的基本用法

按Ctrl+B,找到@Results的源码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Results {
    Result[] value() default {};
}

从源码中我们可以看到这个注解没有id属性。我们应该为每个方法添加重复分配吗?

答案当然是否定的,但是在MyBatis 3.3.0及之前的版本中,注解定义的@Results不能共享,必须写在每个方法中。但从 MyBatis 3.3.1 版本开始,@Results 注解添加了 id 属性。设置 id 属性后,您可以通过 id 属性引用相同的 @Results 配置。

看过之前博客的读者可能知道,我们MyBatis使用的是3.3.0版本,所以不支持设置id属性,哈哈。

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.3.0</version>
</dependency>

将MyBatis的版本改为3.3.1(如果没有设置自动导入更改,则需要手动点击Import Changes):

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.3.1</version>
</dependency>

你会看到上面的代码,原本编译时报错时间,可以编译通过。

目前@Results的源码如下。相比之前的代码,增加了id属性:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Results {
    String id() default "";

    Result[] value() default {};
}

如何引用这个@Results注解?参见如下代码:

@ResultMap("roleResultMap")
@Select("SELECT * FROM sys_role")
List<SysRole> selectAll();

注意:与XML一起使用时,这里引用的id值也可以是XML中resultMap元素的id属性值。

为了避免文章太长,这里不再贴出这三个方法的单元测试代码和输出日志。相信看过前面几篇博客的读者已经可以自己编写单元测试代码了,大家也可以参考一下。从文末源码地址下载源码。 ? ,代码如下:

@Insert({"INSERT INTO sys_role(role_name, enabled, create_by, create_time) ",
        "VALUES (#{roleName},#{enabled},#{createBy},#{createTime,jdbcType=TIMESTAMP})"})
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertUseGeneratedKeys(SysRole sysRole);

和XML中的使用方式类似,@Options(useGeneeratedKeys = true, keyProperty = "id")相当于u​​seGeneeratedKeys="true" keyProperty= XML 中的“id”

2.3 返回非自增主键

在上一篇博客中我们知道selectKey既支持自增主键的数据库,如MySql,也支持非自增主键的数据库,如甲骨文。 XML 的写法如下:

<selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER">
    SELECT LAST_INSERT_ID()
</selectKey>

那么如何使用注解来实现呢?代码如下:

@Insert({"INSERT INTO sys_role(role_name, enabled, create_by, create_time) ",
        "VALUES (#{roleName},#{enabled},#{createBy},#{createTime,jdbcType=TIMESTAMP})"})
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyColumn = "id", keyProperty = "id", resultType = Long.class, before = false)
int insertUseSelectKey(SysRole sysRole);

before = false 相当于XML中的order="AFTRE",这是MySql数据库的配置。

before = true 相当于 Oracle 数据库配置 XML 中的 order="BEFORE"。

注:不同的数据库有不同的指令值。以上值适用于MySql数据库。请注意使用其他类型数据库时的变化。 ? 。提供者注释​​MyBatis 提供了 4 种类型的提供者注释,即 @SelectProvider、@InsertProvider、@UpdateProvider 和 @DeleteProvider。

下面以@SelectProvider为例来学习如何使用Provider注解。

首先在com.zwwhnly.mybatisaction.mapper包下创建如下类:

package com.zwwhnly.mybatisaction.mapper;

import org.apache.ibatis.jdbc.SQL;

public class SysPrivilegeProvider {
    public String selectById(final Long id) {
        return new SQL() {
            {
                SELECT("id,privilege_name,privilege_url");
                FROM("sys_privilege");
                WHERE("id = #{id}");
            }
        }.toString();
    }
}

上面的代码也可以写成如下:

public String selectById(final Long id) {
    return "SELECT id,privilege_name,privilege_url FROM sys_privilege WHERE id = #{id}";
}

然后在SysPrivilegeProvider接口中添加如下方法:

@SelectProvider(type = SysPrivilegeProvider.class, method = "selectById")
SysPrivilege selectById(Long id);

最后在src/test/ Java下com.zwwhnly.mybatisaction.mapper包下新建测试类SysPrivilegeMapperTest:

package com.zwwhnly.mybatisaction.mapper;

import com.zwwhnly.mybatisaction.model.SysPrivilege;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;

public class SysPrivilegeMapperTest extends BaseMapperTest {
    @Test
    public void testSelectById() {
        SqlSession sqlSession = getSqlSession();

        try {
            SysPrivilegeMapper sysPrivilegeMapper = sqlSession.getMapper(SysPrivilegeMapper.class);
            SysPrivilege sysPrivilege = sysPrivilegeMapper.selectById(1L);

            Assert.assertNotNull(sysPrivilege);
            Assert.assertEquals("用户管理", sysPrivilege.getPrivilegeName());
        } finally {
            sqlSession.close();
        }
    }
}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - = => 准备: SELECT id,privilege_name,privilege_url FROM sys_privilege WHERE (id = ?)
DEBUG [main] - ==> 参数: 1(Long)

TRACE [main] -

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门