Java 无法将连接转换为oracle.jdbc.OracleConnection
为什么java.sql.Connection不能在下面的代码中转换为oracle.jdbc.OracleConnection 我的主要目标是将新用户名传递给Oracle connection,并将其保存在例如“osuser”列中的“SESSION”表中,因为我希望跟踪数据库中的用户更改,并将其显示在表中Java 无法将连接转换为oracle.jdbc.OracleConnection,java,oracle,hibernate,jdbc,jndi,Java,Oracle,Hibernate,Jdbc,Jndi,为什么java.sql.Connection不能在下面的代码中转换为oracle.jdbc.OracleConnection 我的主要目标是将新用户名传递给Oracle connection,并将其保存在例如“osuser”列中的“SESSION”表中,因为我希望跟踪数据库中的用户更改,并将其显示在表中 @Repository public class AuditLogDAOImpl implements AuditLogDAO { @PersistenceContext(unitNa
@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
在这种情况下,我通常有两个问题:
- 为什么从连接到OracleConnection的强制转换失败,以及
- 实现我的意图的最佳方法是什么(我的意思是在Oracle DB中将新用户名设置为v$session.osuser)
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
连接池通常在实际连接实例周围有一个包装器,这就是您的强制转换失败的原因 无论如何,您所做的不会起作用,因为只有在建立连接时才会检查properties实例中的参数。因为您有一个已处于活动状态的连接,所以它不会更改任何内容
您需要使用tou来更改现有连接的连接。我在使用spring获取连接时遇到了这个问题。通常,每个层都会在基本类上添加一个包装器。我刚刚完成了connection.getClass().getName()查看正在重新调整的连接的运行时类型。它将是一个包装器/代理,您可以通过它轻松找到获取基本OracleConnection类型的方法。您正在检索的连接可能是一个已包装的连接 如果确实需要获得底层Oracle连接,则应使用:
if (connection.isWrapperFor(OracleConnection.class)){
OracleConnection oracleConnection= connection.unwrap(OracleConnection.class);
}else{
// recover, not an oracle connection
}
自Java 1.6以来,isWrapperFor
和unwrap
方法都可用,并且应该由A/S连接包装器有意义地实现
我也遇到了同样的问题。我们使用spring,它有一个名为
NativeJdbcExtractor。它有许多实现,下面的一个适用于TomCat。Jboss有一个特定的实现,称为JBossNativeJdbcExtractor
<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean>
这只是为那些通过搜索来这里了解如何在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 wiring init或连接池有关。您可以访问包装器中的内部OracleObject,在本例中是包装器 类型为NewProxyConnection:
DelegatingConnection delConnection = (DelegatingConnection) dbcpConnection;
oraConnection = (oracle.jdbc.OracleConnection)delConnection.getInnermostDelegate();
(我在我的项目中使用过它,它很有效……没有迷雾,只是使用反射)
试着像下面这样铸造
WrappedConnectionJDK6 wc = (WrappedConnectionJDK6) connection;
connection = wc.getUnderlyingConnection();
下面介绍了AQ的TopicConnection.getTopicSession=>JMS-112
//调试:本机数据源:weblogic.jdbc.common.internal.RmiDataSource
con=DataSource.getConnection();
调试(“通用SQL连接:+con.toString());
//调试:通用连接:weblogic.jdbc.wrapper.PoolConnection\u oracle\u jdbc\u driver\u T4C连接
if(con!=null&&con.isWrapperFor(OracleConnection.class)){
WebLogicNativeJdbcExtractor wlne=新建WebLogicNativeJdbcExtractor();//org.springframework拯救!!
java.sql.Connection nativeCon=wlne.getNativeConnection(con);
this.oraConnection=(OracleConnection)nativeCon;
调试(“展开SQL连接:+this.oraConnection.toString());
}
//调试:本机连接:oracle.jdbc.driver.T4CConnectionè
现在我可以在AQ工厂中使用它了,不知道我的情况是否相关,但是对于我的项目,仅仅更改数据库配置设置实际上会导致展开失败 我将Play框架与Scala一起使用;这只在以下情况下对我有效:
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
因此,有关“展开”的某些内容实际上可能会导致“展开”失败。不知道为什么
无论是哪种配置,我的连接对象都是:
HikariProxyConnection@1880261898包装
oracle.jdbc.driver。T4CConnection@6b28f065
isWrapperFor(OracleConnection)
在这两种情况下都是正确的
这种情况发生在Hikari连接池和Bone CP中。也许这是Oracle JDBC中的一个bug
符合MANIFEST.MF的Oracle JDBC驱动程序版本
实施版本:11.2.0.3.0存储库Id:JAVAVM_11.2.0.4.0_LINUX.X64_130711 经过反复试验。 这种方式有效:
DelegatingConnection delConnection = new DelegatingConnection(dbcpConnection);
oraConnection = (oracle.jdbc.OracleConnection)delConnection.getInnermostDelegate();
但这种方式为oraConnection返回了一个空指针:
DelegatingConnection delConnection = (DelegatingConnection) dbcpConnection;
oraConnection = (oracle.jdbc.OracleConnection)delConnection.getInnermostDelegate();
如果您从ClassCastException打印出异常消息,它将告诉您连接对象的实际类是什么。这将帮助您(和我们)理解强制转换失败的原因。找到它是什么对象-通常是System.out.println(连接)连接中的对象是org.jboss.resource.adapter.jdbc.jdk6.wrappedconnectionjdk6如果我理解正确,我可以通过两种方式实现我的目标:1)编辑现有连接(通过
DBMS\u应用程序\u信息。设置\u客户端\u信息()
或2)在连接建立过程中添加用户名,对吗?关于在hibernate中实现这种方法的第二种方法,因为我没有手动创建连接(我已经配置了EntityManagerFactory,并注入了hibernate bean)?@Roman:对不起,我不知道如何配置hibernate。但是,如果使用例如Tomcat的连接池,则可以指定附加属性。手册中记录了具体需要如何完成
DelegatingConnection delConnection = (DelegatingConnection) dbcpConnection;
oraConnection = (oracle.jdbc.OracleConnection)delConnection.getInnermostDelegate();