交易不回滚
问题内容:
我叫两种方法,第一种方法更新一个表,第二种方法在另一个表中插入一条记录。当第二笔交易失败时,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.帮助我诊断了此问题。