mybatis批量插入失敗的問題

某日,同事說批量插入失敗,異常如下

2018-03-07 20:54:58,262 ERROR [][CardOperationVerifyServiceImpl.java:95] : 添加申請記錄出現異常

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter '__frch_item_0' not found. Available parameters are [list, param1]

at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:76)

at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:399)

at com.sun.proxy.$Proxy17.insert(Unknown Source)

at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:253)

at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:52)

at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53)

at com.sun.proxy.$Proxy29.batchCardOperationRecord(Unknown Source)

at com.shitu.cloudCard.service.impl.CardOperationVerifyServiceImpl.applyMoneyUp(CardOperationVerifyServiceImpl.java:91)

at com.shitu.service.CardOperationVerifyTest.applyMoneyUpTest(CardOperationVerifyTest.java:20)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:483)

at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)

at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)

at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)

at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)

at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)

at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)

at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)

at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)

at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)

at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)

at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)

at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)

at org.junit.runners.ParentRunner.run(ParentRunner.java:363)

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)

at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)

at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Caused by: org.apache.ibatis.binding.BindingException: Parameter '__frch_item_0' not found. Available parameters are [list, param1]

at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:168)

at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:45)

at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122)

at org.apache.ibatis.reflection.MetaObject.metaObjectForProperty(MetaObject.java:145)

at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:115)

at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:79)

at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:85)

at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:63)

at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:77)

at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)

at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:115)

at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:483)

at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)

at com.shitu.cloudCard.interceptor.SqlInterceptor.intercept(SqlInterceptor.java:137)

at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)

at com.sun.proxy.$Proxy40.update(Unknown Source)

at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:170)

at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:157)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:483)

at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:386)

... 35 more



這是mybatis的常見異常,隨即查詢xml里的sql語句,多次測試,無問題。困惑。。。

將批量插入改成單筆插入,插入數據庫成功。

懷疑是mycat的問題,搜索之。

SELECT:

跨分片(實體庫)的交叉查詢

跨節點的聯合查詢 (如用戶庫的表和平臺庫的表做聯合查詢)

INSERT:

插入的字段不包含分片字段 (如插入tbl_user_base_info表,沒有提供user_id列)

插入的分片字段找不到對應分片

復制插入Insert into…select…

多行插入insert into tab_a(c1,c2) values(v1,v2),(v11,v21)…

UPDATE:

更新的列包含分片列

多表更新update a, b set a.nation=’China’, b.pwd=’123456’ where a.id=b.id

復雜更新update a, b set a.nation=’China’ where a.id=b.id; 但支持子查詢方式update a set a.nation=’China’ where id in (select id from b);

DELETE:

復雜刪除 delete a from a join b on a.id=b.id;

支持子查詢方式delete from a where a.id in (select id from b), 但表不能起別名

其它:

Call procedure() MyCat未支持存儲過程定義, 因而不允許調用存儲過程,但可通過注解來調用各個分片上的存儲過程

Select func(); 不支持這種方式直接調用自定義函數,但支持select id, func() from employee,只需employee所在的所有分片上存在這個函數。MySql自帶函數可隨意使用。

注意事項:

Order by字段必須出現在select中(MyCat先將結果取出,然后排序)

Group by務必使用標準語法select count(1),type from tab_a group by type;

MyCat的一些自帶函數sum,min,max等可以正確使用,但多分片執行的avg有bug,執行的結果是錯誤的謹慎使用子查詢,外層查詢沒有分片查詢條件,則會在所有分片上執行(子查詢內外層的表一樣較為特殊)


隨即將mybatis中的#改成$,問題解決。

動態 SQL 是 mybatis 的強大特性之一,也是它優于其他 ORM 框架的一個重要原因。mybatis 在對 sql 語句進行預編譯之前,會對 sql 進行動態解析,解析為一個 BoundSql 對象,也是在此處對動態 SQL 進行處理的。在動態 SQL 解析階段, #{ } 和 ${ } 會有不同的表現

select * from user where name = #{name};

#{} 在動態解析的時候, 會解析成一個參數標記符。就是解析之后的語句是:

select * from user where name = ?;

那么我們使用 ${}的時候

select * from user where name = ${name};

${}在動態解析的時候,會將我們傳入的參數當做String字符串填充到我們的語句中,就會變成下面的語句

select * from user where name = "dato";

預編譯之前的 SQL 語句已經不包含變量了,完全已經是常量數據了。相當于我們普通沒有變量的sql了。

綜上所得, ${ } 變量的替換階段是在動態 SQL 解析階段,而 #{ }變量的替換是在 DBMS 中。

這是 #{} 和 ${} 我們能看到的主要的區別,除此之外,還有以下區別:

#方式能夠很大程度防止sql注入。

$方式無法防止Sql注入。

$方式一般用于傳入數據庫對象,例如傳入表名.

一般能用#的就別用$.

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內容