java - annotation - spring hibernate jndi
La conexión no se puede convertir en oracle.jdbc.OracleConnection (9)
¿Por qué java.sql.Connection no se puede convertir en oracle.jdbc.OracleConnection en el código a continuación?
Mi objetivo principal es pasar a la conexión de Oracle un nuevo nombre de usuario y guardarlo en la tabla ''SESIÓN'' en, por ejemplo, la columna ''osuser'' porque quiero rastrear en los cambios del usuario de BD y mostrarlo en la tabla.
@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();
}
}
}
Aquí está el registro de error:
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
Generalmente tengo 2 problemas en este caso:
- por qué el lanzamiento de Connection a OracleConnection falla y
- ¿Cuál es la mejor manera de implementar mi intención (me refiero a establecer el nuevo nombre de usuario en v $ session.osuser en Oracle DB?
Trabajo con Oracle 11g, Hibernate (usando el administrador de entidades), fuente de datos a través de jndi.
Por favor ayuda, gracias!
EDITAR:
Después de algunas mejoras, el problema con la fundición aún existe.
Mejora:
Connection connection = DataSourceUtils.getConnection(dataSource);
connection = ((org.jboss.resource.adapter.jdbc.WrappedConnection)connection).getUnderlyingConnection();
OracleConnection oracleConnection = (OracleConnection) connection;
Error:
java.lang.ClassCastException: $Proxy287 cannot be cast to org.jboss.resource.adapter.jdbc.WrappedConnection
El grupo de conexiones generalmente tiene un contenedor alrededor de la instancia de conexión real, es por eso que tu conversión falla.
Lo que está haciendo no funcionaría de todos modos, porque los parámetros en la instancia de propiedades solo se verifican cuando se establece la conexión. Como tiene una conexión que ya está activa, no cambiará nada.
Necesita usar tou DBMS_APPLICATION_INFO.SET_CLIENT_INFO()
para cambiar esto para una conexión existente.
La conexión que está recuperando es probablemente una conexión envuelta.
Si realmente necesita obtener la conexión Oracle subyacente, debe usar:
if (connection.isWrapperFor(OracleConnection.class)){
OracleConnection oracleConnection= connection.unwrap(OracleConnection.class);
}else{
// recover, not an oracle connection
}
Los métodos isWrapperFor
y isWrapperFor
están disponibles desde Java 1.6 y deben implementarse de manera significativa mediante los contenedores de conexión A / S.
Me he enfrentado a este problema cuando uso la primavera para obtener conexiones. Normalmente, cada capa agrega un contenedor sobre las clases básicas. Acabo de hacer connection.getClass (). getName () para ver el tipo de tiempo de ejecución de la conexión que se está restableciendo. Será un Wrapper / proxy sobre el cual podrá encontrar fácilmente el método para obtener el tipo OracleConnection base.
Pruebe lo siguiente
Me encontré con el mismo problema. Estábamos usando la primavera y tiene una clase llamada NativeJdbcExtractor. Tiene muchas implementaciones y la siguiente funciona para TomCat. Hay una implementación específica para Jboss llamada JBossNativeJdbcExtractor
<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean>
En tu DAO puedes inyectar el frijol y usar el siguiente método
protected NativeJdbcExtractor jdbcExtractor;
Connection conn=jdbcExtractor.getNativeConnection(oracleConnection);
Esto es solo para las personas que vienen aquí a través de la búsqueda sobre cómo establecer las métricas en OracleConnection. Dedico mucho tiempo a esto, por lo que podría ayudar a alguien.
Después de obtener su "conexión" esto debería funcionar:
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...
Funciona para mí para OracleConnection, pero enfrento el problema de la dificultad cuando establezco las métricas:
short zero = 0;
oraConnection.setEndToEndMetrics(metrics, zero);
Después de proxying conexión a través de mi método donde establezco métricas pocas veces, obtengo:
java.sql.SQLRecoverableException: No more data to read from socket
Pero creo que tiene que ver con algunos inits de cableado de primavera o grupo de conexiones.
Puede acceder al OracleObject interno dentro de un Wrapper, en este caso el tipo de envoltura es NewProxyConnection:
(Lo he usado en mi proyecto, funcionó ... no hay misterio, solo usa reflexión)
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;
}
prueba a lanzar como a continuación
WrappedConnectionJDK6 wc = (WrappedConnectionJDK6) connection;
connection = wc.getUnderlyingConnection();
Lo siguiente funcionó para evitar TopicConnection.getTopicSession => JMS-112 de AQ
//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 è
Ahora podría usar esto en AQ-Factory sin JMS-112
No estoy seguro de si mi situación está relacionada, pero con mi proyecto, simplemente cambiar la configuración de la base de datos hace que el desplegado falle.
Estoy usando Play framework con Scala; esto funciona solo cuando logSql = falso :
db.withConnection { implicit c =>
val oracleConnection = c.unwrap(classOf[OracleConnection])
}
(Esta es solo la versión de Scala de desenvolver una OracleConnection)
Cuando configuro logSql = verdadero , obtengo:
com.sun.proxy. $ Proxy17 no se puede convertir a oracle.jdbc.OracleConnection java.lang.ClassCastException: com.sun.proxy. $ Proxy17 no se puede convertir a oracle.jdbc.OracleConnection
Por lo tanto, algo sobre la configuración de logSql puede hacer que el desplegado falle. No tengo idea por qué.
Con cualquiera de las configuraciones, mi objeto de conexión es:
HikariProxyConnection @ 1880261898 envolviendo oracle.jdbc.driver.T4CConnection@6b28f065
isWrapperFor(OracleConnection)
es verdadero en ambos casos
Esto sucede con Hikari Connection Pool y Bone CP. Tal vez es un error en Oracle JDBC?
Versión de Oracle JDBC Driver según MANIFEST.MF
Versión de implementación: 11.2.0.3.0
Repository-Id: JAVAVM_11.2.0.4.0_LINUX.X64_130711