什么是可用于Java/JDBC的最佳连接池库?
我正在考虑2个主要候选人(免费/开源):
我在博客和其他论坛上阅读了很多关于它们的内容,但无法做出决定.
这两个是否有任何相关的替代方案?
据说在使用后关闭所有JDBC资源是一个好习惯.但是,如果我有以下代码,是否有必要关闭Resultset和Statement?
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = // Retrieve connection
stmt = conn.prepareStatement(// Some SQL);
rs = stmt.executeQuery();
} catch(Exception e) {
// Error Handling
} finally {
try { if (rs != null) rs.close(); } catch (Exception e) {};
try { if (stmt != null) stmt.close(); } catch (Exception e) {};
try { if (conn != null) conn.close(); } catch (Exception e) {};
}
Run Code Online (Sandbox Code Playgroud)
问题是连接的关闭是否完成了工作,或者是否使用了一些资源.
我一直在对我们的宠物项目之一进行代码审查(主要使用像FindBugs这样的工具),FindBugs将以下代码标记为错误(伪代码):
Connection conn = dataSource.getConnection();
try{
PreparedStatement stmt = conn.prepareStatement();
//initialize the statement
stmt.execute();
ResultSet rs = stmt.getResultSet();
//get data
}finally{
conn.close();
}
Run Code Online (Sandbox Code Playgroud)
错误是此代码可能不会释放资源.我发现ResultSet和Statement没有关闭,所以我最后关闭了它们:
finally{
try{
rs.close()
}catch(SqlException se){
//log it
}
try{
stmt.close();
}catch(SqlException se){
//log it
}
conn.close();
}
Run Code Online (Sandbox Code Playgroud)
但是我在很多项目中遇到过上述模式(来自不少公司),没有人关闭ResultSet或Statements.
在Connection关闭时,您是否遇到没有关闭ResultSet和Statements的麻烦?
我发现只有这个,它指的是Oracle在关闭Connections时关闭ResultSet的问题(我们使用Oracle db,因此我的更正).java.sql.api在Connection.close()javadoc中什么也没说.
注意:我们重用单一连接.
************************************************
public Connection connection() {
try {
if ((connection == null) || (connection.isClosed()))
{
if (connection!=null)
log.severe("Connection was closed !");
connection = DriverManager.getConnection(jdbcURL, username, password);
}
} catch (SQLException e) {
log.severe("can't connect: " + e.getMessage());
}
return connection;
}
**************************************************
public IngisObject[] select(String query, String idColumnName, String[] columns) {
Connection con = connection();
Vector<IngisObject> objects = new Vector<IngisObject>();
try {
Statement stmt = con.createStatement();
String sql = query;
ResultSet rs =stmt.executeQuery(sql);//oracle increases cursors count here
while(rs.next()) {
IngisObject …Run Code Online (Sandbox Code Playgroud) OracleTypes.ARRAY多次调用带有输入参数的Oracle存储过程时,会出现以下错误: -
org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call EMP_SCHEMA.GET_EMPLOYEE_LIST(?, ?)}]; SQL state [72000]; error code [1000]; ORA-01000: maximum open cursors exceeded; nested exception is java.sql.SQLException: ORA-01000: maximum open cursors exceeded
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
Run Code Online (Sandbox Code Playgroud)
JDBC模板配置是: -
<bean id="commonsDbcpNativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg>
<ref bean="dataSource" />
</constructor-arg>
<property name="nativeJdbcExtractor" ref="commonsDbcpNativeJdbcExtractor" />
</bean>
Run Code Online (Sandbox Code Playgroud)
存储过程类: -
public class GetEmployees extends StoredProcedure {
public GetEmployees(JdbcTemplate jdbcTemplate) {
super(jdbcTemplate, "EMP_SCHEMA.GET_EMPLOYEE_LIST");
declareParameter(new SqlParameter("p_emp_id_list", OracleTypes.ARRAY, "TBL_EMP_ID"));
declareParameter(new SqlOutParameter(CURSOR, OracleTypes.CURSOR, new EmployeeDataRowMapper())); …Run Code Online (Sandbox Code Playgroud) 我的Java应用程序需要将游标保存到Oracle DB一段时间.在此期间,必须进行其他DB语句.这是否需要单独的DB连接或相同(光标的一个)可以使用?
谢谢.
我们的Oracle 11g数据库包含298个表(最近添加了10个),(+100个序列),我们声明了500个游标.
在启动我们的WebApplication(Tomcat 7.0,jdbc池)时,在sessionFactory初始化时,当hibernate验证模式时,它使用所有游标(参见下文).
为了让hibernate对Oracle游标不那么贪婪,有什么已知的东西吗?
请注意,此问题与预处理语句或hibernate实体的处理无关,因为在此步骤中我不与它们中的任何一个一起使用.
Caused by: org.hibernate.exception.GenericJDBCException: could not get table metadata: MYTABLE
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
at org.hibernate.tool.hbm2ddl.DatabaseMetadata.getTableMetadata(DatabaseMetadata.java:105)
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1080)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:116)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:317)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1300)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:863)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:782)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:188)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1573)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1511)
... 34 more
Caused by: java.sql.SQLException: ORA-01000: maximum open cursors exceeded
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:774)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:925)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798) …Run Code Online (Sandbox Code Playgroud) 我尝试通过以下方式使用 EntityManager 的“createStoredProcedureQuery”调用 Oracle 存储过程:
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
public void saveMeterVol(Meter meter, Double vol1, Chng chng, User user, Date dt1, Date dt2) {
StoredProcedureQuery qr = em.createStoredProcedureQuery("mt.P_METER.meter_vol_ins_upd_java");
qr.registerStoredProcedureParameter(1, Integer.class, ParameterMode.OUT);
qr.registerStoredProcedureParameter(2, Integer.class, ParameterMode.IN);
qr.registerStoredProcedureParameter(3, Integer.class, ParameterMode.IN);
qr.registerStoredProcedureParameter(4, Double.class, ParameterMode.IN);
qr.registerStoredProcedureParameter(5, Date.class, ParameterMode.IN);
qr.registerStoredProcedureParameter(6, Date.class, ParameterMode.IN);
qr.registerStoredProcedureParameter(7, String.class, ParameterMode.IN);
qr.setParameter(2, meter.getId());
qr.setParameter(3, chng.getId());
qr.setParameter(4, vol1);
qr.setParameter(5, dt1);
qr.setParameter(6, dt2);
qr.setParameter(7, user.getCd());
qr.execute();
}
Run Code Online (Sandbox Code Playgroud)
当我调用这个方法超过 300 次时,Oracle 陷入异常:ORA-01000: maximum open cursors exceeded
据我了解,Java 在调用我的过程后不会关闭 Oracle 游标,但我不明白为什么? …