本文是测试Db2数据库插入数据报错。具体来讲,是通过命令行、JDBC、Mybatis等各种方式,尝试把一个长度为11的字符串插入到 VARCHAR(8)
的字段,查看报错信息,方便以后遇到类似的错误时,能够帮助快速定位问题。
$ db2level
DB21085I This instance or install (instance name, where applicable:
"db2inst1") uses "64" bits and DB2 code release "SQL11050" with level
identifier "0601010F".
Informational tokens are "DB2 v11.5.0.0", "s1906061700", "DYN1906061700AMD64",
and Fix Pack "0".
Product is installed at "/opt/ibm/db2/V11.5".
SAMPLE
$ db2 connect to sample
Database Connection Information
Database server = DB2/LINUXX8664 11.5.0.0
SQL authorization ID = DB2INST1
Local database alias = SAMPLE
T6
$ db2 describe table t6
Data type Column
Column name schema Data type name Length Scale Nulls
------------------------------- --------- ------------------- ---------- ----- ------
C1 SYSIBM INTEGER 4 0 Yes
C2 SYSIBM VARCHAR 8 0 Yes
2 record(s) selected.
懒得看具体测试过程的同学,请直接看总结:
SQL0433N
(即 SQLCODE -433
),并且会提供导致错误的值,本例中是 abcdefghijk
?
动态绑定的值(先prepare,再set value,再执行) ,则报错是SQLCODE -302
,并且不会提供导致错误的值或者column名字,这就很讨厌,因为如果有多个 ?
,你也不知道是哪个绑定的值出错了select cast(stmt_text as varchar(100)), section_type from table(MON_GET_PKG_CACHE_STMT(null, null, null, -2))
),其中section_type都是 D
stmt_text
可知,literal的SQL就是literal, ?
的SQL就是 ?
-4229
,但这只是一个笼统的错误码,表明batch操作中的某个操作有错误,并没有提供更详细的错误说明。另外, batch index #1
,这里面的 1
我没搞懂是什么意思getCause()
,得到 BatchUpdateException
(需要强制类型转换),再调用其 getNextException()
方法,才能获取真正的异常 SqlDataException
。同样,其具体的错误是 -302
,但并不知道是哪个值或者column出错了batch element #
中的
值,指明是batch操作的第几个SQL出错了测试方式 | Auto Commit | Prepared | stmt_text | 报错位置 | 报错信息 | |
---|---|---|---|---|---|---|
Test 1 | 命令行 | Y | N | insert into t6 values (1, 'abcdefghijk') |
insert处 | SQL0433N Value "abcdefghijk" is too long. SQLSTATE=22001 |
Test 2 | 命令行 | N | N | insert into t6 values (1, 'abcdefghijk') |
insert处 | SQL0433N Value "abcdefghijk" is too long. SQLSTATE=22001 |
Test 3 | JDBC | Y | N | insert into t6 values (1, 'abcdefghijk') |
insert处 | Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-433, SQLSTATE=22001, SQLERRMC=abcdefghijk, |
Test 4 | JDBC | N | N | insert into t6 values (1, 'abcdefghijk') |
insert处 | Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-433, SQLSTATE=22001, SQLERRMC=abcdefghijk, |
Test 5 | JDBC | Y | Y | insert into t6 values (?, ?) |
insert处 | Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, |
Test 6 | JDBC | N | Y | insert into t6 values (?, ?) |
insert处 | Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, |
Test 7 | Mybatis | Y | Y | insert into t6 values (?, ?) |
insert处 | ### Error updating database. Cause: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, |
Test 8 | Mybatis | N | Y | insert into t6 values (?, ?) |
insert处 | ### Error updating database. Cause: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, |
Test 9 | Mybatis (Batch Insert) | N | Y | insert into t6 values (?, ?) |
commit处 | ### Error committing transaction. Cause: org.apache.ibatis.executor.BatchExecutorException: testMybatis.Test0207Mapper.insert (batch index #1) failed. Cause: com.ibm.db2.jcc.am.BatchUpdateException: [jcc][t4][102][10040][4.21.29] Batch failure. The batch was submitted, but at least one exception occurred on an individual member of the batch. Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null |
直接在Db2命令行运行insert语句:
$ db2 "insert into t6 values (1, 'abcdefghijk')"
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0433N Value "abcdefghijk" is too long. SQLSTATE=22001
SQL0433N
即Db2的 -433
error,其具体解释如下:
$ db2 ? sql433
SQL0433N Value "" is too long.
Explanation:
The value "" required truncation by a system (built-in)
cast or adjustment function, which was called to transform the value in
some way. The truncation is not allowed where this value is used.
The value being transformed is one of the following:
* an argument to a user defined function (UDF)
* an input to the SET clause of an UPDATE statement
* a value being INSERTed into a table
* an input to a cast or adjustment function in some other context
* a recursively referenced column whose data type and length is
determined by the initialization part of recursion and may grow in
the iterative part of the recursion
* an XML data value being serialized to the output by XMLSERIALIZE
function.
The statement cannot be processed.
User response:
If "" is a literal string in the SQL statement, it is
too long for its intended use.
If "" is not a literal string, examine the SQL
statement to determine where the transformation is taking place. Either
the input to the transformation is too long, or the target is too short.
Correct the problem and rerun the statement.
sqlcode: -433
sqlstate: 22001
同上,唯一差别是把AutoCommit设置为off:
$ db2 +c "insert into t6 values (1, 'abcdefghijk')"
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0433N Value "abcdefghijk" is too long. SQLSTATE=22001
注:别忘了commit或者rollback。如果在同一事务之内,在这个失败的SQL之前运行过其它SQL,则那些SQL仍然需要显式的commit/rollback。
使用JDBC程序来做insert操作:
package testJDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Test0207 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Class.forName("com.ibm.db2.jcc.DB2Driver");
try (Connection conn = DriverManager.getConnection("jdbc:db2://9.30.251.58:50000/sample", "db2inst1" , "N1cetest")) {
String sql1 = "insert into t6 values (1, 'abcdefghijk')";
try (Statement ps = conn.createStatement()) {
ps.executeUpdate(sql1);
}
}
}
}
运行程序,报错如下:
Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-433, SQLSTATE=22001, SQLERRMC=abcdefghijk, DRIVER=4.21.29
at com.ibm.db2.jcc.am.kd.a(kd.java:802)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:140)
at com.ibm.db2.jcc.am.sp.c(sp.java:2796)
at com.ibm.db2.jcc.am.sp.d(sp.java:2784)
at com.ibm.db2.jcc.am.sp.b(sp.java:2146)
at com.ibm.db2.jcc.t4.bb.j(bb.java:233)
at com.ibm.db2.jcc.t4.bb.c(bb.java:48)
at com.ibm.db2.jcc.t4.p.b(p.java:38)
at com.ibm.db2.jcc.t4.vb.h(vb.java:124)
at com.ibm.db2.jcc.am.sp.jb(sp.java:2141)
at com.ibm.db2.jcc.am.sp.a(sp.java:3336)
at com.ibm.db2.jcc.am.sp.c(sp.java:768)
at com.ibm.db2.jcc.am.sp.executeUpdate(sp.java:747)
at testJDBC.Test0207.main(Test0207.java:18)
相比前面的JDBC程序:
运行结果:
package testJDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Test0207 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Class.forName("com.ibm.db2.jcc.DB2Driver");
try (Connection conn = DriverManager.getConnection("jdbc:db2://9.30.251.58:50000/sample", "db2inst1" , "N1cetest")) {
conn.setAutoCommit(false);
String sql1 = "insert into t6 values (1, 'abcdefg')";
try (Statement ps = conn.createStatement()) {
ps.executeUpdate(sql1);
}
System.out.println(sql1);
sql1 = "insert into t6 values (1, 'abcdefghijk')";
try (Statement ps = conn.createStatement()) {
ps.executeUpdate(sql1);
}
System.out.println(sql1);
sql1 = "insert into t6 values (1, 'hijklmn')";
try (Statement ps = conn.createStatement()) {
ps.executeUpdate(sql1);
}
System.out.println(sql1);
conn.commit();
}
}
}
运行程序,报错如下:
insert into t6 values (1, 'abcdefg')
Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-433, SQLSTATE=22001, SQLERRMC=abcdefghijk, DRIVER=4.21.29
at com.ibm.db2.jcc.am.kd.a(kd.java:802)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:140)
at com.ibm.db2.jcc.am.sp.c(sp.java:2796)
at com.ibm.db2.jcc.am.sp.d(sp.java:2784)
at com.ibm.db2.jcc.am.sp.b(sp.java:2146)
at com.ibm.db2.jcc.t4.bb.j(bb.java:233)
at com.ibm.db2.jcc.t4.bb.c(bb.java:48)
at com.ibm.db2.jcc.t4.p.b(p.java:38)
at com.ibm.db2.jcc.t4.vb.h(vb.java:124)
at com.ibm.db2.jcc.am.sp.jb(sp.java:2141)
at com.ibm.db2.jcc.am.sp.a(sp.java:3336)
at com.ibm.db2.jcc.am.sp.c(sp.java:768)
at com.ibm.db2.jcc.am.sp.executeUpdate(sp.java:747)
at testJDBC.Test0207.main(Test0207.java:25)
Suppressed: com.ibm.db2.jcc.am.SqlException: [jcc][t4][10251][10308][4.21.29] java.sql.Connection.close() requested while a transaction is in progress on the connection.
The transaction remains active, and the connection cannot be closed. ERRORCODE=-4471, SQLSTATE=null
at com.ibm.db2.jcc.am.kd.a(kd.java:794)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:133)
at com.ibm.db2.jcc.am.Connection.checkForTransactionInProgress(Connection.java:1457)
at com.ibm.db2.jcc.t4.b.checkForTransactionInProgress(b.java:7374)
at com.ibm.db2.jcc.am.Connection.closeResourcesX(Connection.java:1480)
at com.ibm.db2.jcc.am.Connection.closeX(Connection.java:1466)
at com.ibm.db2.jcc.am.Connection.close(Connection.java:1443)
at testJDBC.Test0207.main(Test0207.java:37)
先prepare statement,再set值,再执行:
package testJDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test0207 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Class.forName("com.ibm.db2.jcc.DB2Driver");
try (Connection conn = DriverManager.getConnection("jdbc:db2://9.30.251.58:50000/sample", "db2inst1" , "N1cetest")) {
String sql1 = "insert into t6 values (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql1)) {
ps.setInt(1, 1);
ps.setString(2, "abcdefghijk");
ps.executeUpdate();
}
}
}
}
运行程序,报错如下:
Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
at com.ibm.db2.jcc.am.kd.a(kd.java:802)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:140)
at com.ibm.db2.jcc.am.sp.b(sp.java:2447)
at com.ibm.db2.jcc.am.sp.c(sp.java:2430)
at com.ibm.db2.jcc.t4.bb.m(bb.java:415)
at com.ibm.db2.jcc.t4.bb.a(bb.java:62)
at com.ibm.db2.jcc.t4.p.a(p.java:50)
at com.ibm.db2.jcc.t4.wb.b(wb.java:220)
at com.ibm.db2.jcc.am.tp.uc(tp.java:3567)
at com.ibm.db2.jcc.am.tp.a(tp.java:4613)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.a(tp.java:4798)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.mc(tp.java:817)
at com.ibm.db2.jcc.am.tp.executeUpdate(tp.java:791)
at testJDBC.Test0207.main(Test0207.java:20)
Db2的 -302
error,其具体解释如下:
$ db2 ? sql302
SQL0302N The value of a host variable in the EXECUTE or OPEN statement
is out of range for its corresponding use.
Explanation:
The value of an input host variable was found to be out of range for its
use in the SELECT, VALUES, or prepared statement.
One of the following occurred:
* The corresponding host variable or parameter marker used in the SQL
statement is defined as string, but the input host variable contains
a string that is too long.
* The corresponding host variable or parameter marker used in the SQL
statement is defined as numeric, but the input host variable contains
a numeric value that is out of range.
* The terminating NUL character is missing from the C language
NUL-terminated character string host variable.
* Federated system users: in a pass-through session, a data
source-specific restriction might have been violated.
This error occurs as a result of specifying either an incorrect host
variable or an incorrect SQLLEN value in an SQLDA on an EXECUTE or OPEN
statement.
The statement cannot be processed.
User response:
Ensure that the input host variable value is the correct type and
length.
If the input host variables supply values to parameter markers, match
values with the implied data type and length of the parameter marker.
Federated system users: for a pass-through session, determine what data
source is causing the error.
Examine the SQL dialect for that data source to determine which specific
restriction has been violated, and adjust the failing statement as
needed.
sqlcode: -302
sqlstate: 22001, 22003
Related information:
Troubleshooting data source connection errors
请注意:在Db2的错误信息里面,并没有提供出错的字段,也就是说,我们无法确定是哪个字段在insert时超出了范围。
相比前面的JDBC程序:
运行结果:
package testJDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test0207 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Class.forName("com.ibm.db2.jcc.DB2Driver");
try (Connection conn = DriverManager.getConnection("jdbc:db2://9.30.251.58:50000/sample", "db2inst1" , "N1cetest")) {
conn.setAutoCommit(false);
String sql1 = "insert into t6 values (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql1)) {
ps.setInt(1, 1);
ps.setString(2, "abcdefg");
ps.executeUpdate();
System.out.println("1111111");
ps.setInt(1, 1);
ps.setString(2, "abcdefghijk");
ps.executeUpdate();
System.out.println("2222222");
ps.setInt(1, 1);
ps.setString(2, "hijklmn");
ps.executeUpdate();
System.out.println("3333333");
conn.commit();
}
}
}
}
运行程序,报错如下:
1111111
Exception in thread "main" com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
at com.ibm.db2.jcc.am.kd.a(kd.java:802)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:140)
at com.ibm.db2.jcc.am.sp.b(sp.java:2447)
at com.ibm.db2.jcc.am.sp.c(sp.java:2430)
at com.ibm.db2.jcc.t4.bb.m(bb.java:415)
at com.ibm.db2.jcc.t4.bb.a(bb.java:62)
at com.ibm.db2.jcc.t4.p.a(p.java:50)
at com.ibm.db2.jcc.t4.wb.b(wb.java:220)
at com.ibm.db2.jcc.am.tp.uc(tp.java:3567)
at com.ibm.db2.jcc.am.tp.a(tp.java:4613)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.a(tp.java:4798)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.mc(tp.java:817)
at com.ibm.db2.jcc.am.tp.executeUpdate(tp.java:791)
at testJDBC.Test0207.main(Test0207.java:26)
Suppressed: com.ibm.db2.jcc.am.SqlException: [jcc][t4][10251][10308][4.21.29] java.sql.Connection.close() requested while a transaction is in progress on the connection.
The transaction remains active, and the connection cannot be closed. ERRORCODE=-4471, SQLSTATE=null
at com.ibm.db2.jcc.am.kd.a(kd.java:794)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:133)
at com.ibm.db2.jcc.am.Connection.checkForTransactionInProgress(Connection.java:1457)
at com.ibm.db2.jcc.t4.b.checkForTransactionInProgress(b.java:7374)
at com.ibm.db2.jcc.am.Connection.closeResourcesX(Connection.java:1480)
at com.ibm.db2.jcc.am.Connection.closeX(Connection.java:1466)
at com.ibm.db2.jcc.am.Connection.close(Connection.java:1443)
at testJDBC.Test0207.main(Test0207.java:36)
使用Mybatis框架来做insert操作:
package testMybatis;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class Test0207 {
public static void main(String[] args) throws Exception {
MyObject obj = new MyObject();
obj.setC1(1);
obj.setC2("abcdefghijk");
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
Test0207Mapper mapper = sqlSession.getMapper(Test0207Mapper.class);
mapper.insert(obj);
sqlSession.close();
}
}
运行程序,报错如下:
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
### The error may exist in testMybatis/Test0207Mapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: insert into t6 values (?, ?)
### Cause: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:196)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:181)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62)
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at com.sun.proxy.$Proxy4.insert(Unknown Source)
at testMybatis.Test0207.main(Test0207.java:28)
Caused by: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
at com.ibm.db2.jcc.am.kd.a(kd.java:802)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:140)
at com.ibm.db2.jcc.am.sp.b(sp.java:2447)
at com.ibm.db2.jcc.am.sp.c(sp.java:2430)
at com.ibm.db2.jcc.t4.bb.m(bb.java:415)
at com.ibm.db2.jcc.t4.bb.a(bb.java:62)
at com.ibm.db2.jcc.t4.p.a(p.java:50)
at com.ibm.db2.jcc.t4.wb.b(wb.java:220)
at com.ibm.db2.jcc.am.tp.uc(tp.java:3567)
at com.ibm.db2.jcc.am.tp.a(tp.java:4613)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.a(tp.java:4798)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.oc(tp.java:2870)
at com.ibm.db2.jcc.am.tp.execute(tp.java:2845)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194)
... 6 more
相比前面的JDBC程序:
运行结果:
package testMybatis;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class Test0207_2 {
public static void main(String[] args) throws Exception {
MyObject obj = new MyObject();
obj.setC1(1);
obj.setC2("abcdefg");
MyObject obj2 = new MyObject();
obj2.setC1(1);
obj2.setC2("abcdefghijk");
MyObject obj3 = new MyObject();
obj3.setC1(1);
obj3.setC2("hijklmn");
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession(false);
Test0207Mapper mapper = sqlSession.getMapper(Test0207Mapper.class);
try {
mapper.insert(obj);
System.out.println("1111111");
} catch (Exception e) {
e.printStackTrace();
}
try {
mapper.insert(obj2);
System.out.println("2222222");
} catch (Exception e) {
e.printStackTrace();
}
try {
mapper.insert(obj3);
System.out.println("3333333");
} catch (Exception e) {
e.printStackTrace();
}
sqlSession.commit();
sqlSession.close();
}
}
运行程序,报错如下:
1111111
org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
### The error may exist in testMybatis/Test0207Mapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: insert into t6 values (?, ?)
### Cause: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:196)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:181)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62)
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at com.sun.proxy.$Proxy4.insert(Unknown Source)
at testMybatis.Test0207_2.main(Test0207_2.java:46)
Caused by: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
at com.ibm.db2.jcc.am.kd.a(kd.java:802)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:140)
at com.ibm.db2.jcc.am.sp.b(sp.java:2447)
at com.ibm.db2.jcc.am.sp.c(sp.java:2430)
at com.ibm.db2.jcc.t4.bb.m(bb.java:415)
at com.ibm.db2.jcc.t4.bb.a(bb.java:62)
at com.ibm.db2.jcc.t4.p.a(p.java:50)
at com.ibm.db2.jcc.t4.wb.b(wb.java:220)
at com.ibm.db2.jcc.am.tp.uc(tp.java:3567)
at com.ibm.db2.jcc.am.tp.a(tp.java:4613)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.a(tp.java:4798)
at com.ibm.db2.jcc.am.tp.b(tp.java:4173)
at com.ibm.db2.jcc.am.tp.oc(tp.java:2870)
at com.ibm.db2.jcc.am.tp.execute(tp.java:2845)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194)
... 6 more
3333333
使用Mybatis的batch insert:
org.apache.ibatis.exceptions.PersistenceException
,它并不包含具体的错误信息,只是说提交事务出错了。其cause( org.apache.ibatis.executor.BatchExecutorException
)提示 testMybatis.Test0207Mapper.insert
(即mapper里所定义的接口方法)操作有错。它的cause( com.ibm.db2.jcc.am.BatchUpdateException
)提示说batch操作中有异常,使用 getNextException()
方法来获取具体异常。所以:
PersistenceException.getCause()
-> BatchExecutorException.getCause()
-> BatchUpdateException.getNextException()
-> SqlDataException
此处才有真正的错误原因================
所分隔的信息testMybatis.Test0207Mapper.insert (batch index #1) failed
这句话里的 batch index #1
我没有理解是什么意思。本来我以为它指示了batch操作中的第几条SQL有错,但经过试验发现,不管第几条SQL有错,log里始终显示 #1
。此处待查Error for batch element #2
原先我以为是insert操作的第2个元素有问题,但经过试验发现,这个 #2
才是表明了batch操作中的第几条SQL有错,此处的 2
表明是第2个SQL有错package testMybatis;
import java.io.InputStream;
import java.sql.SQLException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.ibm.db2.jcc.am.BatchUpdateException;
public class Test0207_3 {
public static void main(String[] args) throws Exception {
MyObject obj = new MyObject();
obj.setC1(1);
obj.setC2("abcdefg");
MyObject obj2 = new MyObject();
obj2.setC1(1);
obj2.setC2("abcdefghijk");
MyObject obj3 = new MyObject();
obj3.setC1(1);
obj3.setC2("hijklmn");
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
Test0207Mapper mapper = sqlSession.getMapper(Test0207Mapper.class);
try {
mapper.insert(obj);
System.out.println("1111111");
} catch (Exception e) {
e.printStackTrace();
}
try {
mapper.insert(obj2);
System.out.println("2222222");
} catch (Exception e) {
e.printStackTrace();
}
try {
mapper.insert(obj3);
System.out.println("3333333");
} catch (Exception e) {
e.printStackTrace();
}
try {
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
System.out.println("================");
Throwable cause = e.getCause().getCause();
if (cause instanceof BatchUpdateException) {
SQLException e2 = ((BatchUpdateException)cause).getNextException();
e2.printStackTrace();
}
}
sqlSession.close();
}
}
运行程序,报错如下:
1111111
2222222
3333333
org.apache.ibatis.exceptions.PersistenceException:
### Error committing transaction. Cause: org.apache.ibatis.executor.BatchExecutorException: testMybatis.Test0207Mapper.insert (batch index #1) failed. Cause: com.ibm.db2.jcc.am.BatchUpdateException: [jcc][t4][102][10040][4.21.29] Batch failure. The batch was submitted, but at least one exception occurred on an individual member of the batch.
Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null
### Cause: org.apache.ibatis.executor.BatchExecutorException: testMybatis.Test0207Mapper.insert (batch index #1) failed. Cause: com.ibm.db2.jcc.am.BatchUpdateException: [jcc][t4][102][10040][4.21.29] Batch failure. The batch was submitted, but at least one exception occurred on an individual member of the batch.
Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null
================
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:223)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:214)
at testMybatis.Test0207_3.main(Test0207_3.java:64)
Caused by: org.apache.ibatis.executor.BatchExecutorException: testMybatis.Test0207Mapper.insert (batch index #1) failed. Cause: com.ibm.db2.jcc.am.BatchUpdateException: [jcc][t4][102][10040][4.21.29] Batch failure. The batch was submitted, but at least one exception occurred on an individual member of the batch.
Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null
at org.apache.ibatis.executor.BatchExecutor.doFlushStatements(BatchExecutor.java:149)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:129)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:122)
at org.apache.ibatis.executor.BaseExecutor.commit(BaseExecutor.java:242)
at org.apache.ibatis.executor.CachingExecutor.commit(CachingExecutor.java:119)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:220)
... 2 more
Caused by: com.ibm.db2.jcc.am.BatchUpdateException: [jcc][t4][102][10040][4.21.29] Batch failure. The batch was submitted, but at least one exception occurred on an individual member of the batch.
Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null
at com.ibm.db2.jcc.am.kd.a(kd.java:502)
at com.ibm.db2.jcc.am.Agent.endBatchedReadChain(Agent.java:416)
at com.ibm.db2.jcc.am.tp.a(tp.java:5328)
at com.ibm.db2.jcc.am.tp.c(tp.java:4915)
at com.ibm.db2.jcc.am.tp.executeBatch(tp.java:3048)
at org.apache.ibatis.executor.BatchExecutor.doFlushStatements(BatchExecutor.java:123)
... 7 more
com.ibm.db2.jcc.am.SqlDataException: Error for batch element #2: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.21.29
at com.ibm.db2.jcc.am.kd.a(kd.java:802)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:140)
at com.ibm.db2.jcc.t4.bb.a(bb.java:574)
at com.ibm.db2.jcc.t4.bb.a(bb.java:70)
at com.ibm.db2.jcc.t4.p.a(p.java:57)
at com.ibm.db2.jcc.t4.wb.a(wb.java:225)
at com.ibm.db2.jcc.am.tp.a(tp.java:3573)
at com.ibm.db2.jcc.am.tp.d(tp.java:5825)
at com.ibm.db2.jcc.am.tp.a(tp.java:5259)
at com.ibm.db2.jcc.am.tp.c(tp.java:4915)
at com.ibm.db2.jcc.am.tp.executeBatch(tp.java:3048)
at org.apache.ibatis.executor.BatchExecutor.doFlushStatements(BatchExecutor.java:123)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:129)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:122)
at org.apache.ibatis.executor.BaseExecutor.commit(BaseExecutor.java:242)
at org.apache.ibatis.executor.CachingExecutor.commit(CachingExecutor.java:119)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:220)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:214)
at testMybatis.Test0207_3.main(Test0207_3.java:64)