亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Mybatis-plus解決兼容oracle批量插入的示例詳解

 更新時(shí)間:2024年11月03日 08:33:09   作者:騎龜?shù)墓? 
Mybatis-Plus 是一個(gè) MyBatis 的增強(qiáng)工具,提供無(wú)侵入、損耗小的 CRUD 操作,本文給大家介紹了Mybatis-plus解決兼容oracle批量插入,文中通過(guò)大家介紹的非常詳細(xì),需要的朋友可以參考下

1. 自定義SQL注入器

新建一個(gè)名為EasySqlInjector的類,繼承DefaultSqlInjector。

public class EasySqlInjector extends DefaultSqlInjector {
 
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        // 注意:此SQL注入器繼承了DefaultSqlInjector(默認(rèn)注入器),調(diào)用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自帶方法
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    }
 
}

2. 將SQL注入器交給Spring容器

MybatisPlusConfig類中,將剛才創(chuàng)建的SQL注入器EasySqlInjector,注冊(cè)為一個(gè)bean。

@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig
{
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 設(shè)置請(qǐng)求的頁(yè)面大于最大頁(yè)后操作, true調(diào)回到首頁(yè),false 繼續(xù)請(qǐng)求 默認(rèn)false
        // paginationInterceptor.setOverflow(false);
        // 設(shè)置最大單頁(yè)限制數(shù)量,默認(rèn) 500 條,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 開(kāi)啟 count 的 join 優(yōu)化,只針對(duì)部分 left join
        paginationInterceptor.setLimit(-1);
//        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
 
    /**
     * 分頁(yè)插件,自動(dòng)識(shí)別數(shù)據(jù)庫(kù)類型 https://baomidou.com/guide/interceptor-pagination.html
     */
    public PaginationInnerInterceptor paginationInnerInterceptor()
    {
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        // 設(shè)置數(shù)據(jù)庫(kù)類型為mysql
        paginationInnerInterceptor.setDbType(DbType.ORACLE);
        // 設(shè)置最大單頁(yè)限制數(shù)量,默認(rèn) 500 條,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        return paginationInnerInterceptor;
    }
 
    /**
     * 樂(lè)觀鎖插件 https://baomidou.com/guide/interceptor-optimistic-locker.html
     */
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor()
    {
        return new OptimisticLockerInnerInterceptor();
    }
 
    /**
     * 如果是對(duì)全表的刪除或更新操作,就會(huì)終止該操作 https://baomidou.com/guide/interceptor-block-attack.html
     */
    public BlockAttackInnerInterceptor blockAttackInnerInterceptor()
    {
        return new BlockAttackInnerInterceptor();
    }
 
    @Bean
    public EasySqlInjector sqlInjector() {
        return new EasySqlInjector();
    }
 
}

3. 配置EasyBaseMapper繼承BaseMapper

新建EasyBaseMapper類,繼承BaseMapper,并在此類中配置insertBatchSomeColumn()方法。

public interface  EasyBaseMapper<T> extends BaseMapper<T> {
    /**
     * @param entityList 實(shí)體列表
     */
    void insertBatchSomeColumn(Collection<T> entityList);
}

4.自定義Mybatis攔截器OracleSqlInterceptor

這個(gè)地方要注意,表的主鍵我用觸發(fā)器已經(jīng)自動(dòng)填入,所以keyGenerator設(shè)置為NoKeyGenerator.INSTANCE,這個(gè)地方有個(gè)坑,不那么設(shè)置,SQL一直報(bào)錯(cuò),折騰了兩個(gè)小時(shí),實(shí)際上拼接的SQL沒(méi)問(wèn)題

@Component
@Slf4j
@Order(1)
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class OracleSqlInterceptor implements Interceptor {
 
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //當(dāng)前業(yè)務(wù),兼容pg 和 oracle,需要兼容oracle的批量插入語(yǔ)句
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
 
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(statementHandler, "delegate");
        MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
        ReflectUtil.setFieldValue(mappedStatement,"keyGenerator", NoKeyGenerator.INSTANCE);
        String mName  = mappedStatement.getId().substring(mappedStatement.getId().lastIndexOf(".") + 1);
        if("insertBatchSomeColumn".equals(mName)){
            //開(kāi)始兼容批量插入語(yǔ)句,并設(shè)置boundSql
            Field declaredField = boundSql.getClass().getDeclaredField("sql");
            declaredField.setAccessible(true);
            declaredField.set(boundSql, convertOracleInsertSql(sql));
            log.info("---轉(zhuǎn)換后的sql為:{}", boundSql.getSql());
        }
        return invocation.proceed();
    }
 
    /**
     * Oracle Insert語(yǔ)句轉(zhuǎn)化
     *
     * @param sql 傳入的pg的sql
     * @return 轉(zhuǎn)化后的sql
     */
    public String convertOracleInsertSql(String sql) {
        //用oracle中的批量語(yǔ)句代替
        //查找values的位置,將后面全部括號(hào)里的東西取出,然后再用對(duì)應(yīng)的數(shù)據(jù)進(jìn)行封裝
        //獲取前面的sql,這段sql與Oracle的相同
        String prefix = sql.substring(0, getKeywordValueIndex(sql));
        //排除table中的括號(hào),取后面的括號(hào)
        String subSql = sql.substring(getKeywordValueIndex(sql));
        String valueSql = subSql.substring(subSql.indexOf("("));
        List<String> valueList = getValues(valueSql);
 
        //拼接sql
        StringBuilder sqlBuilder = new StringBuilder().append(prefix);
        //sqlBuilder.append("SELECT A.* FROM (");
        String selectValue = "SELECT ";
        String endValue = " FROM DUAL ";
        String unionValue = "UNION ALL ";
        boolean start = true;
        for (String value : valueList) {
            if (!start) {
                sqlBuilder.append(unionValue);
            }
            else {
                start = false;
            }
            sqlBuilder.append(selectValue).append(value).append(endValue);
        }
        //sqlBuilder.append(") A");
        return sqlBuilder.toString();
    }
 
    /**
     * 使用棧實(shí)現(xiàn)獲取value中括號(hào)的值
     *
     */
    public List<String> getValues(String sql) {
        List<String> values = new ArrayList<>();
        Stack<Character> brackets = new Stack<>();
        StringBuilder splitValue = new StringBuilder();
        for (Character c : sql.toCharArray()) {
            if ('(' == c) {
                //左括號(hào)進(jìn)棧
                brackets.push(c);
            }
            else if (')' == c) {
                //右括號(hào)則將左括號(hào)出棧,清空builder
                brackets.pop();
                values.add(splitValue.toString());
                splitValue.delete(0, splitValue.length());
            }
            else if (!brackets.empty()) {
                //只有進(jìn)入括號(hào)中才將值放入,排除括號(hào)外的逗號(hào)
                splitValue.append(c);
            }
        }
        return values;
 
    }
 
    /**
     * 查找關(guān)鍵字value的位置
     */
    public  int getKeywordValueIndex(String sql) {
        //先找values,再找value
        if (sql.contains("values")) {
            return sql.indexOf("values");
        }
        else if (sql.contains("VALUES")) {
            return sql.indexOf("VALUES");
        }
        else if (sql.contains("value")) {
            return sql.indexOf("value");
        }
        else {
            return sql.indexOf("VALUE");
        }
    }
 
}

然后,用業(yè)務(wù)Mapper繼承EasyBaseMapper就可以調(diào)用insertBatchSomeColumn()方法了。

到此這篇關(guān)于Mybatis-plus解決兼容oracle批量插入的示例詳解的文章就介紹到這了,更多相關(guān)Mybatis-plus oracle批量插入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaGUI模仿QQ聊天功能完整版

    JavaGUI模仿QQ聊天功能完整版

    這篇文章主要為大家詳細(xì)介紹了JavaGUI模仿QQ聊天功能完整版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • javaweb設(shè)計(jì)中filter粗粒度權(quán)限控制代碼示例

    javaweb設(shè)計(jì)中filter粗粒度權(quán)限控制代碼示例

    這篇文章主要介紹了javaweb設(shè)計(jì)中filter粗粒度權(quán)限控制代碼示例,小編覺(jué)得還是挺不錯(cuò)的,需要的朋友可以參考。
    2017-10-10
  • java 實(shí)現(xiàn)將Object類型轉(zhuǎn)換為int類型

    java 實(shí)現(xiàn)將Object類型轉(zhuǎn)換為int類型

    這篇文章主要介紹了java 實(shí)現(xiàn)將Object類型轉(zhuǎn)換為int類型的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • IntelliJ IDEA 小技巧之Bookmark(書(shū)簽)的使用

    IntelliJ IDEA 小技巧之Bookmark(書(shū)簽)的使用

    這篇文章主要介紹了IntelliJ IDEA 小技巧之Bookmark(書(shū)簽)的使用,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • servlet實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

    servlet實(shí)現(xiàn)簡(jiǎn)單的權(quán)限管理和敏感詞過(guò)濾功能

    JavaEE課要求用servlet和過(guò)濾器實(shí)現(xiàn)權(quán)限管理和敏感詞過(guò)濾功能,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 關(guān)于解決iReport4.1.1無(wú)法正常啟動(dòng)或者閃退或者JDK8不兼容的問(wèn)題

    關(guān)于解決iReport4.1.1無(wú)法正常啟動(dòng)或者閃退或者JDK8不兼容的問(wèn)題

    在安裝使用iReport的過(guò)程中遇到一個(gè)問(wèn)題,我的iReport始終不能打開(kāi),困擾了我好久。接下來(lái)通過(guò)本文給大家介紹iReport4.1.1無(wú)法正常啟動(dòng)或者閃退或者JDK8不兼容的問(wèn)題,需要的朋友可以參考下
    2018-09-09
  • JavaWeb文件上傳與下載功能解析

    JavaWeb文件上傳與下載功能解析

    這篇文章主要為大家詳細(xì)介紹了JavaWeb文件上傳與下載功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Java中枚舉類型的一種使用方式

    Java中枚舉類型的一種使用方式

    這篇文章主要介紹了Java中枚舉類型的一種使用方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java中的排序Comparator類用法詳解

    Java中的排序Comparator類用法詳解

    這篇文章主要介紹了Java中的排序Comparator類用法詳解,Comparator?類常作為?sorted()?方法的參數(shù)傳遞給?sorted?方法,用來(lái)解決給集合排序,自定義排序規(guī)則的問(wèn)題,需要的朋友可以參考下
    2023-08-08
  • Java如何替換字符

    Java如何替換字符

    文章介紹了Java中String類的replace()方法及其變體replaceFirst()的使用,包括如何替換單個(gè)字符、第一次出現(xiàn)的字符以及多個(gè)字符,通過(guò)示例展示了如何處理字符串中的特殊字符和空格
    2024-11-11

最新評(píng)論