Jsf Tomcat7中JDBC连接池的事务处理

Jsf Tomcat7中JDBC连接池的事务处理,jsf,jdbc,transactions,db2,connection-pooling,Jsf,Jdbc,Transactions,Db2,Connection Pooling,我正在开发一个JSF应用程序,它通过Tomcat7配置使用JNDI连接池连接到DB2数据库。我在管理事务时遇到问题,更具体地说,当从共享连接的方法抛出异常时,我会回滚 下面的代码建立了一个连接,并将其传递给所有其他被调用的方法。然后,此连接仅在方法的finally块中关闭。我的问题是,例如,如果在方法中的任何一点抛出异常,在此之前完成的任何工作都将提交,而不会回滚。我的印象是,当在finally块中关闭一个连接时,如果在该连接的生存期内抛出任何异常,那么该连接将不会提交,然后该连接将返回到池中,

我正在开发一个JSF应用程序,它通过Tomcat7配置使用JNDI连接池连接到DB2数据库。我在管理事务时遇到问题,更具体地说,当从共享连接的方法抛出异常时,我会回滚

下面的代码建立了一个连接,并将其传递给所有其他被调用的方法。然后,此连接仅在方法的finally块中关闭。我的问题是,例如,如果在方法中的任何一点抛出异常,在此之前完成的任何工作都将提交,而不会回滚。我的印象是,当在finally块中关闭一个连接时,如果在该连接的生存期内抛出任何异常,那么该连接将不会提交,然后该连接将返回到池中,而不管该工作是否已提交或回滚

public boolean updateSubCountry(SubCountryDTO dto,
        List<FeatureAliasDTO> aliases, List<FeatureCodeDTO> codes)
        throws ReferenceDataException {
    boolean success = true;
    Connection c = null;
    try {
        c = fDao.getConnection();
        success = fDao.updateSubCountry(c, dto, TEMP_USERNAME) && success;
        success = updateAliases(c, aliases, dto.getOdi(), TEMP_USERNAME,
                dto.getSubCountryId()) && success;
        for (FeatureCodeDTO codeDto : codes) {
            success = updateFeatureCode(c, codeDto, dto.getSubCountryId())
                    && success;
        }
    } finally {
        closeConnection(c, DEFAULT_CONNECTION_ERROR_MSG);
    }
    return success;
}
public boolean updateSubCountry(SubCountryDTO到dto,
列出别名、列表代码)
抛出ReferenceDataException{
布尔成功=真;
连接c=null;
试一试{
c=fDao.getConnection();
success=fDao.updateSubCountry(c、dto、TEMP_用户名)&&success;
success=updateAlias(c,别名,dto.getOdi(),TEMP_用户名,
dto.getSubCountryId())和&success;
用于(功能代码到代码到:代码){
success=updateFeatureCode(c,codeDto,dto.getSubCountryId())
&&成功;
}
}最后{
closeConnection(c,默认连接错误消息);
}
回归成功;
}
我的JNDI配置如下(敏感信息用星号标出):


感谢您的帮助

谢谢

更新

我已尝试实施@Tiny提出的建议。但是,当故意使updateFeatureCode()方法在数据库级别抛出异常时,在此之前的任何工作都不会回滚吗

@Transactional (rollbackFor={Exception.class, ReferenceDataException.class})
    public boolean updateSubCountry(SubCountryDTO dto,
            List<FeatureAliasDTO> aliases, List<FeatureCodeDTO> codes)
            throws ReferenceDataException {
        boolean success = true;
        Connection c = null;
        try {
            c = fDao.getConnection();
            success = fDao.updateSubCountry(c, dto, TEMP_USERNAME) && success;
            success = updateAliases(c, aliases, dto.getOdi(), TEMP_USERNAME,
                    dto.getSubCountryId()) && success;
            for (FeatureCodeDTO codeDto : codes) {
                success = updateFeatureCode(c, codeDto, dto.getSubCountryId())
                        && success;
            }
        } finally {
            closeConnection(c, DEFAULT_CONNECTION_ERROR_MSG);
        }
        return success;
    }
@Transactional(rollboor={Exception.class,ReferenceDataException.class})
公共布尔值更新SubCountry(SubCountryDTO到dto,
列出别名、列表代码)
抛出ReferenceDataException{
布尔成功=真;
连接c=null;
试一试{
c=fDao.getConnection();
success=fDao.updateSubCountry(c、dto、TEMP_用户名)&&success;
success=updateAlias(c,别名,dto.getOdi(),TEMP_用户名,
dto.getSubCountryId())和&success;
用于(功能代码到代码到:代码){
success=updateFeatureCode(c,codeDto,dto.getSubCountryId())
&&成功;
}
}最后{
closeConnection(c,默认连接错误消息);
}
回归成功;
}

当连接到DB2数据库时,IBM JDBC驱动程序默认为
autoCommit=true
,这意味着在每条语句之后都会发出显式的
COMMIT
。如果您希望自己控制事务,请根据需要禁用自动提交和提交或回滚。或者,正如@Tiny所建议的,使用事务管理器。

“我的印象是,当在finally块中关闭一个连接时,如果在该连接的生命周期内抛出任何异常,并且该连接返回到池中,则不会提交该请求。”否。您需要将代码包装在事务单元周围。如果该单元内发生任何异常,则事务单元内完成的工作将被还原/回滚。好的,这样做的最佳方式是什么?是否将特定共享连接的自动提交设置为false,并手动直接调用连接对象的rollback()和commit()。但是,最好的方法是将这项关键任务委托给您感兴趣的事务管理系统(声明式),如EJB(JTA)或者使用
org.springframework.transaction.annotation.Transactional
annotation指定的Spring服务。我通过手动将共享连接的auto commit设置为false,然后仅在没有引发异常的情况下提交,成功地实现了所需的行为。理想情况下,我想尝试使用前面提到的事务管理。。。。我已经更新了我的上述问题,以显示我的尝试。我已经在pom.xml中包含了spring依赖项,以便将spring api引入到我的项目中。我在服务方法中包含了@transactional标记,但是似乎没有任何变化,事务也不起作用?我需要在我的JSF项目中设置任何其他配置吗?谢谢。我已尝试使用事务管理器(请参阅更新的帖子)。你能解释一下如何正确地实现这个吗?恐怕我对J2EE不够精通,不能在这里提供太多帮助。
@Transactional (rollbackFor={Exception.class, ReferenceDataException.class})
    public boolean updateSubCountry(SubCountryDTO dto,
            List<FeatureAliasDTO> aliases, List<FeatureCodeDTO> codes)
            throws ReferenceDataException {
        boolean success = true;
        Connection c = null;
        try {
            c = fDao.getConnection();
            success = fDao.updateSubCountry(c, dto, TEMP_USERNAME) && success;
            success = updateAliases(c, aliases, dto.getOdi(), TEMP_USERNAME,
                    dto.getSubCountryId()) && success;
            for (FeatureCodeDTO codeDto : codes) {
                success = updateFeatureCode(c, codeDto, dto.getSubCountryId())
                        && success;
            }
        } finally {
            closeConnection(c, DEFAULT_CONNECTION_ERROR_MSG);
        }
        return success;
    }