TKMappper框架oracle in超过1000问题处理

简介: TKMappper框架oracle in超过1000问题处理

背景


oracle 的sql in 或者 not in超过1000个项目,会报错。项目中已经大量使用了in,not in,考虑如何从框架层面统一处理。


解决方案


项目启动时候,Mapper会调用ExampleProvider类中的方法生成动态sql, 生成的动态sql的工具类为SqlHelper.java。因此修改SqlHelper.java中的源码即可。

  • 修改前

1671089465326.jpg

  • 修改后

1671089472681.jpg

public static String exampleWhereClause() {
        return "<if test="_parameter != null">" +
                "<where>\n" +
                " ${@tk.mybatis.mapper.util.OGNL@andNotLogicDelete(_parameter)}" +
                " <trim prefix="(" prefixOverrides="and |or " suffix=")">\n" +
                "  <foreach collection="oredCriteria" item="criteria">\n" +
                "    <if test="criteria.valid">\n" +
                "      ${@tk.mybatis.mapper.util.OGNL@andOr(criteria)}" +
                "      <trim prefix="(" prefixOverrides="and |or " suffix=")">\n" +
                "        <foreach collection="criteria.criteria" item="criterion">\n" +
                "          <choose>\n" +
                "            <when test="criterion.noValue">\n" +
                "              ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition}\n" +
                "            </when>\n" +
                "            <when test="criterion.singleValue">\n" +
                "              ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value}\n" +
                "            </when>\n" +
                "            <when test="criterion.betweenValue">\n" +
                "              ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value} and #{criterion.secondValue}\n" +
                "            </when>\n" +
                "            <when test="criterion.listValue">\n" +
                "               ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ( ${criterion.condition}\n" +
                "               <foreach collection="criterion.value" item="listItem" index="index"  open="(" close=")">\n" +
                "                   <if test="index != 0">\n" +
                "                       <choose>\n" +
                "                           <when test="index % 999 == 0">) <choose> <when test='criterion.condition.contains("not in")'> AND </when> <otherwise> OR </otherwise></choose> ${criterion.condition} (</when>\n" +
                "                           <otherwise>,</otherwise>\n" +
                "                       </choose>\n" +
                "                   </if>\n" +
                "                   #{listItem}\n" +
                "               </foreach>\n" +
                "               )\n" +
                "           </when>\n" +
                "          </choose>\n" +
                "        </foreach>\n" +
                "      </trim>\n" +
                "    </if>\n" +
                "  </foreach>\n" +
                " </trim>\n" +
                "</where>" +
                "</if>";
    }
复制代码
  • 修改内容
## 如果criterion.listValue为true的时候表示是in, not in的情况。
<when test="criterion.listValue"> 
    ## 解析出外面是and或者or, criterion.condition为:字段 in, 字段 not in
    ${@tk.mybatis.mapper.util.OGNL@andOr(criterion)} ( ${criterion.condition} 
        ## 循环遍历值
        <foreach collection="criterion.value" item="listItem" index="index" open="(" close=")"> 
          ## index不等于0, 因为0的余数都是0,不能进入循环  
          <if test="index != 0"> 
                <choose> 
                    ## 如果索引被999整除的情况
                    <when test="index % 999 == 0">
                      ## 添加括号
                      ) 
                        ## 如果是not in,用and连接, 如果是in, 用or连接
                        <choose> 
                            <when test='criterion.condition.contains("not in")'> AND </when> 
                            <otherwise> OR </otherwise>
                        </choose>
                      ## 重新生成 in 或者 not in
                     ${criterion.condition} (
                    </when> 
                    ## 其他的情况,用逗号
                     <otherwise>,
                     </otherwise> 
                </choose> 
            </if> 
            #{listItem} 
        </foreach> 
    ) 
</when> 
复制代码
  • 重点提示
  1. 修改的方法有两个,一个是exampleWhereClause,另外一个是updateByExampleWhereClause。
  2. in的话生成的内层用or连接, not in 生成的内层sql 用 and 连接。


测试案例


为了便于测试,用10来代替1000作为边界进行测试。

  • 测试代码

1671089489471.jpg

  • 生成SQL
SELECT USERNAME, PASSWORD_, REALNAME, TITLE, ORG_ID
  , IS_ENABLED, MULTILOGIN_ENABLED, ORG_PATH, EMAIL, MOBILE
  , CREATE_TIME, UPDATE_TIME, LAST_PWD_TIME, PWD_ERROR_TIMES, CREATE_BY
  , UPDATE_BY, PAGE_SIZE, UNLOCK_TIME
FROM sys_user
WHERE ORG_ID = 'aaa'
  OR (USERNAME IN (
      'admin0', 
      'admin1', 
      'admin2', 
      'admin3', 
      'admin4', 
      'admin5', 
      'admin6', 
      'admin7', 
      'admin8'
    )
    OR USERNAME IN ('admin9', 'admin10'))
  AND EMAIL = '33333'
  AND ((USERNAME NOT IN (
        'admin0', 
        'admin1', 
        'admin2', 
        'admin3', 
        'admin4', 
        'admin5', 
        'admin6', 
        'admin7', 
        'admin8'
      )
      AND USERNAME NOT IN ('admin9', 'admin10'))
    OR EMAIL = '33333');


目录
相关文章
|
4月前
|
开发框架 Oracle 关系型数据库
ABP框架使用Oracle数据库,并实现从SQLServer中进行数据迁移的处理
ABP框架使用Oracle数据库,并实现从SQLServer中进行数据迁移的处理
|
6月前
|
SQL Oracle 关系型数据库
JAVAEE框架数据库技术之12_oracle常用函数和高级查询子查询
JAVAEE框架数据库技术之12_oracle常用函数和高级查询子查询
112 0
JAVAEE框架数据库技术之12_oracle常用函数和高级查询子查询
|
6月前
|
存储 Java 数据库
JAVAEE框架数据库技术之13_oracle 之PLSQL技术及存储过程和函数(二)
JAVAEE框架数据库技术之13_oracle 之PLSQL技术及存储过程和函数
75 0
|
6月前
|
SQL 存储 Oracle
JAVAEE框架数据库技术之11 oracle入门
JAVAEE框架数据库技术之11 oracle入门
154 0
JAVAEE框架数据库技术之11 oracle入门
|
6月前
|
存储 SQL Java
JAVAEE框架数据库技术之13_oracle 之PLSQL技术及存储过程和函数(一)
JAVAEE框架数据库技术之13_oracle 之PLSQL技术及存储过程和函数
64 0
|
Oracle Java 关系型数据库
JSP struts2工资管理系统myeclipse开发oracle数据库bs框架java编程网结构
JSP 工资管理系统是一套完善的struts2设计系统MVC结构,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Oracle10g,使用java语言开发,系统主要采用B/S模式开发。
68 1
|
存储 SQL Oracle
【MyBatis框架点滴】——mybatis插入数据返回主键(mysql、oracle)
  向数据库中插入数据时,大多数情况都会使用自增列或者UUID做为主键。主键的值都是插入之前无法知道的,但很多情况下我们在插入数据后需要使用刚刚插入数据的主键,比如向两张关联表A、B中插入数据(A的主键是B的外键),向A表中插入数据之后,向B表中插入数据时需要用到A的主键。
|
Oracle 关系型数据库 物联网
《物联网框架ServerSuperIO教程》-19.设备驱动和OPC Client支持mysql、oracle、sqlite、sqlserver的持久化。v3.6.4版本发布
19.设备驱动和OPC Client支持mysql、oracle、sqlite、sqlserver的持久化 19.1     概述      ServerSuperIO支持设备驱动和OPC Client采集的数据信息按标签集合写入mysql、oracle、sqlserver和sqlite数据库。
1122 0
|
19天前
|
存储 Oracle 关系型数据库
Oracle数据库的应用场景有哪些?
【10月更文挑战第15天】Oracle数据库的应用场景有哪些?
134 64