Spring oracle 数据源不破坏连接
Spring oracle datasource does not destroy connection
我将 oracle.jdbc.pool.OracleDataSource
用于 Oracle 池连接,但连接似乎在数据库中保持活动状态。今天我在连接到 Oracle 数据库时遇到错误:
ORA-12516: TNS:listener could not find available handler with matching protocol stack
我们的数据库管理员告诉我,我的应用程序中有太多打开的连接处于 "IDLE" 模式。
我用的是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 class:
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 是否有错误或我的代码有错误?
提前致谢!
您可以设置数据源限制属性来控制缓存的大小。
<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>
尝试使用不同的数据源org.apache.commons.dbcp.BasicDataSource。对我有用
池的全部意义在于保持连接打开。但是我不确定 OracleDataSource
是一个实际的池还是您需要 OracleConnectionPoolDataSource
。
我建议使用 HikariCP. The page on configuration options 和默认值,而不是使用普通的 Oracle 池。
在那种情况下,您的数据源将类似于
<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
class 并注入(或创建)一个 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);
}
});
}
我们有通用连接池 (UCP),它是 Java 连接池。
有关更多配置详细信息,请参阅 UCP with Spring。
我将 oracle.jdbc.pool.OracleDataSource
用于 Oracle 池连接,但连接似乎在数据库中保持活动状态。今天我在连接到 Oracle 数据库时遇到错误:
ORA-12516: TNS:listener could not find available handler with matching protocol stack
我们的数据库管理员告诉我,我的应用程序中有太多打开的连接处于 "IDLE" 模式。
我用的是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 class:
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 是否有错误或我的代码有错误?
提前致谢!
您可以设置数据源限制属性来控制缓存的大小。
<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>
尝试使用不同的数据源org.apache.commons.dbcp.BasicDataSource。对我有用
池的全部意义在于保持连接打开。但是我不确定 OracleDataSource
是一个实际的池还是您需要 OracleConnectionPoolDataSource
。
我建议使用 HikariCP. The page on configuration options 和默认值,而不是使用普通的 Oracle 池。
在那种情况下,您的数据源将类似于
<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
class 并注入(或创建)一个 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);
}
});
}
我们有通用连接池 (UCP),它是 Java 连接池。
有关更多配置详细信息,请参阅 UCP with Spring。