交易不回滚


问题内容

我叫两种方法,第一种方法更新一个表,第二种方法在另一个表中插入一条记录。当第二笔交易失败时,EJB它不会回退第一笔交易。

这是我的支持豆:

@ManagedBean
@ViewScoped
public class TransactionTestBean implements Serializable {

    @EJB
    private TransactionTestService service;

    public String loadView() {
        return "/test/transactionTest";
    }

    public void test() {
        try {
            service.updateTest();
        } catch (Exception e) {
        }
    }
}

EJB接口:

@Local
public interface TransactionTestService {

    void updateTest() throws CustomException;
}

EJB类:

@Stateless
@TransactionManagement
public class TransactionTestServiceImpl implements TransactionTestService {

    @Resource(mappedName = "java:jboss/datasources/xxxxxDS", shareable = true)
    public DataSource dataSource;

    private TransactionTestDAO dao;

    @PostConstruct
    public void init() {
        dao = new TransactionTestDAOImpl();
    }

    @PreDestroy
    public void destroy() {
        dao = null;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void updateTest() throws CustomException {

        try (Connection connection = dataSource.getConnection()) {
            dao.updateRecord(connection);
            // dao.saveRecord(connection);
        } catch (SQLException exception) {
            throw new CustomException(exception, exception.getMessage());
        }
    }
}

我的自定义例外:

@ApplicationException(rollback = true)
public class CustomException extends Exception {

    public CustomException(Throwable cause, String message) {
        super(message, cause);
    }
}

编辑:

添加了DAO类:

public class TransactionTestDAOImpl implements TransactionTestDAO {

    @Override
    public void updateRecord(Connection connection) throws CustomException {

        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = connection.prepareStatement("UPDATE table_x SET field_x = ? WHERE field_y = 1");
            preparedStatement.setInt(1, 1);
            preparedStatement.executeUpdate();
        } catch (Exception exception) {
            throw new CustomException(exception, exception.getMessage());
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException sqlException) {
                }
            }
        }
    }
}

和DAO接口:

public interface TransactionTestDAO {

    void updateRecord(Connection connection) throws CustomException;
}

问题答案:

在这种情况下,关键问题是某些JBoss版本中数据源中的默认错误。原始代码很好,并且可以在其他应用程序服务器(WebSphere App
Server和轻量级WebSphere Liberty)中正常工作。

在JBoss中创建的数据源不是JTA-在管理控制台Use JTA中未选中该设置,而在xml相关设置中则为 <datasource jta="false" ...。更改此设置true可解决问题。(JohnB,您写道定义xa-
datasource可以解决此问题,但是由于我没有看到带有数据源定义的原始xml,因此我相信在更改数据源期间,您还更改了有缺陷的jta =“
false”设置)。正如Grzesiek测试的,它也适用于非xa数据源。

这是一个 非常糟糕的默认值 ,因为它导致事务不由容器管理,并 导致EJB 组件 中的连接中的事务行为有缺陷

非常感谢Grzesiek D.帮助我诊断了此问题。