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