首页 > 数据库 >Mybatis实现@Select@Update等注解动态查询或更新SQL语句

Mybatis实现@Select@Update等注解动态查询或更新SQL语句

时间:2022-10-11 17:56:55浏览次数:70  
标签:script matcher org sql Update apache SQL Mybatis import

通过自己实现LanguageDriver,在服务器启动的时候,就会将我们自定义的标签解析为动态SQL语句。
例如,写个构造update in 的动态sql更新,代码如下:
package com.ljw.web.common.mybatis;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** 构造update in 动态sql更新 */
@Slf4j
/** @author seqwait */
public class LanguageDriverUpdateIn extends XMLLanguageDriver implements LanguageDriver {

  private final Pattern pattern = Pattern.compile("\\(#\\{(\\w+)\\}\\)");

  @Override
  public SqlSource createSqlSource(
      Configuration configuration, String script, Class<?> parameterType) {
    Matcher matcher = pattern.matcher(script);
    if (matcher.find()) {
      script =
          matcher.replaceAll(
              "(<foreach collection=\"$1\" item=\"__item\" separator=\",\" >#{__item}</foreach>)");
    }
    script = "<script>" + script + "</script>";
    SqlSource source = super.createSqlSource(configuration, script, parameterType);
    log.info("sql=>{}", script);
    return source;
  }
}

DAO接口层的动态更新sql上面,加上自定义动态update注解,代码如下:

  @Lang(LanguageDriverUpdateIn.class)
  @Update(
      "update user_level set level=1,updateAt=now() where uid in(#{uids})")
  void updateLevel(@Param("uids") Collection<Long> uids);

原理:通过实现LanguageDriver,剥离了冗长的动态拼接SQL语句,简化了Update In的注解代码。

需要注意的是在使用Update In的时候,必在传入的参数前加@Param注解,否则会导致Mybatis找不到参数而抛出异常。

这样的sql语句是不是显得非常简洁,又可实现动态更新多条记录

再来对比一下常规写法,代码如下:

@Update({
          "<script> "
                  + "update user_level set level=1,updateAt=now() where uid in ("
                  + "<foreach collection='uids'  item='uid' separator=','> "
                  + "#{uid} "
                  + "</foreach> ) ",
          "</script>"
}) void updateLevel(@Param("uids") Collection<Long> uids);

这种写法是不是代码量多了很多,麻烦不说,还容易写错,额外增加了工作难度。

 

类似的自定义动态sql查询注解,代码如下:

package com.ljw.web.common.mybatis;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** 构造select in 动态sql查询 */
@Slf4j
/** @author seqwait */
public class LanguageDriverInsertBatch extends XMLLanguageDriver implements LanguageDriver {

  private final Pattern pattern =
      Pattern.compile(
          "(^\\s*?(?:replace|insert)\\s+into\\s+\\w+\\s+)\\((.*?)\\)\\s+(values)\\s+\\(#\\{(\\w+)}\\)");

  @Override
  public SqlSource createSqlSource(
      Configuration configuration, String script, Class<?> parameterType) {
    Matcher matcher = pattern.matcher(script);
    if (matcher.find()) {
      String[] columns = matcher.group(2).split(",");
      String sql =
          "%s (%s) values" + "<foreach collection='%s' item='item' separator=',' >(%s)</foreach>";
      StringBuilder sqls = new StringBuilder();
      for (int i = 0; i < columns.length; i++) {
        sqls.append("#{item.").append(columns[i]).append("}");
        if (i != columns.length - 1) {
          sqls.append(",");
        }
      }
      script =
          String.format(sql, matcher.group(1), matcher.group(2), matcher.group(4), sqls.toString());
    }
    script = "<script>" + script + "</script>";
    return super.createSqlSource(configuration, script, parameterType);
  }
}

 

标签:script,matcher,org,sql,Update,apache,SQL,Mybatis,import
From: https://www.cnblogs.com/Daniel-Leung/p/20221011174130MybatisSelectIn.html

相关文章

  • MySQL实现随机查询一条或多条数据
    一、随机查询一条数据SELECT*FROM`table`ASt1JOIN(SELECTROUND(RAND()*((SELECTMAX(id)FROM`table`)-(SELECTMIN(id)FROM`table`))+(SELECTMIN(id......
  • MyBatis-Plus个人笔记
    第一章MyBatis-Plus入门1)MP简介官方地址:http://mp.baomidou.com代码发布地址:Github:https://github.com/baomidou/mybatis-plusGitee:https://gitee.com/baomi......
  • mysql 时间函数
    时间格式转换标准时间格式:2017-05-1211:41:55--字符串转换为日期函数:str_to_date(str,format)SELECTSTR_TO_DATE('06.05.201719:40:30','%m.%d.%Y%H:%i:%s');--......
  • 浅谈MySQL、Hadoop、BigTable、Clickhouse数据读写机制
    个人理解,欢迎指正数据库引擎写数据读数据补充MySqlInnoDB:支持事务,高速读写性能一般Myisam:不支持事务,高速读写性能好以InnoDB更新一条记录为例1、B+Tree......
  • Mybatis批量操作
    foreach标签foreach元素的属性主要有item,index,collection,open,separator,closeitem表示集合中每一个元素进行迭代时的别名index指定一个名字,用于表示在迭代过程中,每次迭代到......
  • Mybatis通用Mapper(springboot环境下使用)
    ​​mapper3通用接口大全​​​:​​https://gitee.com/free/Mapper.git​​1、添加pom文件依赖<!--mapper--><dependency><groupId>tk.mybatis</groupId><artifact......
  • Mysql查询结果添加序列号
    单表从0开始SELECT(@i:=@i+1)ASidFROMsys_regionn1,(SELECT@i:=-1)ASitLIMIT1000从1开始SELECT(@i:=@i+1)ASidFROMsys_regionn1,......
  • Mysql关于时间的一些总结
    一、mysql获取当月的第一天获取当前时间SQL:SELECT结果:2017-12-27获取当前日期是当月的多少天SQL:SELECTDAY结果:27获取当月第一天SQL:SELECTDATE_ADD(CURDATE(),INTER......
  • sqlserver 分页 row_number() over(), offset fetch next only
    1-row_number()over()  1declare@pageIndexint=1,@pageSize=102select*from(3selectROW_NUMBER()over(orderbyId)'rowid',count(*)over()'Tot......
  • mysql 的连接问题
    --查看mysql的最大连接数showvariableslike'%max_connections%'--查看此时mysql的连接数量showstatuslike'Threads%'--查看mysql的连接的用户的信息s......