无法将连接强制转换为oracle.jdbc.OracleConnection
为什么java.sql.Connection无法在下面的代码中强制转换为oracle.jdbc.OracleConnection?
我的主要目标是传递给Oracle连接新用户名并将其保存在例如’osuser’列的’SESSION’表中,因为我想跟踪数据库用户更改并在表中显示它。
@Repository public class AuditLogDAOImpl implements AuditLogDAO { @PersistenceContext(unitName="myUnitName") EntityManager em; @Resource(name = "dataSource") DataSource dataSource; public void init() { try { Connection connection = DataSourceUtils.getConnection(dataSource); OracleConnection oracleConnection = (OracleConnection) connection; //Here I got cast exception! String metrics[] = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX]; metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = "my_new_username"; oracleConnection.setEndToEndMetrics(metrics, (short) 0); java.util.Properties props = new java.util.Properties(); props.put("osuser", "newValue"); oracleConnection.setClientInfo(props); } catch (SQLException e) { e.printStackTrace(); } } }
这是错误日志:
10:42:29,251 INFO [STDOUT] org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6@bcc8cb 10:42:51,701 ERROR [STDERR] java.lang.ClassCastException: $Proxy286 cannot be cast to oracle.jdbc.OracleConnection
通常我在这种情况下有2个问题:
- 为什么从Connection到OracleConnection的转换失败了
- 实现我的意图的最佳方法是什么(我的意思是在Oracle DB中将新用户名设置为v $ session.osuser?
我通过jndi使用Oracle 11g,Hibernate(使用实体管理器),数据源。
请帮忙,谢谢!
编辑:
经过一些改进后,铸造问题仍然存在。
改进:
Connection connection = DataSourceUtils.getConnection(dataSource); connection = ((org.jboss.resource.adapter.jdbc.WrappedConnection)connection).getUnderlyingConnection(); OracleConnection oracleConnection = (OracleConnection) connection;
错误:
java.lang.ClassCastException: $Proxy287 cannot be cast to org.jboss.resource.adapter.jdbc.WrappedConnection
您正在检索的连接可能是一个包装连接。
如果您确实需要获得底层Oracle连接,则应使用:
if (connection.isWrapperFor(OracleConnection.class)){ OracleConnection oracleConnection= connection.unwrap(OracleConnection.class); }else{ // recover, not an oracle connection }
isWrapperFor
和isWrapperFor
方法自Java 1.6起可用,并且应该由A / S连接包装器有意义地实现。
连接池通常在真实连接实例周围有一个包装器,这就是你的转换失败的原因。
您正在做的事情无论如何都无法工作,因为只有在建立连接时才会检查属性实例中的参数。 由于您的连接已处于活动状态,因此不会更改任何内容。
您需要使用DBMS_APPLICATION_INFO.SET_CLIENT_INFO()
来更改现有连接。
这只适用于通过搜索如何在OracleConnection中设置指标的人来到这里,我花了很多时间在这上面,所以可能会帮助别人。
获得“连接”后,这应该有效:
DatabaseMetaData dmd = connection.getMetaData(); Connection metaDataConnection = null; if(dmd != null) { metaDataConnection = dmd.getConnection(); } if(!(metaDataConnection instanceof OracleConnection)) { log.error("Connection is not instance of OracleConnection, returning"); return; /* Not connection u want */ } OracleConnection oraConnection = (OracleConnection)metaDataConnection; String[] metrics = new String[END_TO_END_STATE_INDEX_MAX]; // Do the rest below...
它适用于OracleConnection,但在设置指标时我遇到了差异问题:
short zero = 0; oraConnection.setEndToEndMetrics(metrics, zero);
通过我的方法代理连接后,我设置了几次指标,我得到:
java.sql.SQLRecoverableException: No more data to read from socket
但我认为它与一些Spring接线或连接池有关。
当我使用spring来获取连接时,我遇到了这个问题。 通常,每个层都在基本类上添加一个包装器。 我刚刚完成了connection.getClass()。getName()来查看正在重新调整的连接的运行时类型。 它将是一个包装器/代理,您可以通过它轻松找到获取基本OracleConnection类型的方法。
您可以访问Wrapper中的内部OracleObject,在这种情况下,包装类型是NewProxyConnection:
(我在我的项目中使用它,它工作……没有谜,只是使用reflection)
Field[] fieldsConn= connection.getClass().getDeclaredFields(); Object innerConnObject = getFieldByName(fieldsConn,"inner").get(connection); if(innerConnObject instanceof OracleConnection ){ OracleConnection oracleConn = (OracleConnection)innerConnObject; //OracleConnection unwrap = ((OracleConnection)innerConnObject).unwrap(); // now you have the OracleObject that the Wrapper } //Method: Set properties of the ooject accessible. public static Field getFieldByName(Field[] campos, String name) { Field f = null; for (Field campo : campos) { campo.setAccessible(true); if (campo.getName().equals(name)) { f = campo; break; } } return f; }
请尝试以下方法
我遇到过同样的问题。 我们使用spring,它有一个名为NativeJdbcExtractor的类。 它有许多实现,以下一个适用于TomCat。 Jboss有一个特定的实现叫做JBossNativeJdbcExtractor
在DAO中,您可以注入bean并使用以下方法
protected NativeJdbcExtractor jdbcExtractor; Connection conn=jdbcExtractor.getNativeConnection(oracleConnection);
不确定我的情况是否相关,但是对于我的项目,只需更改数据库配置设置实际上会导致解包失败!
我正在使用Scala的Play框架; 这只适用于logSql = false时 :
db.withConnection { implicit c => val oracleConnection = c.unwrap(classOf[OracleConnection]) }
(这只是解开OracleConnection的Scala版本)
当我设置logSql = true时 ,我得到:
com.sun.proxy。$ Proxy17无法强制转换为oracle.jdbc.OracleConnection java.lang.ClassCastException:com.sun.proxy。$ Proxy17无法强制转换为oracle.jdbc.OracleConnection
所以关于logSql配置的一些事实上可能导致unwrap失败。 不知道为什么。
无论使用哪种配置,我的连接对象都是:
HikariProxyConnection @ 1880261898包装oracle.jdbc.driver.T4CConnection@6b28f065
isWrapperFor(OracleConnection)
在两种情况下都是正确的
这种情况发生在Hikari Connection Pool和Bone CP上。 也许这是Oracle JDBC中的一个错误?
根据MANIFEST.MF的 Oracle JDBC驱动程序版本
实现版本:11.2.0.3.0
存储库ID:JAVAVM_11.2.0.4.0_LINUX.X64_130711
以下是解决AQ的TopicConnection.getTopicSession => JMS-112的问题
//DEBUG: Native DataSource : weblogic.jdbc.common.internal.RmiDataSource con = DataSource.getConnection(); debug("Generic SQL Connection: " + con.toString()); //DEBUG: Generic Connection: weblogic.jdbc.wrapper.PoolConnection_oracle_jdbc_driver_T4CConnection if (con != null && con.isWrapperFor(OracleConnection.class)) { WebLogicNativeJdbcExtractor wlne = new WebLogicNativeJdbcExtractor();//org.springframework to the rescue!! java.sql.Connection nativeCon = wlne.getNativeConnection(con); this.oraConnection = (OracleConnection) nativeCon; debug("Unwrapp SQL Connection: " + this.oraConnection.toString()); } //DEBUG: Native Connection: oracle.jdbc.driver.T4CConnection è
现在我可以在没有JMS-112的AQ-Factory中使用它
尝试如下铸造
WrappedConnectionJDK6 wc = (WrappedConnectionJDK6) connection; connection = wc.getUnderlyingConnection();
- 在自动触发的默认侦听器之前,激活Hibernate自定义事件侦听器
- Hibernate 4 – 什么应该替换弃用的@MapKey来映射Map集合,而Key是一个自定义的Hibernate UserType
- Hibernate java.lang.OutOfMemoryError:Java堆空间
- 在持久化Hibernate之前自动设置bean值(列)?
- Hibernate没有在数据库中保存对象?
- Hibernate将NULL值粘贴到列表中
- 如何使用Hibernate Projection检索复杂的类及其成员?
- Spring-Hibernate – 找不到当前线程的Session
- Hibernate可以返回除List之外的结果对象的集合吗?