Соединение не может быть передано в oracle.jdbc.OracleConnection
Почему java.sql.Connection не может быть передан в oracle.jdbc.OracleConnection в коде ниже?
Моя главная цель - перейти к новому имени пользователя для подключения к Oracle и сохранить его в таблице "SESSION", например, в столбце "osuser", потому что я хочу отслеживать в пользовательских изменениях БД и отображать их в таблице.
@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] [email protected]b
10:42:51,701 ERROR [STDERR] java.lang.ClassCastException: $Proxy286 cannot be cast to oracle.jdbc.OracleConnection
Как правило, у меня есть 2 проблемы в этом случае:
- почему сбрасывается из Connection to OracleConnection и
- Каков наилучший способ реализации моего намерения (я имею в виду установить новое имя пользователя для v $session.osuser в Oracle DB?
Я работаю с Oracle 11g, Hibernate (используя диспетчер сущностей), источником данных через jndi.
Пожалуйста, помогите, спасибо!
EDIT:
После некоторого улучшения проблема с кастингом все еще существует.
Улучшение:
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
Ответы
Ответ 1
Соединение, которое вы извлекаете, возможно, это завернутое соединение.
Если вам действительно нужно получить базовое соединение с Oracle, вы должны использовать:
if (connection.isWrapperFor(OracleConnection.class)){
OracleConnection oracleConnection= connection.unwrap(OracleConnection.class);
}else{
// recover, not an oracle connection
}
Методы isWrapperFor
и unwrap
доступны начиная с Java 1.6 и должны быть осмысленно реализованы оболочками соединения A/S.
Ответ 2
Пул соединений обычно имеет оболочку вокруг реального экземпляра подключения, поэтому почему ваш листинг не работает.
То, что вы делаете, не будет работать, потому что параметры в экземпляре свойств проверяются только при установлении соединения. Поскольку у вас есть уже действующее соединение, это ничего не изменит.
Вам нужно использовать DBMS_APPLICATION_INFO.SET_CLIENT_INFO()
, чтобы изменить это для существующего соединения.
Ответ 3
Это просто для людей, которые приходят сюда через поиск по настройке показателей в 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, но я сталкиваюсь с проблемой diff при настройке показателей:
short zero = 0;
oraConnection.setEndToEndMetrics(metrics, zero);
После проксирования соединения через мой метод, когда я устанавливаю метрики несколько раз, я получаю:
java.sql.SQLRecoverableException: No more data to read from socket
Но я думаю, что это связано с некоторыми проводниками проводки Spring или пулом соединений.
Ответ 4
Я столкнулся с этой проблемой при использовании spring для подключения. Как правило, каждый слой добавляет обертку поверх базовых классов. Я только что сделал connection.getClass(). getName(), чтобы просмотреть тип среды выполнения перенастройки. Это будет Wrapper/proxy, над которым вы можете легко найти метод для получения базового типа OracleConnection.
Ответ 5
Вы можете получить доступ к внутреннему объекту OracleObject внутри Wrapper, в этом случае оболочка
type - NewProxyConnection:
(Я использовал его в своем проекте, он работал... нет mistery, просто используйте отражение)
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;
}
Ответ 6
Попробуйте выполнить
Я столкнулся с той же проблемой. Мы использовали spring, и у него есть класс, называемый
NativeJdbcExtractor. Он имеет множество реализаций, и для TomCat работает один из них. Для Jboss существует определенная реализация, называемая JBossNativeJdbcExtractor
<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean>
В вашем DAO вы можете ввести bean и использовать следующий метод
protected NativeJdbcExtractor jdbcExtractor;
Connection conn=jdbcExtractor.getNativeConnection(oracleConnection);
Ответ 7
Не уверен, что моя ситуация связана, но с моим проектом просто изменение настройки конфигурации базы данных на самом деле приводит к отказу!
Я использую платформу Play с Scala; это работает для меня только тогда, когда logSql = false:
db.withConnection { implicit c =>
val oracleConnection = c.unwrap(classOf[OracleConnection])
}
(это только версия Scala для развертывания OracleConnection)
Когда я устанавливаю logSql = true, я получаю:
com.sun.proxy. $Proxy17 нельзя передать в oracle.jdbc.OracleConnection java.lang.ClassCastException: com.sun.proxy. $Proxy17 не может быть отброшен oracle.jdbc.OracleConnection
Итак, что-то об конфигурации logSql может привести к сбою разворота. Не знаю, почему.
С любой конфигурацией мой объект подключения:
HikariProxyConnection @1880261898 упаковка [email protected]
isWrapperFor(OracleConnection)
истинно в обоих случаях
Это происходит с пулом соединений Hikari и Bone CP. Может быть, это ошибка в Oracle JDBC?
Версия драйвера JDBC Oracle в соответствии с MANIFEST.MF
Реализация-Версия: 11.2.0.3.0
Идентификатор репозитория: JAVAVM_11.2.0.4.0_LINUX.X64_130711
Ответ 8
После проб и ошибок. Этот способ работает:
DelegatingConnection delConnection = new DelegatingConnection(dbcpConnection);
oraConnection = (oracle.jdbc.OracleConnection)delConnection.getInnermostDelegate();
Но этот путь вернул нулевой указатель для oraConnection:
DelegatingConnection delConnection = (DelegatingConnection) dbcpConnection;
oraConnection = (oracle.jdbc.OracleConnection)delConnection.getInnermostDelegate();
Ответ 9
Следующее работало, чтобы обойти 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 è
Теперь я мог бы использовать это в AQ- Factory без JMS-112
Ответ 10
попробуйте выполнить кастинг, как показано ниже
WrappedConnectionJDK6 wc = (WrappedConnectionJDK6) connection;
connection = wc.getUnderlyingConnection();