【问题标题】:Transaction handling with JDBC Connection Pooling in Tomcat7在 Tomcat7 中使用 JDBC 连接池进行事务处理
【发布时间】: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


【解决方案1】:

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

【讨论】:

  • 我尝试使用事务管理器(请参阅更新后的帖子)。你能解释一下如何正确实现吗?
  • 恐怕我对 J2EE 不太熟悉,无法在此提供很多帮助。
猜你喜欢
  • 2013-02-23
  • 2012-06-09
  • 2023-03-29
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多