欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

mybatis plus開(kāi)發(fā)過(guò)程中遇到的問(wèn)題記錄及解決

 更新時(shí)間:2023年07月14日 14:20:56   作者:唱跑雨淋淋  
這篇文章主要介紹了mybatis plus開(kāi)發(fā)過(guò)程中遇到的問(wèn)題記錄及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

本文主要記錄本人使用 mybatis plus 開(kāi)發(fā)過(guò)程中碰到的問(wèn)題,以及解決方案

## 以下 mybatis plus 統(tǒng)一簡(jiǎn)稱(chēng) mp

一、使用 mp 生成代碼時(shí)

1、使用saveOrUpdateBatch或者saveBatch等新增修改方法時(shí)

問(wèn)題情況:

MybatisPlusException: error: can not execute. because can not find column for id from entity

原因:

不能執(zhí)行。因?yàn)闊o(wú)法從實(shí)體中找到id列使用 mp 自動(dòng)生成代碼時(shí),可能有這一行代碼,會(huì)導(dǎo)致不生成主鍵 ID,變成自定義基礎(chǔ)的Entity類(lèi),公共字段

strategy.setSuperEntityColumns("id")

解決方法:

將上面這行代碼注釋即可

可能生成 ID 之后任舊無(wú)法執(zhí)行,檢查下面的原因

可能會(huì)存在實(shí)體類(lèi)屬性與數(shù)據(jù)庫(kù)字段不一致的情況,所以我們?cè)谑褂?mp 生成實(shí)體類(lèi)時(shí),最好在生成策略中加上這個(gè)行

strategy.setEntityTableFieldAnnotationEnable(true);

目的:生成之后的實(shí)體類(lèi)中的每個(gè)屬性會(huì)多出一個(gè)注解,來(lái)用于屬性和數(shù)據(jù)庫(kù)字段的對(duì)應(yīng)

 @TableField("id")

2、生成實(shí)體類(lèi)時(shí)

數(shù)據(jù)庫(kù)中的 int 類(lèi)型 ID 變成了 String

問(wèn)題情況:

原因及解決方法:

我這里是 Mysql 數(shù)據(jù)庫(kù),生成代碼時(shí),做數(shù)據(jù)庫(kù)類(lèi)型轉(zhuǎn)換時(shí),原本選擇的是 Oracle 數(shù)據(jù)庫(kù),改成 Mysql 數(shù)據(jù)的類(lèi)型就可以

3、引用第2鐘錯(cuò)誤,當(dāng)我們使用 mp 生成代碼的時(shí)候,只想生成實(shí)體類(lèi)

問(wèn)題情況:

引用第2鐘錯(cuò)誤,當(dāng)我們使用 mp 生成代碼的時(shí)候,可能實(shí)體類(lèi)或者某一個(gè)文件中的代碼生成的有問(wèn)題,需要重新生成,但是又不想覆蓋其他 Controller 、Mapper 等文件,我們?nèi)绾芜x擇只生成實(shí)體類(lèi)?

解決方法:

我百度搜過(guò),大佬們生成代碼時(shí),基本上都是生成所有的文件,所以我就自己開(kāi)始研究。

請(qǐng)看下面這段代碼,大家應(yīng)該都明白這是什么意思,就是讓我們生成的 mapper.xml 生成到我們指定的 resource 的文件夾下面,那么它原本的 xml 為什么不會(huì)生成了呢?

        // 自定義輸出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定義配置會(huì)被優(yōu)先輸出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定義輸出文件名 , 如果你 Entity 設(shè)置了前后綴、此處注意 xml 的名稱(chēng)會(huì)跟著發(fā)生變化!!
                return projectPath + "/src/main/resources/mapperWorkDiscovery/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        //讓默認(rèn)生成 mapper 的目錄不再生成
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

關(guān)鍵點(diǎn)在這一行代碼

templateConfig.setXml(null);

在配置模板的時(shí)候,我們?cè)O(shè)置了模板的 xml 為null,那么在我們改變 xml 的生成路徑之后,原本的xml 就不會(huì)自己生成了,所以我想會(huì)不會(huì)有 .setMapper(null) 、 .setController(null) 的方法呢,于是我就自己嘗試了一下,加上這幾行代碼

templateConfig.setMapper(null);
templateConfig.setController(null);
templateConfig.setService(null);
templateConfig.setServiceImpl(null);

這樣重新生成之后,就只會(huì)生成 Entity 實(shí)體類(lèi)了。

二、使用 mp 封裝的方法時(shí)

1、使用修改方法,修改對(duì)象某一字段為null

問(wèn)題情況:開(kāi)發(fā)過(guò)程中,我們不可避免的會(huì)碰到這樣的一個(gè)場(chǎng)景,需要修改對(duì)象某一個(gè)字段的值為 null,原本我們用 mybatis 時(shí),修改方法會(huì)有兩個(gè)

  • updateByPrimaryKey 對(duì)你注入的字段全部更新(不判斷是否為Null);我們可以用這個(gè)來(lái)更新 null 值
  • updateByPrimaryKeySelective 會(huì)對(duì)字段進(jìn)行判斷再更新(如果為Null就忽略更新)

但是 mp 中的 update 方法是默認(rèn)只更新不為 null 的值

例如:這樣是更新不了對(duì)應(yīng)字段為 null 的

        TSysUseraccount tSysUseraccount = sysUseraccountMapper.selectById(84);
        tSysUseraccount.setfExtensionnumber(null);
        sysUseraccountMapper.updateById(tSysUseraccount);
//執(zhí)行的 sql 語(yǔ)句
UPDATE T_Sys_UserAccount SET F_UserCode='cs', F_DeleteFlag=0 WHERE F_UserId=84

解決方法:

使用 LambdaUpdateWrapper 強(qiáng)制設(shè)置字段值為 null

        TSysUseraccount tSysUseraccount = sysUseraccountMapper.selectById(84);
        LambdaUpdateWrapper<TSysUseraccount> userUpdateWrapper = new UpdateWrapper<TSysUseraccount>().lambda()
                .eq(TSysUseraccount::getfUserid,tSysUseraccount.getfUserid())
                .set(TSysUseraccount::getfExtensionnumber,null);
        sysUseraccountMapper.update(tSysUseraccount,userUpdateWrapper);
// 執(zhí)行的 sql 語(yǔ)句
UPDATE T_Sys_UserAccount SET F_UserCode='cs', F_DeleteFlag=0, F_ExtensionNumber=null WHERE F_UserId = 84

三、自定義 sql 查詢

1、mapper 接口中注解查詢

 @Select({"<script>",
            "SELECT IFNULL(sum( IFNULL(detail.amount,0) ),0) as total  FROM T_Lhgy_Work_Plan plan, T_Lhgy_Work_Plan_Detail detail WHERE plan.id = detail.plan_id AND plan.delete_flag = 0 AND detail.delete_flag = 0 AND plan.object_id = #{yhCompanyId}",
            "<when test='startTime!=null'>",
            "AND date_format(plan.create_date,'%Y-%m-%d')  >= #{startTime}",
            "</when>",
            "<when test='endTime!=null'>",
            "AND date_format(plan.create_date,'%Y-%m-%d') <= #{endTime}",
            "</when>",
            "</script>"})
    List<Map<String, Object>> selectSumAmountByYhCompany(@Param("yhCompanyId") Integer yhCompanyId,@Param("startTime") String startTime,@Param("endTime") String endTime);

問(wèn)題情況:

mybatis 報(bào)The content of elements must consist of well-formed character data or markup. 語(yǔ)法格式錯(cuò)誤

問(wèn)題原因:

原來(lái)在xml中使用“<” “>” “&” 等一些這樣的操作符時(shí),xml會(huì)把它當(dāng)成一個(gè)新的元素開(kāi)始;

解決方法:

使用< ![CDATA[" 標(biāo)記開(kāi)始,以"]]> 包裹在< ![CDATA[" 標(biāo)記開(kāi)始,以"]]> 里包裹的元素,在xml解析時(shí)會(huì)被解析器忽略

比如 >= 可以寫(xiě)成 <![CDATA[ >= ]]>

<= 可以寫(xiě)成 <![CDATA[ <= ]]>

 @Select({"<script>",
            "SELECT IFNULL(sum( IFNULL(detail.amount,0) ),0) as total  FROM T_Lhgy_Work_Plan plan, T_Lhgy_Work_Plan_Detail detail WHERE plan.id = detail.plan_id AND plan.delete_flag = 0 AND detail.delete_flag = 0 AND plan.object_id = #{yhCompanyId}",
            "<when test='startTime!=null'>",
            "AND date_format(plan.create_date,'%Y-%m-%d') <![CDATA[ >= ]]> #{startTime}",
            "</when>",
            "<when test='endTime!=null'>",
            "AND date_format(plan.create_date,'%Y-%m-%d') <![CDATA[ <= ]]> #{endTime}",
            "</when>",
            "</script>"})
    List<Map<String, Object>> selectSumAmountByYhCompany(@Param("yhCompanyId") Integer yhCompanyId,@Param("startTime") String startTime,@Param("endTime") String endTime);

四、使用 mybatis plus 性能分析插件

@Configuration
public class MybatisPlusConfig {
    /**
     * 打印 sql
     */
    @Bean
    @Profile({"dev","pro"})// 設(shè)置 dev pro 環(huán)境開(kāi)啟日志打印
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        //格式化sql語(yǔ)句
        Properties properties = new Properties();
        properties.setProperty("format", "false");
        performanceInterceptor.setProperties(properties);
        return performanceInterceptor;
    }
}

問(wèn)題:3.2 無(wú)法使用此性能分析插件,導(dǎo)包時(shí)無(wú)法導(dǎo)入

原因:如果 mp 在3.1版本時(shí)使用是不會(huì)有問(wèn)題的,但是如果你的 mp 是3.2的版本,就無(wú)法使用這個(gè)插件了,因?yàn)?mp 在3.2的版本已經(jīng)移除了這個(gè)性能分析插件并推薦使用第三方插件。

3.1 mp 源碼

3.2 mp 源碼,已經(jīng)沒(méi)有了 PerformanceInterceptor

解決方案:

將 3.1 的源碼復(fù)制出來(lái),自定義一個(gè) sql 性能分細(xì)插件

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package me.zhengjie.config;
import cn.hutool.db.sql.SqlFormatter;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
/**
 *  由于 mybatis plus 3.2 升級(jí)之后移除了性能分析的插件,所以此處手動(dòng)引入 3.1 的性能分析插件
 */
@Intercepts({@Signature(
    type = StatementHandler.class,
    method = "query",
    args = {Statement.class, ResultHandler.class}
), @Signature(
    type = StatementHandler.class,
    method = "update",
    args = {Statement.class}
), @Signature(
    type = StatementHandler.class,
    method = "batch",
    args = {Statement.class}
)})
public class PerformanceInterceptor implements Interceptor {
    private static final Log logger = LogFactory.getLog(PerformanceInterceptor.class);
    private static final String DruidPooledPreparedStatement = "com.alibaba.druid.pool.DruidPooledPreparedStatement";
    private static final String T4CPreparedStatement = "oracle.jdbc.driver.T4CPreparedStatement";
    private static final String OraclePreparedStatementWrapper = "oracle.jdbc.driver.OraclePreparedStatementWrapper";
    private long maxTime = 0L;
    private boolean format = false;
    private boolean writeInLog = false;
    private Method oracleGetOriginalSqlMethod;
    private Method druidGetSQLMethod;
    private static final SqlFormatter SQL_FORMATTER = new SqlFormatter();
    public PerformanceInterceptor() {
    }
    /** @deprecated */
    @Deprecated
    public static String sqlFormat(String boundSql, boolean format) {
        if (format) {
            try {
                return SQL_FORMATTER.format(boundSql);
            } catch (Exception var3) {
                ;
            }
        }
        return boundSql;
    }
    public Object intercept(Invocation invocation) throws Throwable {
        Object firstArg = invocation.getArgs()[0];
        Statement statement;
        if (Proxy.isProxyClass(firstArg.getClass())) {
            statement = (Statement)SystemMetaObject.forObject(firstArg).getValue("h.statement");
        } else {
            statement = (Statement)firstArg;
        }
        MetaObject stmtMetaObj = SystemMetaObject.forObject(statement);
        try {
            statement = (Statement)stmtMetaObj.getValue("stmt.statement");
        } catch (Exception var20) {
            ;
        }
        if (stmtMetaObj.hasGetter("delegate")) {
            try {
                statement = (Statement)stmtMetaObj.getValue("delegate");
            } catch (Exception var19) {
                ;
            }
        }
        String originalSql = null;
        String stmtClassName = statement.getClass().getName();
        Class clazz;
        Object stmtSql;
        if ("com.alibaba.druid.pool.DruidPooledPreparedStatement".equals(stmtClassName)) {
            try {
                if (this.druidGetSQLMethod == null) {
                    clazz = Class.forName("com.alibaba.druid.pool.DruidPooledPreparedStatement");
                    this.druidGetSQLMethod = clazz.getMethod("getSql");
                }
                stmtSql = this.druidGetSQLMethod.invoke(statement);
                if (stmtSql instanceof String) {
                    originalSql = (String)stmtSql;
                }
            } catch (Exception var18) {
                var18.printStackTrace();
            }
        } else if ("oracle.jdbc.driver.T4CPreparedStatement".equals(stmtClassName) || "oracle.jdbc.driver.OraclePreparedStatementWrapper".equals(stmtClassName)) {
            try {
                if (this.oracleGetOriginalSqlMethod != null) {
                    stmtSql = this.oracleGetOriginalSqlMethod.invoke(statement);
                    if (stmtSql instanceof String) {
                        originalSql = (String)stmtSql;
                    }
                } else {
                    clazz = Class.forName(stmtClassName);
                    this.oracleGetOriginalSqlMethod = this.getMethodRegular(clazz, "getOriginalSql");
                    if (this.oracleGetOriginalSqlMethod != null) {
                        this.oracleGetOriginalSqlMethod.setAccessible(true);
                        if (null != this.oracleGetOriginalSqlMethod) {
                            Object stmtSql1 = this.oracleGetOriginalSqlMethod.invoke(statement);
                            if (stmtSql1 instanceof String) {
                                originalSql = (String)stmtSql1;
                            }
                        }
                    }
                }
            } catch (Exception var17) {
                ;
            }
        }
        if (originalSql == null) {
            originalSql = statement.toString();
        }
        originalSql = originalSql.replaceAll("[\\s]+", " ");
        int index = this.indexOfSqlStart(originalSql);
        if (index > 0) {
            originalSql = originalSql.substring(index);
        }
        long start = SystemClock.now();
        Object result = invocation.proceed();
        long timing = SystemClock.now() - start;
        Object target = PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(target);
        MappedStatement ms = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
        StringBuilder formatSql = (new StringBuilder()).append(" Time:").append(timing).append(" ms - ID:").append(ms.getId()).append("\n").append("Execute SQL:").append(sqlFormat(originalSql, this.format)).append("\n");
        if (this.isWriteInLog()) {
            if (this.getMaxTime() >= 1L && timing > this.getMaxTime()) {
                logger.error(formatSql.toString());
            } else {
                logger.debug(formatSql.toString());
            }
        } else {
            System.err.println(formatSql.toString());
            Assert.isFalse(this.getMaxTime() >= 1L && timing > this.getMaxTime(), " The SQL execution time is too large, please optimize ! ", new Object[0]);
        }
        return result;
    }
    public Object plugin(Object target) {
        return target instanceof StatementHandler ? Plugin.wrap(target, this) : target;
    }
    public void setProperties(Properties prop) {
        String maxTime = prop.getProperty("maxTime");
        String format = prop.getProperty("format");
        if (StringUtils.isNotEmpty(maxTime)) {
            this.maxTime = Long.parseLong(maxTime);
        }
        if (StringUtils.isNotEmpty(format)) {
            this.format = Boolean.valueOf(format).booleanValue();
        }
    }
    public Method getMethodRegular(Class<?> clazz, String methodName) {
        if (Object.class.equals(clazz)) {
            return null;
        } else {
            Method[] var3 = clazz.getDeclaredMethods();
            int var4 = var3.length;
            for(int var5 = 0; var5 < var4; ++var5) {
                Method method = var3[var5];
                if (method.getName().equals(methodName)) {
                    return method;
                }
            }
            return this.getMethodRegular(clazz.getSuperclass(), methodName);
        }
    }
    private int indexOfSqlStart(String sql) {
        String upperCaseSql = sql.toUpperCase();
        Set<Integer> set = new HashSet();
        set.add(upperCaseSql.indexOf("SELECT "));
        set.add(upperCaseSql.indexOf("UPDATE "));
        set.add(upperCaseSql.indexOf("INSERT "));
        set.add(upperCaseSql.indexOf("DELETE "));
        set.remove(Integer.valueOf(-1));
        if (CollectionUtils.isEmpty(set)) {
            return -1;
        } else {
            List<Integer> list = new ArrayList(set);
            list.sort(Comparator.naturalOrder());
            return ((Integer)list.get(0)).intValue();
        }
    }
    public PerformanceInterceptor setMaxTime(long maxTime) {
        this.maxTime = maxTime;
        return this;
    }
    public long getMaxTime() {
        return this.maxTime;
    }
    public PerformanceInterceptor setFormat(boolean format) {
        this.format = format;
        return this;
    }
    public boolean isFormat() {
        return this.format;
    }
    public PerformanceInterceptor setWriteInLog(boolean writeInLog) {
        this.writeInLog = writeInLog;
        return this;
    }
    public boolean isWriteInLog() {
        return this.writeInLog;
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Junit Mockito實(shí)現(xiàn)單元測(cè)試方法介紹

    Junit Mockito實(shí)現(xiàn)單元測(cè)試方法介紹

    JUnit是用于編寫(xiě)和運(yùn)行可重復(fù)的自動(dòng)化測(cè)試開(kāi)源測(cè)試項(xiàng)目框架,這樣可以保證我們的代碼按與其工作。JUnit可廣泛用于工業(yè)和作為支架(從命令行)或IDE(如IDE)內(nèi)單獨(dú)的java程序
    2022-09-09
  • 關(guān)于mybatis plus 中的查詢優(yōu)化問(wèn)題

    關(guān)于mybatis plus 中的查詢優(yōu)化問(wèn)題

    這篇文章主要介紹了關(guān)于mybatis plus 中的查詢優(yōu)化問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • java瀏覽器文件打包下載過(guò)程解析

    java瀏覽器文件打包下載過(guò)程解析

    這篇文章主要介紹了java瀏覽器文件打包下載過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java?Guava的使用技巧整理

    Java?Guava的使用技巧整理

    Guava是Google發(fā)布的一個(gè)開(kāi)源庫(kù),主要提供了一些在Java開(kāi)發(fā)中非常有用的工具類(lèi)和API,不管是工作還是學(xué)習(xí)都是非常值得我們?nèi)ナ煜さ?,一起?lái)看看吧
    2023-03-03
  • 基于ElasticSearch Analyzer的使用規(guī)則詳解

    基于ElasticSearch Analyzer的使用規(guī)則詳解

    這篇文章主要介紹了基于ElasticSearch Analyzer的使用規(guī)則,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java利用Picocli開(kāi)發(fā)一個(gè)簡(jiǎn)化命令行工具

    Java利用Picocli開(kāi)發(fā)一個(gè)簡(jiǎn)化命令行工具

    Picocli 是一個(gè)強(qiáng)大、易用且功能豐富的 Java 庫(kù),用于開(kāi)發(fā)命令行工具,本文我們就來(lái)為大家介紹一下Java如何利用Picocli進(jìn)行命令行簡(jiǎn)化功能的吧
    2025-03-03
  • Nacos配置文件使用經(jīng)驗(yàn)及CAP原則詳解

    Nacos配置文件使用經(jīng)驗(yàn)及CAP原則詳解

    這篇文章主要為大家介紹了Nacos配置文件使用經(jīng)驗(yàn)及CAP規(guī)則詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-02-02
  • 一文帶你學(xué)習(xí)Java中的線程

    一文帶你學(xué)習(xí)Java中的線程

    線程是系統(tǒng)調(diào)度的最小單元,一個(gè)進(jìn)程可以包含多個(gè)線程,線程是負(fù)責(zé)執(zhí)行二進(jìn)制指令的。本文將詳細(xì)給大家介紹一下Java中的線程,,需要的朋友可以參考下
    2023-05-05
  • 詳解springboot+mybatis多數(shù)據(jù)源最簡(jiǎn)解決方案

    詳解springboot+mybatis多數(shù)據(jù)源最簡(jiǎn)解決方案

    本篇文章主要介紹了詳解springboot+mybatis多數(shù)據(jù)源最簡(jiǎn)解決方案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • java JSONArray 遍歷方式(2種)

    java JSONArray 遍歷方式(2種)

    這篇文章主要介紹了java JSONArray 遍歷方式(2種),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評(píng)論