最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深度分析MybatisPlus查詢(xún)結(jié)果映射失敗@TableField失效解決辦法

 更新時(shí)間:2025年07月25日 09:31:58   作者:王ASC  
本文針對(duì)SpringBoot使用MybatisPlus框架時(shí)出現(xiàn)的查詢(xún)結(jié)果映射失敗問(wèn)題進(jìn)行深入分析,通過(guò)源碼解析,闡述了@TableField注解失效的原因,并提出了四種有效的解決方案,感興趣的朋友一起看看吧

問(wèn)題場(chǎng)景

Springboot使用MybatisPlus框架,數(shù)據(jù)庫(kù)中SQL能查到值,但是代碼中查不到,出現(xiàn)All elements are null等問(wèn)題。以下MybatisPlus簡(jiǎn)稱(chēng)MP

表結(jié)構(gòu)

CREATE TABLE `camel`  (
  `pwd` varchar(255),
  `age` int(11)
);
INSERT INTO `camel` VALUES ('100', 0);
INSERT INTO `camel` VALUES ('200', 1);
INSERT INTO `camel` VALUES ('300', 2);
INSERT INTO `camel` VALUES ('400', NULL);

Java實(shí)體類(lèi)

@TableName(value = "camel")
@Data
public class Camel {
    @TableField("pwd")
    private String pass_word;
    @TableField("age")
    private Integer age;
}

SpringBoot測(cè)試類(lèi)

@SpringBootTest
class DemoApplicationTests {
    @Autowired
    CamelMapper camelMapper;
    @Test
    void testTableField() {
        // 構(gòu)造查詢(xún)條件 pwd > 100 的 LambdaQueryWrapper
        LambdaQueryWrapper<Camel> lambdaQueryWrapper = Wrappers.lambdaQuery(Camel.class)
                .gt(Camel::getPass_word, "100");
        List<Camel> list = camelMapper.selectList(lambdaQueryWrapper);
        list.forEach(System.out::println);
        assert list.get(0).getPass_word()!=null;
    }
}

執(zhí)行結(jié)果

代碼執(zhí)行結(jié)果與預(yù)期不符,數(shù)據(jù)庫(kù)中能查詢(xún)到pwd,代碼中查到的pass_word為NULL

先說(shuō)原因

pass_word字段不滿(mǎn)足命名規(guī)范,導(dǎo)致MP框架無(wú)法通過(guò)反射將查詢(xún)字段賦值給實(shí)體類(lèi)屬性。

思考

數(shù)據(jù)從表中到實(shí)體類(lèi),可以理解為有兩個(gè)階段,首先是通過(guò)查詢(xún)sql得到字段值,然后ORM框架將查詢(xún)到的結(jié)果集通過(guò)setter的方式賦值給接收對(duì)象。

@TableField注解,用于使用MP動(dòng)態(tài)生成SQL或用resultType接受自定義SQL結(jié)果集時(shí),解決數(shù)據(jù)庫(kù)字段名與實(shí)體類(lèi)的屬性名不一致時(shí)的問(wèn)題,先前認(rèn)為使用該注解就能結(jié)果上述問(wèn)題。查看源碼中MP給出的注釋?zhuān)缦?/p>

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableField {
    /**
     * 數(shù)據(jù)庫(kù)字段值
     * <p>
     * 不需要配置該值的情況:
     * <li> 當(dāng) {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 為 true 時(shí),
     * (mp下默認(rèn)是true,mybatis默認(rèn)是false), 數(shù)據(jù)庫(kù)字段值.replace("_","").toUpperCase() == 實(shí)體屬性名.toUpperCase() </li>
     * <li> 當(dāng) {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 為 false 時(shí),
     * 數(shù)據(jù)庫(kù)字段值.toUpperCase() == 實(shí)體屬性名.toUpperCase() </li>
     */
    String value() default "";

當(dāng)使用@TableField注解,執(zhí)行sql如下:

select 注解值 as 實(shí)體類(lèi)屬性名 from table;

@TableField注解是通過(guò)別名實(shí)現(xiàn)的,其作用是當(dāng)resultType為實(shí)體類(lèi)時(shí),自動(dòng)為查詢(xún)結(jié)果設(shè)置別名,是發(fā)生在查詢(xún)階段,也因此將控制臺(tái)打印的sql拿到數(shù)據(jù)庫(kù)中能正常執(zhí)行,而本次問(wèn)題是發(fā)生在用實(shí)體類(lèi)接收查詢(xún)結(jié)果階段。

源碼分析

容器啟動(dòng)后,MP會(huì)緩存Mapper實(shí)體類(lèi)的setter與getter方法集合,這里使用了Lombok自動(dòng)生成setter與getter

開(kāi)始執(zhí)行查詢(xún)方法后,首先預(yù)編譯PrepareStatement

當(dāng)配置了Mybatis或MP的日志實(shí)現(xiàn),控制臺(tái)會(huì)打印預(yù)編譯sql與參數(shù),就是在這里實(shí)現(xiàn)的

預(yù)編譯參數(shù)賦值,這里就是查詢(xún)條件中的100

查詢(xún)SQL執(zhí)行完成,處理查詢(xún)結(jié)果的映射關(guān)系

根據(jù)是否打開(kāi)駝峰自動(dòng)轉(zhuǎn)換開(kāi)關(guān),處理屬性名,注意這個(gè)開(kāi)關(guān)在Mybatis中是默認(rèn)關(guān)閉,而在MP中是默認(rèn)打開(kāi)的!所以在這里的pass_word被替換成了password

之后從容器啟動(dòng)時(shí)MP緩存的實(shí)體類(lèi)的setter與getter方法集合中,查找實(shí)體類(lèi)屬性的setter方法,這里可以找到age,但是pass_word因被駝峰命名替換成password,而實(shí)際上實(shí)體類(lèi)中的屬性名是pass_word,導(dǎo)致無(wú)法找到password

用實(shí)體類(lèi)中映射成功的字段接收查詢(xún)結(jié)果,這里就只有age,沒(méi)有password了

通過(guò)反射執(zhí)行上面找到的屬性的setter方法

只有符合命名規(guī)范的字段才會(huì)被賦值成功

最終接收查詢(xún)結(jié)果的集合size = 3,但集合中只有兩個(gè)元素,是因?yàn)镾QL查出了3條記錄,其中pwd=400的記錄,因password字段賦值失敗為NULL,且age也為NULL,該對(duì)象的所有屬性都為NULL,所以集合中就存了一個(gè)NULL對(duì)象,如果集合中所有元素都是NULL,就會(huì)size != 0,且All elements are null

總結(jié)

MP通過(guò)反射的方式,使用屬性對(duì)應(yīng)setter方法為屬性賦值,將查詢(xún)結(jié)果映射到實(shí)體類(lèi),當(dāng)屬性命名不規(guī)范,且開(kāi)啟了駝峰命名開(kāi)關(guān),就會(huì)無(wú)法找到對(duì)應(yīng)setter方法,導(dǎo)致屬性無(wú)法賦值成功。

解決辦法

方法一:手動(dòng)添加setter方法

    private void setPassword(String pass_word) {
        this.pass_word = pass_word;
    }

方法二:若使用Lombok,規(guī)范屬性命名(可以保留命名不規(guī)范的屬性,避免影響項(xiàng)目原功能),本質(zhì)與方法一相同

private String password;

方法三:在配置文件中關(guān)閉駝峰自動(dòng)映射

mybatis-plus.configuration.map-underscore-to-camel-case=false

方法四:自定義Mapper方法,不使用實(shí)體類(lèi)作為resultType,在xml中使用自定義resultMap,指定查詢(xún)結(jié)果字段與實(shí)體類(lèi)屬性對(duì)應(yīng)關(guān)系(沒(méi)有使用resultType,@TableField注解不會(huì)生效)

    <!--property="pass_word"是實(shí)體類(lèi)屬性名,最終執(zhí)行的setter方法是setPass_word-->
    <!--column="pwd"是查詢(xún)結(jié)果字段名-->
    <resultMap id="myResultMap" type="com.example.demo.generator.domain.Camel">
        <result property="pass_word" column="pwd"/>
        <result property="age" column="age"/>
    </resultMap>
    <select id="myList" resultMap="myResultMap">
        select pwd, age from camel
    </select>  

參考

https://blog.csdn.net/HongYu012/article/details/123301153

到此這篇關(guān)于MybatisPlus查詢(xún)結(jié)果映射失敗@TableField失效解決辦法【源碼解析】的文章就介紹到這了,更多相關(guān)mybatisplus @tablefield失效內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot實(shí)現(xiàn)HTTP調(diào)用的7 種方式

    SpringBoot實(shí)現(xiàn)HTTP調(diào)用的7 種方式

    本文主要介紹了SpringBoot實(shí)現(xiàn)HTTP調(diào)用的7 種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • SpringBoot配置actuator的代碼

    SpringBoot配置actuator的代碼

    這篇文章主要介紹了SpringBoot配置actuator,這里大家需要注意可以監(jiān)控SpringBoot?中的?Tomcat?性能數(shù)據(jù),?以日志形式定期輸出監(jiān)控?cái)?shù)據(jù),?只需要配置一個(gè)Bean,需要的朋友可以參考下
    2022-03-03
  • Spring Cloud Feign實(shí)現(xiàn)動(dòng)態(tài)URL

    Spring Cloud Feign實(shí)現(xiàn)動(dòng)態(tài)URL

    本文主要介紹了Spring Cloud Feign實(shí)現(xiàn)動(dòng)態(tài)URL,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • ElasticSearch啟動(dòng)成功卻無(wú)法在瀏覽器訪(fǎng)問(wèn)問(wèn)題解決辦法

    ElasticSearch啟動(dòng)成功卻無(wú)法在瀏覽器訪(fǎng)問(wèn)問(wèn)題解決辦法

    因工作的需要,要使用elasticsearch,安裝完了,啟動(dòng)也成功了之后發(fā)現(xiàn)了問(wèn)題,這篇文章主要給大家介紹了關(guān)于ElasticSearch啟動(dòng)成功卻無(wú)法在瀏覽器訪(fǎng)問(wèn)問(wèn)題的解決辦法,需要的朋友可以參考下
    2024-10-10
  • Springboot實(shí)現(xiàn)MQTT通信的示例代碼

    Springboot實(shí)現(xiàn)MQTT通信的示例代碼

    本文主要介紹了Springboot實(shí)現(xiàn)MQTT通信的示例代碼,包含了MQTT協(xié)議的特點(diǎn)和工作原理等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-01-01
  • Eclipse中如何引入JUnit進(jìn)行單元測(cè)試

    Eclipse中如何引入JUnit進(jìn)行單元測(cè)試

    這篇文章主要介紹了Eclipse中如何引入JUnit進(jìn)行單元測(cè)試問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • JavaEE中volatile、wait和notify詳解

    JavaEE中volatile、wait和notify詳解

    這篇文章主要給大家介紹了關(guān)于JavaEE中volatile、wait和notify的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-02-02
  • Java8中Stream?API的peek()方法詳解及需要注意的坑

    Java8中Stream?API的peek()方法詳解及需要注意的坑

    這篇文章主要給大家介紹了關(guān)于Java8中Stream?API的peek()方法詳解及需要注意的坑,Java 中的 peek 方法是 Java 8 中的 Stream API 中的一個(gè)方法,它屬于中間操作,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • SpringBoot集成Eclipse Mosquitto的實(shí)現(xiàn)示例

    SpringBoot集成Eclipse Mosquitto的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot集成Eclipse Mosquitto的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解

    Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解,一些常用的工具類(lèi)、線(xiàn)程池、緩存,數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)連接池、賬戶(hù)登錄系統(tǒng)、配置文件等程序中可能只允許我們創(chuàng)建一個(gè)對(duì)象,這就需要單例模式,需要的朋友可以參考下
    2023-12-12

最新評(píng)論

桂阳县| 霍城县| 济源市| 石棉县| 松阳县| 康保县| 左贡县| 东兰县| 柳河县| 台中市| 夏邑县| 定兴县| 西充县| 永嘉县| 临武县| 股票| 玉林市| 平和县| 澎湖县| 深圳市| 巴楚县| 安泽县| 禹州市| 海丰县| 靖远县| 湄潭县| 阿克陶县| 仙桃市| 华坪县| 绥德县| 陇南市| 黑龙江省| 浮梁县| 东海县| 东宁县| 扎兰屯市| 阳谷县| 平舆县| 安庆市| 龙南县| 淮南市|