mybatis的批量新增

開發項目中,總是與數據打交道,有的時候將數據放入到一個集合中,然後在遍歷集合一條一條的插入,感覺效率超不好,最近又碰到這個問題,插入50條數據用了將近1s,完全滿足不了系統的需求.效率必須加快,然後網上查詢資料,歷經千萬bug,終於搞定,這裏指提供mybatis中的配置,至於dao層的調用mybatis就自己上網查詢下資料吧

1根據網上搜了一下資料,在sql-mapper.xml文件中寫了如下配置可進行批量操作

< insert id ="insertBatch" parameterType="List" >
    insert into REAL_DATA_HW(
M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
    values
    < foreach collection ="list" item ="item" index ="index" separator =",">
       (
#{obj.M_LINE_NO},to_date(#{obj.M_TIME},'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM},
       #{obj.VOL_A},#{obj.VOL_B},#{obj.VOL_C} )
    </ foreach >
</ insert >

然後啓動,調用這個操作的時候報錯
Error setting null parameter. Most JDBC driversrequire that the JdbcType must be specified for all nullable parameters. Cause:java.sql.SQLException: 無效的列類型
上網繼續查詢說加上 <![CDATA[    ]]> 即可,好吧配置變成了

< insert id ="insertBatch" parameterType="List" >
<![CDATA[
    insert into REAL_DATA_HW(
M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
    values
]]>
    < foreach collection ="list" item ="item" index ="index" separator =",">
       (
#{obj.M_LINE_NO},to_date(#{obj.M_TIME},'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM},
       #{obj.VOL_A},#{obj.VOL_B},#{obj.VOL_C} )
    </ foreach >
</ insert >

然後依然報同樣的錯,查來查去,發現一句坑爹的話這個只是支持mySQL,去年買了個表。。。
繼續找方法吧,又被我找到一種在ORACLE中可以用的方法,參考網上的步驟,有了如下的配置

< insert id ="insertBatch" parameterType="List" >
    insert into REAL_DATA_HW(
M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
    < foreach collection ="list" item ="item" index ="index" separator ="union all">
     select   
#{obj.M_LINE_NO},to_date(#{obj.M_TIME},'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM},
       #{obj.VOL_A},#{obj.VOL_B},#{obj.VOL_C} from dual
    </ foreach >
</ insert >

這個的原理應該是參考的insert into  tableName select 。。。 from tableName1 這個方式
重新啓動,然後繼續報錯,奔潰

org.springframework.jdbc.UncategorizedSQLException: Error setting null parameter. Most JDBC drivers require that the JdbcType must be specified for all nullable parameters...哎 ,找原因,mybaties對null缺乏處理,需要在字段後加上jdbcType=類型,於是添加類型吧,順帶去網上查詢了mybatis的類型
iBatis官方的說法是, 只要是JDBC提供的JdbcType類中所定義的常量字符串,jdbcType這個屬性就可以取這個值,雖然有一些類型iBatis尚且不能支持(例如blobs)。而JdbcType類則由不同的JDBC Driver提供,可能由於Driver(不同類型的數據庫有不同的Driver)的不同會存在差異,不過大同小異。一般都支持如下類型(大小寫不敏感):
Array, BigInt, Binary, Bit, Blob, Boolean, Char, Clob, Datalink, Date, Decimal,
Double, Float, Integer, LongVarBinary, LongVarChar, Numeric, Real, Ref, SmallInt, Struct, Time, Timestamp, TinyInt, VarBinary, VarChar.
大小寫不敏感,,配置如下

< insert id ="insertBatch" parameterType="List" >
    insert into REAL_DATA_HW(
M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
    < foreach collection ="list" item ="item" index ="index" separator ="union all">
     select   
#{obj.M_LINE_NO,jdbcType= VarChar },to_date(#{obj.M_TIME ,jdbcType= VarChar },'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM , jdbcType=Double },
       #{obj.VOL_A ,jdbcType= Double },#{obj.VOL_B ,jdbcType= Double },#{obj.VOL_C ,jdbcType= Double } from dual
    </ foreach >
</ insert >

調用的時候繼續報錯,有一個是
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error resolving JdbcType. Cause: java.lang.IllegalArgumentException: No enum const class org.apache.ibatis.type.JdbcType.Double
親,不敏感你妹!!!!!!!!!
於是慢慢替換了下Double,終於在Double寫成DOUBLE的時候不在報這個錯誤了,此時配置如下

< insert id ="insertBatch" parameterType="List" >
    insert into REAL_DATA_HW(
M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
    < foreach collection ="list" item ="item" index ="index" separator ="union all">
     select   
#{obj.M_LINE_NO,jdbcType= VARCHAR },to_date(#{obj.M_TIME ,jdbcType= VARCHAR },'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM , jdbcType=DOUBLE },
       #{obj.VOL_A ,jdbcType= DOUBLE },#{obj.VOL_B ,jdbcType= DOUBLE },#{obj.VOL_C ,jdbcType= DOUBLE } from dual
    </ foreach >
</ insert >

啓動,調用這個方法的依然報錯。。。

org.springframework.jdbc.BadSqlGrammarException:
### Error updating database.  Cause: java.sql.SQLException: ORA-01790: 表達式必須具有與對應表達式相同的數據類型
然後調試,發現VOL_A雖然是數字樣子,但是我放入到map的是字符串。。。相當的無語,改成Double類型的放入到map中,然後重新調用到這個方法的時候。
看着屏幕上刷的數據,一種幸福感,滿滿的。。。
然後看下效率,比原來單條插入快了6倍!!!

最後想了下mybatis操作的時候#是會根據列的類型來判斷是否需要添加引號,$不會加,然後將jdbcType=DOUBLE的字段換成了$,結果運行的時候沒有報錯。。但是數據庫中相應字段沒有數據啊!!!!!


轉自:http://www.cnblogs.com/dyllove98/archive/2013/08/03/3235546.html

發佈了15 篇原創文章 · 獲贊 12 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章