開發項目中,總是與數據打交道,有的時候將數據放入到一個集合中,然后在遍歷集合一條一條的插入,感覺效率超不好,最近又碰到這個問題,插入50條數據用了將近1s,完全滿足不了系統的需求.效率必須加快,然后網上查詢資料,歷經千萬bug,終於搞定,這里指提供mybatis中的配置,至於dao層的調用mybatis就自己上網查詢下資料吧
1根據網上搜了一下資料,在sql-mapper.xml文件中寫了如下配置可進行批量操作
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 =",">
( #{obj.M_LINE_NO},to_date(#{obj.M_TIME},'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM},
</ foreach >
</ insert >
然后啟動,調用這個操作的時候報錯
Error setting null parameter. Most JDBC driversrequire that the JdbcType must be specified for all nullable parameters. Cause:java.sql.SQLException: 無效的列類型
上網繼續查詢說加上 <![CDATA[ ]]> 即可,好吧配置變成了
<![CDATA[
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 =",">
( #{obj.M_LINE_NO},to_date(#{obj.M_TIME},'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM},
</ foreach >
</ insert >
然后依然報同樣的錯,查來查去,發現一句坑爹的話這個只是支持mySQL,去年買了個表。。。
繼續找方法吧,又被我找到一種在ORACLE中可以用的方法,參考網上的步驟,有了如下的配置
insert into REAL_DATA_HW( M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
select #{obj.M_LINE_NO},to_date(#{obj.M_TIME},'yyyy-MM-dd hh24:mi:ss'),#{obj.HW_NUM},
</ 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 into REAL_DATA_HW( M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
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 },
</ 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 into REAL_DATA_HW( M_LINE_NO,M_TIME,HW_NUM, VOL_A,VOL_B,VOL_C )
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 },
</ insert >
啟動,調用這個方法的依然報錯。。。
然后調試,發現VOL_A雖然是數字樣子,但是我放入到map的是字符串。。。相當的無語,改成Double類型的放入到map中,然后重新調用到這個方法的時候。
看着屏幕上刷的數據,一種幸福感,滿滿的。。。
然后看下效率,比原來單條插入快了6倍!!!
最后想了下mybatis操作的時候#是會根據列的類型來判斷是否需要添加引號,$不會加,然后將jdbcType=DOUBLE的字段換成了$,結果運行的時候沒有報錯。。但是數據庫中相應字段沒有數據啊!!!!!