apache / incubator-seata

:fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.
https://seata.apache.org/
Apache License 2.0
25.25k stars 8.76k forks source link

oracle下使用seata,oracle驱动为ojdbc8:21以上时,使用java.sql.PreparedStatement#addBatch方法会报错 #4570

Open sixlei opened 2 years ago

sixlei commented 2 years ago

Ⅰ. Issue Description

代码类似于:

@GlobalTransactional
public void test(){
Connection connection = null;
            try {
                connection = dataSource.getConnection();
                PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO T_TEST(xxx) values (xxx));
                preparedStatement.setString(1,"123");
                preparedStatement.setString(2,"123");
                preparedStatement.addBatch();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
}

在整合ojdbc8:19.xxx版本的时候能正常使用,在整合21版本以上后,会报错, 21.1.0.0报的是“DML Returning cannot be batched”的异常。21.3.0.0以上报的是

 java.lang.NullPointerException: null
    at oracle.jdbc.driver.OraclePreparedStatement.registerReturnParamsForAutoKey(OraclePreparedStatement.java:11206)
    at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2009)
    at oracle.jdbc.driver.OraclePreparedStatement.addBatch(OraclePreparedStatement.java:9823)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.addBatch(OraclePreparedStatementWrapper.java:998)
    at com.p6spy.engine.wrapper.PreparedStatementWrapper.addBatch(PreparedStatementWrapper.java:377)
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.addBatch(HikariProxyPreparedStatement.java)
    at io.seata.rm.datasource.AbstractPreparedStatementProxy.addBatch(AbstractPreparedStatementProxy.java:232)
    at com.fingard.frisk.exposure.web.controller.test.TestCotroller.lambda$test4$2(TestCotroller.java:104)

Ⅴ. Anything else we need to know?

原因是seata在执行insert语句时,要拿到主键返回,所以执行的prepareStatement方法改成了 connection.prepareStatement("INSERT INTO T_TEST(xxx) values (xxx),new String[]{URID}); 代码位置是:io.seata.rm.datasource.AbstractConnectionProxy#prepareStatement(java.lang.String) 但是21以上执行带主键返回值的addbatch会直接报错。 该问题把ojdbc8降到19.xx能够解决。 但是seata能不能兼容ojdbc8:21.1.0.0以上版本的java.sql.PreparedStatement#addBatch方法

Ⅵ. Environment:

wuwen5 commented 6 months ago

ojdbc8:23版本驱动是支持的,23.3.0.23.09驱动测试正常,jdk8最低要求u161