【发布时间】:2015-06-22 12:07:18
【问题描述】:
我正在开发一个 JSF 应用程序,它通过 Tomcat 7 配置使用 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;
}
我的 JNDI 配置如下(敏感信息已加星标):
<Resource name="jdbc/core" auth="Container" type="javax.sql.DataSource"
url="****"
driverClassName="com.ibm.db2.jcc.DB2Driver"
username="****" password="****"
maxActive="20" maxIdle="3" maxWait="10000"
poolPreparedStatements="true"
maxOpenPreparedStatements="100"
validationQuery="SELECT 1 FROM SYSIBM.SYSDUMMY1" />
感谢任何帮助。
谢谢。
更新
我已尝试实施@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;
}
【问题讨论】:
-
"我的印象是,在 finally 块中关闭连接时,如果在此连接的生命周期内抛出任何异常并将连接返回到池。“不。您需要将代码包装在事务单元周围。如果该单元内发生任何异常,事务单元内完成的工作将被还原/回滚。
-
好吧,最好的方法是什么?是否会将特定共享连接的自动提交设置为 false 并手动直接调用连接对象的回滚()和提交()?
-
应该很少需要将共享连接的自动提交设置为 false,但这取决于。然而,最好的方法是将此关键任务委托给您感兴趣的事务管理系统(声明性),例如 EJB (JTA) 或使用
org.springframework.transaction.annotation.Transactional注释指定的 Spring 服务。 -
我设法通过手动将共享连接的自动提交设置为 false 来实现所需的行为,然后仅在没有引发异常时才提交。理想情况下,我想尝试使用前面提到的事务管理......我已经更新了上面的问题以显示我尝试过的内容。我在 pom.xml 中包含了 spring 依赖项,以将 spring api 引入我的项目。我在服务方法中包含了@transactional 标记,但是似乎没有任何变化并且事务不起作用?我是否需要在我的 JSF 项目中设置任何其他配置?谢谢。
标签: jsf jdbc transactions db2 connection-pooling