Mybatis 注解方式动态SQL映射

MyBatis 提供了XML配置和注解配置两种方式,这里介绍注解配置方式。

一、Mybatis常用注解

注解释义
@Select映射查询的SQL语句
@SelectProviderSelect的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。
@ Insert映射插入的SQL语句
@InsertProviderInsert的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。
@Update映射更新的SQL语句
@UpdateProviderUpdate的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。
@Delete映射删除的SQL语句
@DeleteProviderDelete的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。
@Results多个结果集映射列表
@Result在列和属性之间的单独结果映射
@Options提供配置选项的附加值
@One复杂类型的单独属性值映射。与XML配置中的 < association > 类似
@Many复杂类型结合属性映射 。与XML配置中的 < collection> 类似
@Param当映射器需要多哥参数是,可以用于给每个参数取一个名字。否则多参数默认会以他们的顺序位置和sql语句表达式中的顺序进行映射。

二、Sql语句的直接映射:

1. 举例

表结构如下。

在这里插入图片描述

定义一个实体类如下

// 必须加上改注解,否则会报错
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})
public class User implements Serializable{
    private int id;
    private String name;
    private String pwd;
    private int parentId;
    private User parentUser;
    private List<User> sonUsers;

    public int getParentId() {
        return parentId;
    }

    public void setParentId(int parentId) {
        this.parentId = parentId;
    }

    public User getParentUser() {
        return parentUser;
    }

    public void setParentUser(User parentUser) {
        this.parentUser = parentUser;
    }

    public List<User> getSonUsers() {
        return sonUsers;
    }

    public void setSonUsers(List<User> sonUsers) {
        this.sonUsers = sonUsers;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

}

Mapper文件如下:

@Mapper
public interface UserMapper {
    /**
     *  查找用户,包括其上下节点
     * @param id
     * @return
     */
    @Select("select * from user where id = #{id}")
    @Results({
            // id = true 说明他是主键 。User类中的id属性对应表中的id列。下同。
            // 这是为了指定别名,其实名称相同不指定也可以
            @Result(id = true, column = "id", property = "id"),
            @Result(column = "pwd", property = "pwd"),
            @Result(column = "name", property = "name"),
            @Result(column = "name", property = "name"),
            // @Many 则将通过 selectSonUser 方法查询到其子类用户。
            // column = "id" 作用 是 对selectSonUser方法来说传入的参数是selectUser 锁查询出来的 id 列
            // fetchType 指定懒加载
            // 即User类中的sonUsers 属性从selectSonUser中查询出来,selectSonUser传入的参数是当前的id列
            @Result(column = "id", property = "sonUsers", many = @Many(
                    select = "com.kingfish.dao.UserMapper.selectSonUser", fetchType = FetchType.LAZY
            )),
            // @One 则将通过 selectParentUser 方法查询到其父类用户
            @Result(column = "parentId", property = "parentUser", one = @One(
                    select = "com.kingfish.dao.UserMapper.selectParentUser", fetchType = FetchType.LAZY
            ))

    })
    List<User> selectUser(int id);

    /**
     *  查找儿子节点
     * @param id
     * @return
     */
    @Select("select * from user where parentId = #{id}")
    @Results({
            @Result(column = "id", property = "sonUsers", many = @Many(
                    select = "com.kingfish.dao.UserMapper.selectSonUser", fetchType = FetchType.LAZY
            )),
            @Result(column = "parentId", property = "parentUser", one = @One(
                    select = "com.kingfish.dao.UserMapper.selectParentUser", fetchType = FetchType.LAZY
            ))
    })
    List<User> selectSonUser(int id);

    /**
     * 查找父节点
     * @param parentId
     * @return
     */
    @Select("select * from user where id = #{parentId}")
    User selectParentUser(int parentId);
}

访问接口调用selectUser方法.。得到结果如下。

在这里插入图片描述

插入数据演示:

Mapper映射
在这里插入图片描述

待插入数据
在这里插入图片描述
插入后结果
在这里插入图片描述

更新和删除类似,下面不再演示。

2. MyBatis一对多,一对一关系映射属性

association 的属性具体意思
column表示数据库表的列名。在子查询中会将父表中的该列名的值作为参数传递到子查询中
property表示返回的类型的属性名,属性名为user
javaType表示表示该属性对应的类型,本例是一个User类型
select表示一条查询语句,将查询到的数据封装到property指定的属性中
fetchType取值有eager和lazy。分别代表立即加载和延迟加载。主要为性能考虑,如果此次查询中一定会查询userList可以设置为立即加载。如果不一定使用,可以使用延迟加载。正常情况下,都应设为lazy
collection 的属性具体意思
column表示数据库表的列名。在子查询中会将父表中的该列名的值作为参数传递到子查询中
property表示返回的类型的属性名,属性名为user
javaType表示表示该属性对应的类型,本例是一个User类型
ofTypeList集合中的实例对象类型
select表示一条查询语句,将查询到的数据封装到property指定的属性中
fetchType取值有eager和lazy。分别代表立即加载和延迟加载。主要为性能考虑,如果此次查询中一定会查询userList可以设置为立即加载。如果不一定使用,可以使用延迟加载。正常情况下,都应设为lazy

要延迟加载时,必须要在mybaitis配置文件中加上

		<!-  开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"></setting>
        <setting name="aggressiveLazyLoading" value="false"></setting>

具体如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!--使用jdbc的getGeneratekeys获取自增主键值-->
        <setting name="useGeneratedKeys" value="true"/>
        <!--使用列别名替换别名  默认true-->
        <setting name="useColumnLabel" value="true"/>
        <!--开启驼峰命名转换Table:create_time到 Entity(createTime)-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 打印日志 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
		<!-  开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"></setting>
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>
    <typeAliases>
        <typeAlias type="com.kingfish.pojo.User" alias="user"></typeAlias>
    </typeAliases>
</configuration>

三、Sql语句的动态映射

Mybatis的注解也支持动态,同时提供了对应的一些SQL类的常用方法。基本覆盖了日常使用。
Sql类提供的方法:
在这里插入图片描述
动态sql provider方法可以接收以下参数:

  • 无参数
  • java对象
  • java.util.Map
  1. 需要创建一个动态Sql类。并创建对应生成的sql方法,这里随便创建了一个。
public class UserProvider {
	// 将会拼接生成对应的sql语句。可以通过代码来模拟XML中的各种判断情况,实现动态sql
    public String selectUser(Integer id) {
        return new SQL() {
            {
                SELECT("*");
                FROM("user");
                if (id != null) {
                    WHERE("id = #{id}");
                }
            }
        }.toString();
    }

}

改造一下刚才的selectUser方法。将使用 @Select(注释掉,使用 @SelectProvider 注解
@SelectProvider : type 属性指定了动态sql类,method指定了sql类里面对应词查询的方法。

//    @Select("select * from user where id = #{id}")
    @SelectProvider(type = UserProvider.class, method = "selectUser")
    @Results({
            // id = true 说明他是主键 。User类中的id属性对应表中的id列。下同。
            // 这是为了指定别名,其实名称相同不指定也可以
            @Result(id = true, column = "id", property = "id"),
            @Result(column = "pwd", property = "pwd"),
            @Result(column = "name", property = "name"),
            @Result(column = "name", property = "name"),
            // @Many 则将通过 selectSonUser 方法查询到其子类用户。
            // column = "id" 作用 是 对selectSonUser方法来说传入的参数是selectUser 锁查询出来的 id 列
            // fetchType 指定懒加载
            @Result(column = "id", property = "sonUsers", many = @Many(
                    select = "com.kingfish.dao.UserMapper.selectSonUser", fetchType = FetchType.LAZY
            )),
            // @One 则将通过 selectParentUser 方法查询到其父类用户
            @Result(column = "parentId", property = "parentUser", one = @One(
                    select = "com.kingfish.dao.UserMapper.selectParentUser", fetchType = FetchType.LAZY
            ))

    })

测试没问题。
在这里插入图片描述

补: 一对多的XML形式映射(仅用举例)

    <resultMap id="loadUserByUsernameResultMap" type="com.example.common.config.security.MyUserDetails">
        <collection property="roleIds" select="com.example.dao.UserRoleMapper.selectRoleByUserId"
                    column="user_id" ></collection>
    </resultMap>

    <select id="loadUserByUsername" resultMap="loadUserByUsernameResultMap">
        select
        <include refid="Base_Column_List"></include>
        from user u
        where u.user_id = #{username};
    </select>

以上:内容部分参考《Spring + Mybatis 企业应用实战》。如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫吻鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值