MyBatis注解開發(fā)-@Insert和@InsertProvider的使用
@Insert和@InsertProvider的使用
首先,在mybatis-generator.xml中配置返回主鍵

UserMapper中的
@SelectKey:返回主鍵,具體解釋見下面說明@InsertProvider:type指明SQL工廠類,method是工廠類里對(duì)應(yīng)的方法

@SelectKey注解源碼

statement是要運(yùn)行的SQL語(yǔ)句,它的返回值通過resultType來指定before表示查詢語(yǔ)句statement運(yùn)行的時(shí)機(jī)keyProperty表示查詢結(jié)果賦值給代碼中的哪個(gè)對(duì)象,keyColumn表示將查詢結(jié)果賦值給數(shù)據(jù)庫(kù)表中哪一列keyProperty和keyColumn都不是必需的,有沒有都可以before=true,插入之前進(jìn)行查詢,可以將查詢結(jié)果賦給keyProperty和-keyColumn,賦給keyColumn相當(dāng)于更改數(shù)據(jù)庫(kù)befaore=false,先插入,再查詢,這時(shí)只能將結(jié)果賦給keyProperty- 賦值給
keyProperty用來“讀”數(shù)據(jù)庫(kù),賦值給keyColumn用來寫數(shù)據(jù)庫(kù)
selectKey的兩大作用:
- 1、生成主鍵;
- 2、獲取剛剛插入數(shù)據(jù)的主鍵。
注意:在MYSQL 中 , order是AFTER , 因?yàn)楫?dāng)前及記錄的主鍵值在insert語(yǔ)句執(zhí)行成功之后才能拿到 , 而在ORACLE中 ,oder是BEFORE , 因?yàn)镺RACLE需要先從序列取到值 , 再將其作為主鍵插入到數(shù)據(jù)庫(kù)
另外,附上UserMapper.xml形式的返回主鍵方法
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
實(shí)體類的映射文件
namespace 指定接口的類全名
-->
<mapper namespace="com.wzl.dao.UserMapper">
<!--
方案一: 這表的主鍵必須是自增長(zhǎng)的 auto_increment
useGeneratedKeys="true" 讓自增長(zhǎng)的主鍵開啟返回功能
keyColumn="id" user表中主鍵列
keyProperty="id" user實(shí)體主鍵屬性
注意:支持主鍵自增類型的數(shù)據(jù)庫(kù) MySQL 和 SqlServer , oracle不支持
-->
<insert id="addUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into user values(null,#{user.username},#{user.birthday},#{user.sex},#{user.address})
</insert>
<!--
方案二: <selectKey>
keyColumn="id" user表中主鍵列
keyProperty="id" user實(shí)體主鍵屬性
resultType="int" user實(shí)體主鍵屬性類型
order="AFTER" 表示此標(biāo)簽內(nèi)部sql語(yǔ)句在insert執(zhí)行之前(執(zhí)行),還是之后執(zhí)行(執(zhí)行)
AFTER 之后執(zhí)行【在自增主鍵時(shí)】
BEFORE 之前執(zhí)行【使用指定主鍵時(shí)】
在MYSQL 中 , order是AFTER , 因?yàn)楫?dāng)前及記錄的主鍵值在insert語(yǔ)句執(zhí)行成功之后才能拿到 , 而在ORACLE中 ,oder是BEFORE , 因?yàn)镺RACLE需要先從序列取到值 , 再將其作為主鍵插入到數(shù)據(jù)庫(kù)
-->
<insert id="addUser2">
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user values(null, #{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
使用InsertProvider注解報(bào)錯(cuò)解決過程
目前項(xiàng)目在使用mybatis,并且是使用注解的方式。
在使用InsertProvider注解的時(shí)候報(bào)了一下的錯(cuò)誤:
org.apache.ibatis.builder.BuilderException: Could not find value method on SQL annotation. Cause: org.apache.ibatis.builder.BuilderException: Error creating SqlSource for SqlProvider. Method........
注解是如下這個(gè)樣子的
@InsertProvider(method = "insertlist",type=SqlProvider.class) ?public int insertInnerTable(List list,String dbTable);
思路是要寫一個(gè)通用的插入一個(gè)集合的方法,但是在執(zhí)行的時(shí)候就報(bào)了上面的錯(cuò)誤。在網(wǎng)上查資料未果。
于是只能自己動(dòng)手,豐衣足食了。
一步步跟斷點(diǎn),跟到mybatis了報(bào)錯(cuò)的方法中,發(fā)現(xiàn)了如下的代碼
try {
? ? ? this.sqlSourceParser = new SqlSourceBuilder(config);
? ? ? this.providerType = (Class<?>) provider.getClass().getMethod("type").invoke(provider);
? ? ? providerMethodName = (String) provider.getClass().getMethod("method").invoke(provider);
? ? ? for (Method m : this.providerType.getMethods()) {
? ? ? ? if (providerMethodName.equals(m.getName())) {
? ? ? ? ? if (m.getParameterTypes().length < 2
? ? ? ? ? ? ? && m.getReturnType() == String.class) {
? ? ? ? ? ? this.providerMethod = m;
? ? ? ? ? ? this.providerTakesParameterObject = m.getParameterTypes().length == 1;
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? } catch (Exception e) {
? ? ? throw new BuilderException("Error creating SqlSource for SqlProvider. ?Cause: " + e, e);
? ? }注意標(biāo)黃的位置,終于發(fā)現(xiàn)導(dǎo)致錯(cuò)誤的罪魁禍?zhǔn)琢?,原來是這里限制了參數(shù)的個(gè)數(shù),不能操作兩個(gè)參數(shù)的啊。
于是將方法以及注解改為如下形式
@InsertProvider(method = "insert",type=SqlProvider.class) ?public int insert(SqlContext sqlContext);
在SqlProvider中對(duì)應(yīng)的方法為
public String insert(SqlContext sqlContext){
? ? ? ........
}至此問題解決!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis多對(duì)多關(guān)聯(lián)實(shí)戰(zhàn)教程(推薦)
下面小編就為大家?guī)硪黄猰ybatis多對(duì)多關(guān)聯(lián)實(shí)戰(zhàn)教程(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
SpringFramework應(yīng)用接入Apollo配置中心過程解析
這篇文章主要介紹了SpringFramework應(yīng)用接入Apollo配置中心過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
解決FastJson中"$ref重復(fù)引用"的問題方法
這篇文章主要介紹了解決FastJson中"$ref重復(fù)引用"的問題方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
SSM框架+Plupload實(shí)現(xiàn)分塊上傳大文件示例
這篇文章主要介紹了SSM框架+Plupload實(shí)現(xiàn)分塊上傳示例(Spring+SpringMVC+MyBatis+Plupload),將用戶選中的文件(可多個(gè))分隔成一個(gè)個(gè)小塊,依次向服務(wù)器上傳,有興趣的可以了解一下。2017-03-03
關(guān)于兩個(gè)BeanUtils.copyProperties()的用法及區(qū)別
這篇文章主要介紹了關(guān)于兩個(gè)BeanUtils.copyProperties()的用法及區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
關(guān)于maven項(xiàng)目引入maven庫(kù)沒有的jar處理辦法
這篇文章主要介紹了關(guān)于maven項(xiàng)目引入maven庫(kù)沒有的jar處理辦法,在平時(shí)開發(fā)中,有些jar包是不存在maven中央庫(kù)中的,那么此時(shí)該如何解決才能方便后續(xù)處理呢,需要的朋友可以參考下本文2023-03-03
linux下用renameTo方法修改java web項(xiàng)目中文件夾名稱的實(shí)例
下面小編就為大家?guī)硪黄猯inux下用renameTo方法修改java web項(xiàng)目中文件夾名稱的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06
Java 實(shí)戰(zhàn)練手項(xiàng)目之酒店管理系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書不如行萬(wàn)里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+jsp+mysql+maven實(shí)現(xiàn)一個(gè)酒店管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11
SpringCloud微服務(wù)開發(fā)基于RocketMQ實(shí)現(xiàn)分布式事務(wù)管理詳解
分布式事務(wù)是在微服務(wù)開發(fā)中經(jīng)常會(huì)遇到的一個(gè)問題,之前的文章中我們已經(jīng)實(shí)現(xiàn)了利用Seata來實(shí)現(xiàn)強(qiáng)一致性事務(wù),其實(shí)還有一種廣為人知的方案就是利用消息隊(duì)列來實(shí)現(xiàn)分布式事務(wù),保證數(shù)據(jù)的最終一致性,也就是我們常說的柔性事務(wù)2022-09-09

