有没有办法克服 DSRA9010E“WebSphere 不支持 'setReadOnly'”异常?

Is there a way to overcome DSRA9010E "'setReadOnly' is not supported on the WebSphere" exception?

我们的应用程序正在使用 Spring 进行交易管理,并将某些交易标记为只读。在使用 Oracle JDBC 连接在 websphere (8.5.5.3) 上部署我们的应用程序时,我们遇到如下异常:

Caused by: java.sql.SQLException: DSRA9010E: 'setReadOnly' is not supported on the WebSphere java.sql.Connection implementation.
    at com.ibm.ws.rsadapter.spi.InternalOracleDataStoreHelper.setReadOnly(InternalOracleDataStoreHelper.java:371)
    at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.setReadOnly(WSJdbcConnection.java:3646)
    at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.getTargetConnection(LazyConnectionDataSourceProxy.java:410)
    at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.invoke(LazyConnectionDataSourceProxy.java:376)
    at com.sun.proxy.$Proxy476.getMetaData(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:619)
    at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:239)
    at com.sun.proxy.$Proxy476.getMetaData(Unknown Source)

我知道 websphere 试图告诉我什么,但我想知道是否有办法禁用此检查,以便忽略 Connection.setReadonly 调用而不是抛出异常。

当然我也可以将应用程序更改为不使用只读事务,但那样会复杂得多。

尝试像这样打开 connection 对象:

Context ic = new InitialContext();
DataSource ds = (DataSource)ic.lookup("jdbc/OracleDS");
Connection conn = ds.getConnection();

if (conn.isWrapperFor(oracle.jdbc.OracleConnection.class)) {
     // Returns an object that implements the given interface to
     // allow access to non-standard methods, or standard methods
     // not exposed by the proxy.
     oracle.jdbc.OracleConnection oraCon = conn.unwrap(oracle.jdbc.OracleConnection.class);
     // Do some Oracle-specific work here.
     oraCon.setReadOnly(readOnly);
     ....

}
conn.close(); 

WebSphere Application Server and the JDBC 4.0 Wrapper Pattern

Oracle JDBC(从 12c 开始;也许还有 11g?)与 readonly 一起使用可能会很棘手 - 根据 https://marschall.github.io/2017/01/28/oracle-read-only.html:

Calling Connection.setReadOnly(true) with the 12c driver no longer establishes a read only transaction

这意味着 Spring(版本 4.3.7 之前)也难以使用 Oracle JDBC 设置只读事务(参见之前的 link)。

为了克服这个问题,您需要在 SQL 中手动包含 SET TRANSACTION READ ONLY,而不是依赖 Spring 的 @Transactional(readOnly=true)

但是,从 Spring 4.3.7 开始,事务现在可以正常运行,因此您应该不会再看到此问题 (https://github.com/spring-projects/spring-framework/issues/19774)