如何在以下代码段中关闭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!"
虽然我没有结合Ordinal绑定和命名绑定。任何帮助表示赞赏。
@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;
}
答案 0 :(得分:1)
使用您当前的方法,似乎无法避免SONAR问题。事实上,Spring自己关闭了语句,所以你甚至不应该关闭CallableStatementCallback
impl类中的语句,更不用说在CallableStatementCreator
impl类中。
Spring将在回调返回后关闭Statement对象
有一种替代方法可以创建CallableStatementCreator,而不是创建自己的impl类,这可以帮助您避免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编写的。因此,可能需要对您的需求进行一些小的调整。