使用 CallableStatementCreator 和 CallableStatementCallback 时如何关闭 CallableStatement
How to close CallableStatement when using CallableStatementCreator and CallableStatementCallback
如何在以下代码片段中关闭 CallableStatement。
Sonarcube 抱怨我关闭 CallableStatement
我在 doInCallableStatement 方法中添加了 finally 块并关闭了 callableStatement。它运行良好,callableStatement 正在关闭,但 Sonarcube 仍在抱怨
我关闭 callableStatement。
如果我在 createCallableStatement 方法中添加 finally 块并关闭 callableStatement。 Sonarcube 没有抱怨,但 CallableStatementCallback 失败,因为 callableStatement 已经关闭。
@Override
public MyInfo getMyInfo(String id) throws SecurityDAOException, AuditException {
MyInfo myInfo = null;
try {
myInfo = jdbcTemplate.execute(new CallableStatementCreator() {
@Override
public CallableStatement createCallableStatement(Connection connection) throws SQLException {
CallableStatement callableStatement = null;
callableStatement = connection.prepareCall(STORED_PROCEDURE);
callableStatement.setString("ID", Id);
callableStatement.registerOutParameter("REQID", OracleTypes.VARCHAR);
callableStatement.registerOutParameter("TYPE", OracleTypes.VARCHAR);
return callableStatement;
// If I add finally block here and close callableStatement,
// Sonarcube is not complaining but CallableStatementCallback
// is failing since the callableStatement is already closed.
}
}, new CallableStatementCallback<MyInfo>() {
@Override
public MyInfo doInCallableStatement(CallableStatement callableStatement) throws SQLException {
try {
MyInfo myInfo = new MyInfo();
callableStatement.execute();
myInfo.setSsn(callableStatement.getString("REQID"));
myInfo.setSsnType(String.valueOf(callableStatement.getString("TYPE").charAt(0)));
return myInfo;
} finally {
if (null != callableStatement) {
try {
callableStatement.close();
} catch (SQLException e) {
LOGGER.error("Not able to close CallableStatement:", e);
}
}
}
}
});
} catch (DataAccessException dataAccessException) {
throw new SecurityDAOException(dataAccessException, INTERNAL_SERVER_ERROR,
RESPONSE_CODE_INTERNAL_SERVER_ERROR, dataAccessException.getCause().getMessage());
} catch (Exception e) {
throw new AuditException(e);
}
return myInfo;
}
更新 -(根据评论更新代码以使其工作)
@Vasan,我试过你的方法,但出于某种原因,我没能成功。我收到以下异常
"org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call MY_PROCEDURE(?,?)}]; SQL state [99999]; error code [17090]; operation not allowed: Ordinal binding and Named binding cannot be combined!; nested exception is java.sql.SQLException: operation not allowed: Ordinal binding and Named binding cannot be combined!"
尽管我没有组合序数绑定和命名绑定。感谢任何帮助。
@Override
public String getMyInfo(String id) throws SecurityDAOException, AuditException {
String status = null;
try {
CallableStatementCreatorFactory cscFactory = new CallableStatementCreatorFactory(
MY_PROCEDURE);
cscFactory.addParameter(new SqlParameter("ID", OracleTypes.VARCHAR));
cscFactory.addParameter(new SqlOutParameter("MY_OUTPUT", OracleTypes.VARCHAR));
final Map<String, Object> actualParams = new HashMap<>();
actualParams.put("ID", id);
CallableStatementCreator callableStatementCreator = cscFactory.newCallableStatementCreator(actualParams);
CallableStatementCallback<String> callableStatementCallback = new CallableStatementCallback<String>() {
@Override
public String doInCallableStatement(CallableStatement callableStatement) throws SQLException {
String status = null;
callableStatement.execute();
status = callableStatement.getString(2);
return status;
}
};
status = jdbcTemplate.execute(callableStatementCreator, callableStatementCallback);
} catch (DataAccessException dataAccessException) {
throw new SecurityDAOException(dataAccessException, INTERNAL_SERVER_ERROR,
RESPONSE_CODE_INTERNAL_SERVER_ERROR, dataAccessException.getCause().getMessage());
} catch (Exception e) {
throw new AuditException(e);
}
return status;
}
使用您当前的方法,似乎无法避免 SONAR 问题。事实上,Spring 自己关闭语句,所以你甚至不应该关闭 CallableStatementCallback
impl class 中的语句,更不用说 CallableStatementCreator
impl class.
Spring will close the Statement object after the callback returned
但是,有一种替代方法可以创建 CallableStatementCreator,而不是创建您自己的 impl class,这可能会帮助您避免 SONAR 问题。您可以使用 CallableStatementCreatorFactory.
CallableStatementCreatorFactory cscFactory = new CallableStatementCreatorFactory(STORED_PROCEDURE);
cscFactory.addParameter(new SqlParameter("ID", OracleTypes.VARCHAR));
cscFactory.addParameter(new SqlOutParameter("REQID", OracleTypes.VARCHAR));
cscFactory.addParameter(new SqlOutParameter("TYPE", OracleTypes.VARCHAR));
CallableStatementCreator cscCreator = cscFactory.newCallableStatementCreator(Collections.singletonMap("ID", id));
jdbcTemplate.execute(cscCreator, [...])
我自己以前没有用过这个,这是只用javadocs写的。因此,可能需要根据您的需要对该代码进行一些小的调整。
如何在以下代码片段中关闭 CallableStatement。 Sonarcube 抱怨我关闭 CallableStatement
我在 doInCallableStatement 方法中添加了 finally 块并关闭了 callableStatement。它运行良好,callableStatement 正在关闭,但 Sonarcube 仍在抱怨 我关闭 callableStatement。
如果我在 createCallableStatement 方法中添加 finally 块并关闭 callableStatement。 Sonarcube 没有抱怨,但 CallableStatementCallback 失败,因为 callableStatement 已经关闭。
@Override
public MyInfo getMyInfo(String id) throws SecurityDAOException, AuditException {
MyInfo myInfo = null;
try {
myInfo = jdbcTemplate.execute(new CallableStatementCreator() {
@Override
public CallableStatement createCallableStatement(Connection connection) throws SQLException {
CallableStatement callableStatement = null;
callableStatement = connection.prepareCall(STORED_PROCEDURE);
callableStatement.setString("ID", Id);
callableStatement.registerOutParameter("REQID", OracleTypes.VARCHAR);
callableStatement.registerOutParameter("TYPE", OracleTypes.VARCHAR);
return callableStatement;
// If I add finally block here and close callableStatement,
// Sonarcube is not complaining but CallableStatementCallback
// is failing since the callableStatement is already closed.
}
}, new CallableStatementCallback<MyInfo>() {
@Override
public MyInfo doInCallableStatement(CallableStatement callableStatement) throws SQLException {
try {
MyInfo myInfo = new MyInfo();
callableStatement.execute();
myInfo.setSsn(callableStatement.getString("REQID"));
myInfo.setSsnType(String.valueOf(callableStatement.getString("TYPE").charAt(0)));
return myInfo;
} finally {
if (null != callableStatement) {
try {
callableStatement.close();
} catch (SQLException e) {
LOGGER.error("Not able to close CallableStatement:", e);
}
}
}
}
});
} catch (DataAccessException dataAccessException) {
throw new SecurityDAOException(dataAccessException, INTERNAL_SERVER_ERROR,
RESPONSE_CODE_INTERNAL_SERVER_ERROR, dataAccessException.getCause().getMessage());
} catch (Exception e) {
throw new AuditException(e);
}
return myInfo;
}
更新 -(根据评论更新代码以使其工作)
@Vasan,我试过你的方法,但出于某种原因,我没能成功。我收到以下异常
"org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call MY_PROCEDURE(?,?)}]; SQL state [99999]; error code [17090]; operation not allowed: Ordinal binding and Named binding cannot be combined!; nested exception is java.sql.SQLException: operation not allowed: Ordinal binding and Named binding cannot be combined!"
尽管我没有组合序数绑定和命名绑定。感谢任何帮助。
@Override
public String getMyInfo(String id) throws SecurityDAOException, AuditException {
String status = null;
try {
CallableStatementCreatorFactory cscFactory = new CallableStatementCreatorFactory(
MY_PROCEDURE);
cscFactory.addParameter(new SqlParameter("ID", OracleTypes.VARCHAR));
cscFactory.addParameter(new SqlOutParameter("MY_OUTPUT", OracleTypes.VARCHAR));
final Map<String, Object> actualParams = new HashMap<>();
actualParams.put("ID", id);
CallableStatementCreator callableStatementCreator = cscFactory.newCallableStatementCreator(actualParams);
CallableStatementCallback<String> callableStatementCallback = new CallableStatementCallback<String>() {
@Override
public String doInCallableStatement(CallableStatement callableStatement) throws SQLException {
String status = null;
callableStatement.execute();
status = callableStatement.getString(2);
return status;
}
};
status = jdbcTemplate.execute(callableStatementCreator, callableStatementCallback);
} catch (DataAccessException dataAccessException) {
throw new SecurityDAOException(dataAccessException, INTERNAL_SERVER_ERROR,
RESPONSE_CODE_INTERNAL_SERVER_ERROR, dataAccessException.getCause().getMessage());
} catch (Exception e) {
throw new AuditException(e);
}
return status;
}
使用您当前的方法,似乎无法避免 SONAR 问题。事实上,Spring 自己关闭语句,所以你甚至不应该关闭 CallableStatementCallback
impl class 中的语句,更不用说 CallableStatementCreator
impl class.
Spring will close the Statement object after the callback returned
但是,有一种替代方法可以创建 CallableStatementCreator,而不是创建您自己的 impl class,这可能会帮助您避免 SONAR 问题。您可以使用 CallableStatementCreatorFactory.
CallableStatementCreatorFactory cscFactory = new CallableStatementCreatorFactory(STORED_PROCEDURE);
cscFactory.addParameter(new SqlParameter("ID", OracleTypes.VARCHAR));
cscFactory.addParameter(new SqlOutParameter("REQID", OracleTypes.VARCHAR));
cscFactory.addParameter(new SqlOutParameter("TYPE", OracleTypes.VARCHAR));
CallableStatementCreator cscCreator = cscFactory.newCallableStatementCreator(Collections.singletonMap("ID", id));
jdbcTemplate.execute(cscCreator, [...])
我自己以前没有用过这个,这是只用javadocs写的。因此,可能需要根据您的需要对该代码进行一些小的调整。