【问题标题】:Spring oracle datasource does not destroy connectionSpring oracle数据源不破坏连接
【发布时间】:2017-02-20 07:47:51
【问题描述】:

我将oracle.jdbc.pool.OracleDataSource 用于Oracle 池连接,但似乎连接在数据库中仍然有效。今天连接 Oracle 数据库时出错:

ORA-12516: TNS:listener 找不到具有匹配协议栈的可用处理程序

我们的数据库管理员告诉我,我的应用程序中有太多打开的连接处于“空闲”模式。

我用ojdbc7:

<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc7</artifactId>
    <version>12.1.0.1</version>
</dependency>

Spring applicationContext.xml 文件:

<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close"> 
    <property name="URL" value="${jdbc.url}" /> 
    <property name="user" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
    <property name="connectionCachingEnabled" value="true" /> 
</bean>

DbConnect 类:

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class DbConnect {

  @Autowired
  private DataSource dataSource;

  public Connection getConnection() throws SQLException {
      return dataSource.getConnection();
  }
}

我还在我的 dao 级别使用 jdk7 try-with-resources 语法进行连接:

 @Autowired
 private DbConnect dbConnect;

 public List<User> getAllUsers() {
    List<User> list = new ArrayList<>();

    try(Connection connection = dbConnect.getConnection()) {
        try(PreparedStatement preparedStatement = connection.prepareStatement("select * from V_USERS t")) {
            try(ResultSet resultSet = preparedStatement.executeQuery()) {
                while(resultSet.next()) {
                    list.add(RowFetcher.fetchUser(resultSet));
                }
            }
        }
    }
    catch(Exception e) {
        log.error(e.getMessage(), e);
    }

    return list;
}

无法弄清楚实际问题出在哪里。我应该使用 c3p0 代替 OracleDataSource 吗? ojdbc7 中是否有任何错误或我的代码中有错误?

提前致谢!

【问题讨论】:

  • 你应该发布DbConnect的代码
  • 我已经编辑了帖子。请查看更改
  • 您的 dba 认为多少连接是合适的,Oracle 数据源中的默认设置是什么。
  • 实例化了多少 Dbconnect?
  • @KarlP 我会说一个 DbConnect 实例(spring managed => singleton)问题可能是对getAllUsers 的并行调用太多

标签: java spring oracle datasource ojdbc


【解决方案1】:

我们有通用连接池 (UCP),它是 Java 连接池。
更多配置详情请参考UCP with Spring

【讨论】:

    【解决方案2】:

    池的全部意义在于保持连接打开。但是我不确定OracleDataSource 是实际池还是您需要OracleConnectionPoolDataSource

    我建议不要使用普通的 Oracle 池,而是使用 HikariCPconfiguration options 上的页面和默认值。

    在这种情况下,您的数据源看起来像

    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"> 
        <property name="datasourceClassName" value="oracle.jdbc.pool.OracleDataSource" />
        <property name="dataSourceProperties">
            <props>
                <prop key="URL" value="${jdbc.url}" /> 
                <prop key="user" value="${jdbc.username}" /> 
                <prop key="password" value="${jdbc.password}" /> 
                <prop key="connectionCachingEnabled" value="true" />
            </props>
        </property>
    </bean>
    

    注意:还有一个很好的关于池大小的page(实际上来自 Oracle!)。

    我还建议,要清理您的代码,删除 DbConnect 类并注入(或创建)JdbcTemplate 以使用而不是使用普通连接。节省您管理所有 JDBC 对象的时间。

    private final JdbcTemplate jdbcTemplate;
    
    @Autowired
    public YourRepository(DataSource ds) {
        this.jdbcTemplate=new JdbcTemplate(ds);
    }
    
    public List<User> getAllUsers() {
        List<User> list = new ArrayList<>();
        return this.jdbcTemplate("select * from V_USERS t", new RowMapper() {
            public User mapRow(ResultSet rs, int row) throws SQLException {
                return RowFetcher.fetchUser(rs);
            }
        });
    }
    

    【讨论】:

    • 感谢您的完整回答。很有帮助,我会使用 HikariCP 和 Spring JdbcTemplate。
    【解决方案3】:

    尝试使用不同的数据源org.apache.commons.dbcp.BasicDataSource.t 适合我

    【讨论】:

      【解决方案4】:

      您可以设置dataSource限制属性来控制缓存的大小。

      <property name="connectionCacheProperties">
        <props>
           <prop key="MinLimit">${jdbc.limit.min}</prop>
           <prop key="MaxLimit">${jdbc.limit.max}</prop>
           <prop key="InitialLimit">${jdbc.limit.init}</prop>
        </props>
      </property>
      

      【讨论】:

      • 这很可能是解决方案。 MaxLimit 默认为“0”,无限制。
      猜你喜欢
      • 2017-11-24
      • 1970-01-01
      • 1970-01-01
      • 2014-12-20
      • 2022-10-18
      • 2019-01-18
      • 2010-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多