Spring JdbcTemplate 线程安全吗?

Is Spring JdbcTemplate thread safe?

我在我的一个项目中使用 Spring JdbcTemplate,现在,当确实有很多请求时 - 我开始面对这个异常:

org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; 
uncategorized SQLException for SQL [{? = call API.get_data_for_nb(?, ?)}]; 
SQL state [99999]; error code [17009]; Closed Statement; 
nested exception is java.sql.SQLException: Closed Statement

因此,当您尝试执行已经关闭的语句时会收到 Closed Statement 异常,但在我的情况下,我不会自己关闭它 - 我正是为此使用了 JdbcTemplate。那么,首先,这可能是什么原因?

JdbcTemplate 对象本身以这种方式包含在 @Stateless EJB 中:

@Stateless(name = "NbEdwServiceEJB")
public class NbEdwServiceBean implements NbEdwServiceLocal, NbEdwServiceRemote {

    @Resource(mappedName = JNDI)    
    private DataSource dataSource;

    private static volatile JdbcTemplate jdbcTemplate;

    @PostConstruct
    protected void construct() {
        synchronized (NbEdwServiceBean.class) {
            if (jdbcTemplate == null) {
                jdbcTemplate = new JdbcTemplate(dataSource);
                jdbcTemplate.setResultsMapCaseInsensitive(true);
            }
        }
    }

    private String getDataFromDB(final String request, final int isDigitalSignVerified) {
        String response = null;
        try {
            response = jdbcTemplate.execute(SQL_GET_DATA, new CallableStatementCallback<String>() {
                public String doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
                    cs.registerOutParameter(1, Types.VARCHAR);
                    cs.setInt(2, isDigitalSignVerified);
                    cs.setString(3, request);
                    cs.executeUpdate();
                    return cs.getString(1);
                }
            });
        } catch (DataAccessException ex) {
            LOGGER.error("getDataFromDB()", ex);
        }

        return response;
    }
}

我知道这可能不是严格正确的方法,我可以为每个无状态 bean 创建 JdbcTemplate 实例 - 所以我可能会这样做。那么,其次,为什么会发生这种情况?我的假设是 JdbcTemplate 的 execute 方法不是线程安全的,但是有人可以给出完整的解释吗?

如果有问题,我在 WebLogic 10.3.5 上安装了 JEE 版本 5 运行。

@Tolegen Izbassar 很抱歉您被 EE5 困住了。

关于 Singleton 和 EE5,有一些替代方案。一种是特定于供应商的扩展,例如 JBoss 5.x 有提供 Singleton+JMX 的服务 bean。第二种解决方案是使用与 EE5 兼容的 Jboss Seam 的早期版本。第三种选择是使用 Servlet API 中的 ServerContext。

你在@PostConstuct 中尝试做的事情肯定不好。 SLSB 中的非最终静态是不行的。

我建议看一下 Spring 框架参考中描述 EJB - Spring 集成的第 29.3 节,该节中的一个示例:

@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class MyFacadeEJB implements MyFacadeLocal {
// automatically injected with a matching Spring bean
@Autowired
private MyComponent myComp;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}