使用web服务器配置jndi时怎么在项目中取出原生的OracleConnection
使用web服务器配置jndi时如何在项目中取出原生的OracleConnection
当我们使用web服务器配置JNDI,而在项目中使用dataSource.getConnection()时取出的链接往往是经过web容器包装后的Connection,如Websphere包装后的连接是com.ibm.ws.rsadapter.jdbc.WSJdbcConnection,但在应用中有时需要使用原生的OracleConnection(包括其子类)来进行特定的操作,比如使用Oracle AQ时就必须要用OracleConnection。本文将简单的介绍如何对取出的连接进行转换获取需要的连接,以及在tomcat下如何配置,让取出的Connection就是OracleConnection家的。
1.对取出的连接进行转换获取需要的连接
当然你可以自己编写代码,不过这件事spring已经帮忙解决了,spring提供的NativeJdbcExtractor可以很出色的完成这个任务,针对不同的web服务器有不同的实现类:
下面一段简单的代码是依靠NativeJdbcExtractor为Oracle AQ获取原生的OracleConnection
当然如果你的项目中使用了Oracle AQ,完全不需要这么做,你可以使用以下代码:
既然是这样,那么我给出上面那段简单代码是什么用意呢?也许你已经发现上面那段代码在获取连接时并没有使用dataSource.getConnection(),而使用的是DataSourceUtils.getConnection(this.dataSource),这么做的目的是为了防止连接泄漏,这篇文章里有很好的讲解http://www.ibm.com/developerworks/cn/java/j-lo-spring-ts3/,我在这里点出来是为了大家更好的学习。
2.在tomcat下如何配置,让取出的Connection就是OracleConnection?
我们一般在tomcat下配置jndi会使用下面的方式:
这样配置在使用时不经转换就会报错:
(图中的oracle.jdbc.internal.OracleConnection extends oracle.jdbc.OracleConnection)
如果要让取出的连接不经转换就是Oracle的Connection,需要把type和driverClassName改成oracle.jdbc.pool.OracleDataSource,factory默认是org.apache.commons.dbcp.BasicDataSourceFactory,改成oracle.jdbc.pool.OracleDataSourceFactory,这时你再测试就会报错:用户名或密码错误,这个问题很奇怪,需要把上面的username改成user,至于为什么,没有找到相关的文档说明。
修改之后的配置如下:
当我们使用web服务器配置JNDI,而在项目中使用dataSource.getConnection()时取出的链接往往是经过web容器包装后的Connection,如Websphere包装后的连接是com.ibm.ws.rsadapter.jdbc.WSJdbcConnection,但在应用中有时需要使用原生的OracleConnection(包括其子类)来进行特定的操作,比如使用Oracle AQ时就必须要用OracleConnection。本文将简单的介绍如何对取出的连接进行转换获取需要的连接,以及在tomcat下如何配置,让取出的Connection就是OracleConnection家的。
1.对取出的连接进行转换获取需要的连接
当然你可以自己编写代码,不过这件事spring已经帮忙解决了,spring提供的NativeJdbcExtractor可以很出色的完成这个任务,针对不同的web服务器有不同的实现类:
下面一段简单的代码是依靠NativeJdbcExtractor为Oracle AQ获取原生的OracleConnection
package com.lc.oracle.aq; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.sql.DataSource; import oracle.jdbc.OracleConnection; import oracle.jms.AQjmsQueueConnectionFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; public class OracleAQConnectionFactory implements ConnectionFactory { protected static final Logger logger = LoggerFactory.getLogger(OracleAQConnectionFactory.class); private DataSource dataSource; private NativeJdbcExtractor nativeJdbcExtractor; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) { this.nativeJdbcExtractor = nativeJdbcExtractor; } @Override public javax.jms.Connection createConnection() throws JMSException { java.sql.Connection con = DataSourceUtils.getConnection(this.dataSource); java.sql.Connection conToUse = con; if (!(con instanceof OracleConnection)) { if (logger.isDebugEnabled()) { logger.debug("Unwrapping JDBC Connection of type:" + con.getClass().getName()); } try { conToUse = (OracleConnection) this.nativeJdbcExtractor.getNativeConnection(con); if (logger.isDebugEnabled()) { logger.debug("Using Native JDBC Connection [" + conToUse + "]"); } } catch (Exception e) { throw new RuntimeException("Error unwrapping the Oracle Connection: " + e.getMessage(), e); } } return AQjmsQueueConnectionFactory.createQueueConnection(conToUse); } @Override public javax.jms.Connection createConnection(String username, String password) throws JMSException { throw new UnsupportedOperationException("creating connection with explicit username/password not supported"); } }
当然如果你的项目中使用了Oracle AQ,完全不需要这么做,你可以使用以下代码:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/test" proxy-interface="javax.sql.DataSource" /> <!-- Oracle Advanced Queue Connection Factory --> <orcl:aq-jms-connection-factory id="connectionFactory" connection-factory-type="QUEUE_CONNECTION" data-source="dataSource" native-jdbc-extractor="webSphereNativeJdbcExtractor" use-local-data-source-transaction="true" /> <!-- Jdbc Extractor --> <bean id="webSphereNativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.WebSphereNativeJdbcExtractor" />
既然是这样,那么我给出上面那段简单代码是什么用意呢?也许你已经发现上面那段代码在获取连接时并没有使用dataSource.getConnection(),而使用的是DataSourceUtils.getConnection(this.dataSource),这么做的目的是为了防止连接泄漏,这篇文章里有很好的讲解http://www.ibm.com/developerworks/cn/java/j-lo-spring-ts3/,我在这里点出来是为了大家更好的学习。
2.在tomcat下如何配置,让取出的Connection就是OracleConnection?
我们一般在tomcat下配置jndi会使用下面的方式:
<Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource" username="dbusername" password="dbpassword" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@ip:1521:orcl" maxActive="100" maxIdle="10" maxWait="10000"/>
这样配置在使用时不经转换就会报错:
(图中的oracle.jdbc.internal.OracleConnection extends oracle.jdbc.OracleConnection)
如果要让取出的连接不经转换就是Oracle的Connection,需要把type和driverClassName改成oracle.jdbc.pool.OracleDataSource,factory默认是org.apache.commons.dbcp.BasicDataSourceFactory,改成oracle.jdbc.pool.OracleDataSourceFactory,这时你再测试就会报错:用户名或密码错误,这个问题很奇怪,需要把上面的username改成user,至于为什么,没有找到相关的文档说明。
修改之后的配置如下:
<Resource name="jdbc/test" auth="Container" type="oracle.jdbc.pool.OracleDataSource" factory="oracle.jdbc.pool.OracleDataSourceFactory" user="dbusername" password="dbpassword" driverClassName="oracle.jdbc.pool.OracleDataSource" url="jdbc:oracle:thin:@ip:1521:orcl" maxActive="100" maxIdle="10" maxWait="10000"/>