当前位置: 首页 > 后端技术 > Java

spring-data-jpa使用oracle作为数据源时,查询超过1000条,报ORA_01795错误

时间:2023-04-02 01:38:16 Java

目的是解决项目。使用spring-data-jpa和oracle11g作为数据源时,当inquery后面的条件超过1000条后,oracle报ORA_01795异常。思路的问题在于oracle当前版本不支持单个in查询超过1000的情况,思路是在实体类生成sql之后,在查询之前使用jpa给我们提供的拦截器执行,判断生成的SQL。如果有以上1000条以上的情况,将SQL拆分成多个in的组合,通过or连接。例如:#jpa转换的SQL通常是如下形式,假如in(?,?,?....)超过1000个?selectid,name,genderfromuserwhereidin(?,?,?,?,?,?,?,?,?,?,?);#将其拆分selectid,name,genderfromuserwhere(idin(?,?,?,?,?,?)oridin(,?,?,?)或idin(?,?));代码包com.orient.collab.provider.common.jpa.interceptor;importorg.hibernate.resource.jdbc.spi.StatementInspector;importorg.springframework。boot.autoconfigure.condition.ConditionalOnProperty;导入org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;导入org.springframework.context.annotation.Configuration;导入java.util.Map;导入java.util.regex.Matcher;importjava.util.regex.Pattern;/***描述:*使用oracle作为数据源时,自定义一个sql语句拦截器解决"selectordeletewith'in'"limit1000cause!!!*!!!不支持不在*@authorMorningSun*@version1.0*@sinceJDK1.8*date2022/4/2719:16*/@Configuration@ConditionalOnProperty(name="spring.datasource.driver-class-name",havingValue="oracle.jdbc.driver.OracleDriver")publicclassJPAConfigurationOnUsingOracleimplementsHibernatePropertiesCustomizer{/***StringBuildersql=newStringBuilder("select*.*from..where*.*in(");*for(inti=0;i<999;i++){*sql.append("?,");*}*sql.append("?)");*System.out。println(sql.length());//4033*/privatestaticfinalintSQL_THRESHOLD_LENGTH=4033;//超过这个才去匹配privatefinalstaticintIN_CAUSE_LIMIT=1000;privatefinalstaticPatternpattern=Pattern.compile("[^(^\\()\\s]+\\s+in\\s*\\(+(\\?\\s*,\\s*){"+(IN_CAUSE_LIMIT-2)+",}+\\?\\)",Pattern.CASE_INSENSITIVE);@Overridepublicvoidcustomize(MaphibernateProperties){hibernateProperties.put("hibernate.session_factory.statement_inspector",newStatementInspector(){@OverridepublicStringinspect(Stringsql){if(sql.length()<=SQL_THRESHOLD_LENGTH){returnsql;}returnthis.rewriteSqlToAvoidORA_01795(sql);}私有字符串rewriteSqlToAvoidORA_01795(Stringsql){//longstartTime=System.currentTimeMillis();Matchermatcher=pattern.matcher(sql);while(matcher.find()){StringinExpression=matcher.group();longcountOfParameters=inExpression.chars().filter(ch->ch=='?').count();StringfieldName=inExpression.substring(0,inExpression.indexOf(''));StringBuildertransformedInExpression=newStringBuilder("(").append(fieldName).append("in(");for(inti=0;i