mybatis动态sql-注解方式-05

05-mybatis动态sql-注解方式

基于注解方式实现动态sql

动态sql除了支持xml方式以外,还是支持使用纯注解的方式

主要一下四个注解+对应动态sql语句的类文件

  1. @InsertProvider 动态查询SQL语句对应注解

  2. @InsertProvider 动态插入SQL语句对应注解

  3. @UpdateProvider 动态修改SQL语句对应注解

  4. @DeleteProvider 动态删除SQL语句对应注解

允许构建动态 SQL。这些备选的 SQL 注解允许你指定返回 SQL 语句的类和方法,以供运行时执行。(从 MyBatis 3.4.6 开始,可以使用 CharSequence 代替 String 来作为返回类型)。当执行映射语句时,MyBatis 会实例化注解指定的类,并调用注解指定的方法。你可以通过 ProviderContext 传递映射方法接收到的参数、“Mapper interface type” 和 “Mapper method”(仅在 MyBatis 3.4.5 以上支持)作为参数。(MyBatis 3.4 以上支持传入多个参数)属性:typemethodtype 属性用于指定类名。method 用于指定该类的方法名(从版本 3.5.1 开始,可以省略 method 属性,MyBatis 将会使用 ProviderMethodResolver 接口解析方法的具体实现。如果解析失败,MyBatis 将会使用名为 provideSql 的降级实现)。提示 接下来的“SQL 语句构建器”一章将会讨论该话题,以帮助你以更清晰、更便于阅读的方式构建动态 SQL。

问题

Java 程序员面对的最痛苦的事情之一就是在 Java 代码中嵌入 SQL 语句。这通常是因为需要动态生成 SQL 语句,不然我们可以将它们放到外部文件或者存储过程中。如你所见,MyBatis 在 XML 映射中具备强大的 SQL 动态生成能力。但有时,我们还是需要在 Java 代码里构建 SQL 语句。此时,MyBatis 有另外一个特性可以帮到你,让你从处理典型问题中解放出来,比如加号、引号、换行、格式化问题、嵌入条件的逗号管理及 AND 连接。确实,在 Java 代码中动态生成 SQL 代码真的就是一场噩梦

解决方案

MyBatis 3 提供了方便的工具类来帮助解决此问题。借助 SQL 类,我们只需要简单地创建一个实例,并调用它的方法即可生成 SQL 语句。

看面案例:

需求1:通过条件查询

查询姓名带黄的或者 age = 25

Mapper接口:

    /*
     * @SelectProvider(type=UserSqlBuilder.class,method="selectByCondition")
     * @SelectProvider 查询动态sql语句的 注解
     *  type :   编写动态sql语句的类对应的字节码
     *  method : 编写动态sql语句类对应的方法名称
     * 	此方法返回的是一个String字符串,字符串就是拼接sql语句
     */
    @SelectProvider(type = UserSqlBuilder.class,method = "selectByCondition")
    List selectByCondition(User user);

UserSqlBuilder sql构建类:

public class UserSqlBuilder {

    public String selectByCondition(User user){

        // 创建 sql 对象 构建 sql字符串
        SQL sql = new SQL();

        // select *
        sql.SELECT("*");

        // select * from t_user
        sql.FROM("t_user");

        // select * from t_user where name like #{name}
        if (user.getName() != null) {
            sql.WHERE("name like #{name}");
        }

        //默认多条件是AND ,可以自己制定成 OR
        if (user.getAge() != null) {
            sql.OR();
            sql.WHERE("age = #{age}");
        }
        return sql.toString();
    }

}

测试代码sql的构建:

  @Test
    public void testSelectConditionSQLBuilder(){

        UserSqlBuilder userSqlBuilder = new UserSqlBuilder();

        User u = new User();
        u.setName("%黄%");
        u.setAge(25);
        String s = userSqlBuilder.selectByCondition(u);
        System.out.println(s);

    }

查看日志:

SELECT *
FROM t_user
WHERE (name like #{name}) 
OR (age = #{age})

测试代码:

    @Test
    public void testSelectCondition(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
        User u = new User();
        u.setName("%黄%");
        u.setAge(25);
        List users = mapper.selectByCondition(u);
        System.out.println(users);
        SqlSessionUtils.close(sqlSession);

    }

日志:

DEBUG [main] - ==>  Preparing: SELECT * FROM t_user WHERE (name like ?) OR (age = ?) 
DEBUG [main] - ==> Parameters: %黄%(String), 25(Integer)
TRACE [main] - <==    Columns: id, name, pwd, age
TRACE [main] - <==        Row: 4, 洪七公, aaa, 25
TRACE [main] - <==        Row: 5, 黄蓉, 阿里巴巴, 38
TRACE [main] - <==        Row: 6, 王语嫣, abc, 25
TRACE [main] - <==        Row: 7, 周芷若, 1234, 25
TRACE [main] - <==        Row: 8, 黄药师, 1234, 66
DEBUG [main] - <==      Total: 5

需求2:通过条件查询统计结果

Mapper接口:

Long selectTotalByCondition(User user);

UserSqlBuilder sql构建类:

 public String selectTotalByCondition(User user){

        SQL sql = new SQL();

        // select *
        sql.SELECT("count(*) ");

        // select * from t_user
        sql.FROM("t_user");

        // select * from t_user  where name like name = #{name}
        if (user.getName() != null) {
            sql.WHERE(" name like name = #{name}");
        }
        if (user.getAge() != null) {

           // select * from t_user  where name like name = #{name} or age = #{age}
            sql.OR();
            sql.WHERE("age = #{age}");
        }

        return sql.toString();
    }

测试sql构建:

 @Test
    public void testselectTotalByConditionSqlBuilder() {

        UserSqlBuilder sqlBuilder = new UserSqlBuilder();

        User u = new User();
        u.setName("%黄%");
        u.setAge(25);
        String s = sqlBuilder.selectTotalByCondition(u);
        System.out.println(s);
    }

日志:

SELECT count(*) 
FROM t_user
WHERE ( name like name = #{name}) 
OR (age = #{age})

测试代码:

    @Test
    public void testSelectTotalByCondition(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
        User u = new User();
        u.setName("%黄%");
        u.setAge(25);
        Long aLong = mapper.selectTotalByCondition(u);
        System.out.println(aLong);
        SqlSessionUtils.close(sqlSession);
    }

日志:

DEBUG [main] - ==>  Preparing: SELECT count(*) FROM t_user WHERE ( name like name = ?) OR (age = ?) 
DEBUG [main] - ==> Parameters: %黄%(String), 25(Integer)
TRACE [main] - <==    Columns: count(*)
TRACE [main] - <==        Row: 3
DEBUG [main] - <==      Total: 1
3

需求3:修改用户

mapper接口:

@UpdateProvider(type = UserSqlBuilder.class, method = "updateUserByNotNull")
int updateUserByNotNull(User user);

UserSqlBuilder sql构建类:


    public String updateUserByNotNull(User user){

        SQL sql = new SQL();

        // update t_user
        sql.UPDATE("t_user");

        // update t_user set name = #{name}
        if (user.getName() != null) { // 不要自己在后面加 ,
            sql.SET("name = #{name}");

        }
        // update t_user set name = #{name},age = #{age}
        if (user.getAge() != null) {
            sql.SET("age = #{age}");
        }
        // update t_user set name = #{name},age = #{age},pwd = #{pwd}
        if (user.getPwd() != null) {
            sql.SET("pwd = #{pwd}");
        }

        // update t_user set name = #{name},age = #{age},pwd = #{pwd} where id = #{id}
        sql.WHERE("id = #{id}");

        return sql.toString();
    }

sql构建的测试:

    @Test
    public void testUpdateSqlBuilder() {

        UserSqlBuilder sqlBuilder = new UserSqlBuilder();

        User u = new User();
        u.setName("紫衫龙王");
        u.setAge(25);
        u.setId(4);
        String s = sqlBuilder.updateUserByNotNull(u);
        System.out.println(s);
    }

日志:

UPDATE t_user
SET name = #{name}, age = #{age}
WHERE (id = #{id})

测试代码:

    @Test
    public void testUpdate(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
        User u = new User();
        u.setName("紫衫龙王");
        u.setAge(25);
        u.setId(8);
        int i= mapper.updateUserByNotNull(u);

        sqlSession.commit();

        System.out.println(i);

        SqlSessionUtils.close(sqlSession);
    }

日志:

DEBUG [main] - ==>  Preparing: UPDATE t_user SET name = ?, age = ? WHERE (id = ?) 
DEBUG [main] - ==> Parameters: 紫衫龙王(String), 25(Integer), 8(Integer)
DEBUG [main] - <==    Updates: 1
1

需求4:通过多个id删除数据

mapper的代码:

 @DeleteProvider(type = UserSqlBuilder.class,method = "deleteUsers")
 int deleteUsers(@Param("list") List list);

UserSqlBuilder sql构建类:


    public String deleteUsers(@Param("list") List list){

        SQL sql = new SQL();

        // delete from t_user
        sql.DELETE_FROM("t_user");

		// 没有拼接的方法 只能自己写字符串拼接 
        // 拼接条件    (#{list[0]},#{list[1]},#{list[2]})
        StringBuilder sb = new StringBuilder();

        sb.append("(");
        for (int i = 0; i < list.size(); i++) {
            sb.append("#{list["+i+"]},");
        }

        // 删除  字符串拼接最后一个 ,
        sb.deleteCharAt(sb.length() - 1);

        sb.append(")");
        
        // delete from t_user where id in (1,2,3);
        sql.WHERE("id in " +sb.toString());

        return sql.toString();

    }

sql测试代码:

   @Test
    public void testDeleteSqlBuilder() {

        UserSqlBuilder sqlBuilder = new UserSqlBuilder();

         List list =new ArrayList<>();
         list.add(1);
         list.add(4);
         list.add(5);

        sqlBuilder.deleteUsers(list);
        String s = sqlBuilder.deleteUsers(list);
        System.out.println(s);
    }

日志:

DELETE FROM t_user
WHERE (id in (#{list[0]},#{list[1]},#{list[2]}))

测试代码:

   @Test
    public void testSelectList(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List list =new ArrayList<>();

        list.add(1);
        list.add(4);
        list.add(5);
        List users = mapper.selectList(list);
        System.out.println(users);
        SqlSessionUtils.close(sqlSession);
    }

日志:

DEBUG [main] - ==>  Preparing: DELETE FROM t_user WHERE (id in (?,?,?)) 
DEBUG [main] - ==> Parameters: 1(Integer), 4(Integer), 5(Integer)
DEBUG [main] - <==    Updates: 3
3

需求5:批量插入

mapper接口:

@InsertProvider(type = UserSqlBuilder.class,method = "insertUsers")
int insertUsers(@Param("users")List list);

UserSqlBuilder sql构建类:


    public String insertUsers(@Param("users")List list){

        SQL sql = new SQL();

        // insert into t_user(name,pwd,age) values (?,?,?)

        StringBuilder sb = new StringBuilder();

        sb.append("insert into t_user(name,pwd,age) values ");

        for (int i = 0; i < list.size(); i++) {

            sb.append("(");
            sb.append("#{users["+i+"].name},");
            sb.append("#{users["+i+"].pwd},");
            sb.append("#{users["+i+"].age}");

            sb.append("),");
        }

        sb.deleteCharAt(sb.length() - 1);

        return sb.toString();
    }

sql构建测试代码:

    @Test
    public void testInsertSqlBuilder() {

        UserSqlBuilder sqlBuilder = new UserSqlBuilder();

        List list =new ArrayList<>();

        list.add(new User(null,"梅超风","123",30));
        list.add(new User(null,"曲正风","123",40));
        list.add(new User(null,"空见","123",35));

        String s = sqlBuilder.insertUsers(list);

        System.out.println(s);
    }

测试代码:

    @Test
    public void testInsertUsers(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);

        List list =new ArrayList<>();

        list.add(new User(null,"梅超风","123",30));
        list.add(new User(null,"曲正风","123",40));
        list.add(new User(null,"空见","123",35));

        mapper.insertUsers(list);
        sqlSession.commit();
        SqlSessionUtils.close(sqlSession);
    }

日志:

DEBUG [main] - ==>  Preparing: insert into t_user(name,pwd,age) values (?,?,?),(?,?,?),(?,?,?) 
DEBUG [main] - ==> Parameters: 梅超风(String), 123(String), 30(Integer), 曲正风(String), 123(String), 40(Integer), 空见(String), 123(String), 35(Integer)
DEBUG [main] - <==    Updates: 3

你可能感兴趣的:(框架,mybatis,java)