有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Oracle数据源连接池不能与Spring和JDBCTemplate一起使用

问题:大量与数据库的活动未关闭物理连接,即使使用连接池。有人能告诉我为什么会这样吗

我使用oracle.jdbc.pool.OracleDataSource配置了连接池设置。然而,使用后物理连接似乎没有关闭。 我想,因为它是连接池,连接将从池中重用,所以不会进行这么多物理连接, 但这不是现在发生的事情

数据库中有100多个从应用程序生成的活动物理连接[不是从plsql developer或任何此类客户端工具生成的], 因此,它在尝试对数据库执行写操作时引发TNS错误, 其中,即使有大量活动连接,读操作也可以

这是Spring的配置

<bean id="oracleDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close"
                                p:URL="${url}"
                                p:user="${username}"
                                p:password="${password}"
                                p:connectionCachingEnabled="true">
                                <property name="connectionProperties">
                                   <props merge="default">
                                      <prop key="AutoCommit">false</prop>
                                   </props>
                                </property>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
                                p:dataSource-ref="oracleDataSource" />

<bean id="transactionManager"
                                class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
                                p:dataSource-ref="oracleDataSource">
</bean>

返回100多个活动连接的SQL为

select username, terminal,schemaname, osuser,program from v$session where username = 'grduser'

共 (2) 个答案

  1. # 1 楼答案

    多亏了@Evgeny Dorofev

    解决方案详细信息:

    1. connectionCache已启用,但未设置属性。 设置如下所示的属性

    `

    <bean id="oracleDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close"
                                            p:URL="${url}"
                                            p:user="${username}"
                                            p:password="${password}"
                                            p:connectionCachingEnabled="true">
                                            <property name="connectionProperties">
                                               <props merge="default">
                                                  <prop key="AutoCommit">false</prop>
                                               </props>
                                            </property>
             <property name="connectionCacheProperties">
                        <props>
                            <prop key="MinLimit">5</prop>
                            <prop key="MaxLimit">10</prop>
                            <prop key="InactivityTimeout">2</prop>
                        </props>
                    </property>
         </bean>
    

    `

    现在,对于应用程序中需要连接的每个操作,如果可用并准备好使用,它将尝试从池中获取,但保证数据库最多只有10个活动物理连接。任何获取额外物理连接的尝试都将导致应用程序端的数据库错误

    1. 即使设置了connectionCache,也要确保应用程序没有显式地尝试获取连接,比如

    Connection connection = getJdbcTemplate().getDataSource().getConnection();

    这很令人担忧,JDBCTemplate无法管理此连接的关闭。因此,使用后必须自己关闭,否则即使使用后物理连接仍将处于活动状态且未关闭。所以下次你再次调用它时,它会尝试获得一个新的物理连接,并保持未关闭状态,导致活动连接堆积,直到达到maxLimit

    当您想将其作为参数传递给其他函数时,比如ArrayDescriptor[如果您与具有in参数的PLSQL存储过程交谈,以接受一个值数组、一个Varchar数组或一个RAW数组],可能需要明确的连接。如果需要创建ArrayDescriptor

    ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor(
                               "SOME_TYPE_NAME", connection );
    ARRAY SQLArray= new ARRAY(arrayDescriptor, connection , arrayString);
    

    因此,在这里做一个connection.close()明确的说明

    其他信息:

    Connection connection = getJdbcTemplate().getDataSource().getConnection()
    
    • 这将尝试与该数据源对象所代表的数据源建立连接

    调用这行代码一次将尝试建立新的连接。 再次呼叫将建立第二个连接。对于每个请求,它都将创建一个新连接!。所以如果你的最大极限是10, 在数据库中有10个活动的物理连接之前,调用将成功,但是 请注意,所有连接都处于活动状态[未关闭]

    假设现在有10个活动的db连接,因为maxLimit设置为10

    因此,任何需要数据库操作的请求都会通过 通过JDBCTemplate访问一个连接的正常途径是[从10个连接中]获取已经建立的连接

    但是,任何调用此代码getJdbcTemplate().getDataSource().getConnection()以访问连接的请求 将尝试建立新连接,并将失败,导致异常

    解决这个问题的唯一方法是在显式创建连接时显式关闭连接。 ie呼叫connection.close() 当我们没有显式地创建连接时,当它由Spring管理时,Spring将负责关闭 连接也是如此。在使用Oracle数据源池和JDBCTemplate的情况下,关闭连接[返回 到池的连接]由Spring管理

  2. # 2 楼答案

    您应该配置连接缓存,隐式连接缓存的最大连接数的默认值是为数据库配置的最大数据库会话数