请帮助克服以下问题。 当我调用最近重新编译的存储过程时,我收到错误ORA - “ORA-04068:已丢弃现有的包状态。”我知道当代码中的连接关闭时,它只会返回到池中,但仍然存在于会话中。我知道可能的解决方案之一是捕获此错误并在catch块中再次调用过程,不知何故这样:
callProcedure(Params params){
SimpleJdbcCall jdbcCall = getSimpleJdbcCall();
Map<String, Object> results = Collections.EMPTY_MAP;
try {
results = jdbcCall.execute(params);
}catch (UncategorizedSQLException ex){
if (checkOra04067Exception(ex)){
callProcedure(params);
}
}
return results;
}
private boolean checkOra04067Exception(UncategorizedSQLException ex){
return "72000".equals(ex.getSQLException().getSQLState()) &&
ex.getSQLException().getErrorCode() == 4068;
}
但是有更优雅的方法来克服这个问题,并不是真的想在许多使用jdbcCall.execute(params)的DAO对象中放置这个try-catch块。是的我可以使用try-catch为SimpleJdbcCall做一个包装器,并在需要它的地方注入这个包装器,但也许有可能微调数据方法以真正关闭连接或一旦它返回到连接池就完全删除它们?或者是否有一个解决方案来创建任何可以验证oracle包状态并使用它的查询 “spring.datasource.validation-query”而不是“select one from dual”。 感谢您的帮助。 P.S我正在使用org.apache.tomcat.jdbc.pool.DataSource和oracle.jdbc.driver.OracleDriver
顺便说一下,代码有问题,所以该方法返回空结果。 它以某种方式连接到try-catch块。 第一次出现错误时,callProcedure(params)方法会触发 再次在catch块中返回结果,但后来我不知道为什么但是结果从catch块之前的调用返回。这是一张空地图。
这是我可行的解决方案。 1)扩展SimpleJdbcCall 2)覆盖执行方法:
public class MyJdbcCall extends SimpleJdbcCall {
public MyyJdbcCall(DataSource dataSource) {
super(dataSource);
}
public Map<String, Object> execute(SqlParameterSource parameterSource) {
Map<String, Object> results = Collections.EMPTY_MAP;
try {
results = executeInternal(parameterSource);
} catch (UncategorizedSQLException ex) {
if (checkOra04067Exception(ex)) {
results = executeInternal(parameterSource);
}
}
return results;
}
private Map<String, Object> executeInternal(SqlParameterSource parameterSource) {
return super.execute(parameterSource);
}
private boolean checkOra04067Exception(UncategorizedSQLException ex) {
return SQL_STATE_72000.equals(ex.getSQLException().getSQLState())
&& ex.getSQLException().getErrorCode() == SQL_ERROR_CODE_4068;
}
}