目錄
一.問題描述
二.源碼分析
三.總結(jié)
一.問題描述
事情的起因是用MybaitsPlus查詢數(shù)據(jù)庫過程中,查詢結(jié)果與要封裝的實(shí)體類字段類型對(duì)應(yīng)不上,類似這樣:
數(shù)據(jù)庫查詢結(jié)果:
java實(shí)體類:
@TableName("my_user")
@ToString
public class User {
private Long id;
private String name;
private BigDecimal age;
public User(String name,BigDecimal age){
this.name=name;
this.age=age;
}
}
字段名字和實(shí)體類的名字類型都能對(duì)應(yīng)上,但最后的查詢結(jié)果卻會(huì)報(bào)錯(cuò)java.sql.SQLDataException: Cannot determine value type from string
意思就是String類型的‘zhang’沒有對(duì)應(yīng)的類型實(shí)體類字段,這就很奇怪了,經(jīng)過排查,是因?yàn)榧恿擞袇?gòu)造器,有參構(gòu)造器去掉或者加上注解@NoArgConstructor就可以解決問題,不想看原因的可以直接跳到后面看結(jié)論
二.源碼分析
根據(jù)報(bào)錯(cuò)信息找到了Mybatis中DefaultResultSetHandler這個(gè)類的createResultObject方法,這是創(chuàng)建返回的實(shí)體類的方法
這里我們看到已經(jīng)拿到了實(shí)體類的Class對(duì)象,并且走到了createByConstructorSignature方法,這個(gè)方法顧名思義就是通過構(gòu)造器來創(chuàng)建對(duì)象,我們?cè)龠M(jìn)這個(gè)方法看看
這個(gè)方法會(huì)拿到一個(gè)defaultConstructor默認(rèn)構(gòu)造器,那這個(gè)defaultConstructor又是從哪里來的呢,點(diǎn)進(jìn)去findDefaultConstructor方法看一下
這個(gè)方法里也很簡(jiǎn)單,如果只有一個(gè)構(gòu)造器就返回這個(gè)構(gòu)造器,User類只有一個(gè)構(gòu)造器,返回的就是(String,Bigdecimal)的構(gòu)造器,回到createByConstructorSignature這個(gè)方法中,接下來就會(huì)進(jìn)入createUsingConstructor這個(gè)方法中
這個(gè)方法會(huì)通過for循環(huán)把構(gòu)造器中的參數(shù)和查詢出的結(jié)果一一對(duì)應(yīng),并添加到constructorArgs中,最后通過objectFactory.create(resultType, constructorArgTypes, constructorArgs)這個(gè)方法來用這個(gè)構(gòu)造器反射生成實(shí)力對(duì)象??梢钥吹降谝粋€(gè)參數(shù)就出問題了,構(gòu)造器中第一個(gè)參數(shù)是String類型,而查詢出來的第一個(gè)字段id應(yīng)該是Long類型的,顯然對(duì)應(yīng)不上
查詢出來的id為String類型的1234,而到第二個(gè)參數(shù)就會(huì)變成BigDecimal類型去對(duì)應(yīng)String類型的name,這無法轉(zhuǎn)換就會(huì)報(bào)錯(cuò)
那如果去掉有參的構(gòu)造器呢,去掉之后實(shí)體類里就只會(huì)剩下空參的構(gòu)造器,再執(zhí)行到createResultObject方法時(shí),我們就可以看到執(zhí)行到metaType.hasDefaultConstructor()這個(gè)方法時(shí)返回的是true,而defaultConstructor就是空參構(gòu)造器,所以進(jìn)入的是objectFactory.create(resultType)這個(gè)方法,這個(gè)方法里會(huì)通過這個(gè)空參的構(gòu)造器來反射生成一個(gè)對(duì)象,后續(xù)再通過反射給這個(gè)對(duì)象賦值
文章來源:http://www.zghlxwxcb.cn/news/detail-772444.html
三.總結(jié)
在mybatis中,用于承接sql執(zhí)行結(jié)果的實(shí)體類最好要有一個(gè)空參構(gòu)造器,否則很可能出現(xiàn)類型對(duì)應(yīng)不上的問題,因?yàn)镸ybaits會(huì)優(yōu)先用空參構(gòu)造器來反射生成對(duì)象,如果沒有空參構(gòu)造器則會(huì)用有參的構(gòu)造器,這時(shí)候查詢的返回結(jié)果必須和構(gòu)造器的參數(shù)一一對(duì)應(yīng),而且因?yàn)槭荕ybatis框架的原因,所有數(shù)據(jù)庫都有可能出現(xiàn)這個(gè)情況,只是拋出的提示會(huì)有所不同,值得注意的是如果用了@Bulider這個(gè)注解編譯后會(huì)生成一個(gè)全參的構(gòu)造器,需要注意文章來源地址http://www.zghlxwxcb.cn/news/detail-772444.html
到了這里,關(guān)于Mybaits:數(shù)據(jù)庫查詢類型不匹配,java.sql.SQLDataException: Cannot determine value type from string的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!