我有3.0规范的无状态会话EJB。
/*Remote Interface*/
package com.nseit.ncfm2.data.ejb;
import java.sql.SQLException;
import java.util.Collection;
import javax.ejb.Remote;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.naming.NamingException;
import com.nseit.ncfm2.security.Audit;
@Remote
public interface ProductionDataChangesRequestsRemote {
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public boolean shiftCandidateDetails(String sourceNcfmId,
String destinationNcfmId, Collection<String> specialCasesList, String shiftingRemarks, String user, Audit updtAudit) throws NamingException, SQLException;
}
/*Bean Class*/
package com.nseit.ncfm2.data.ejb;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.naming.NamingException;
import com.nseit.ncfm2.security.Audit;
import com.nseit.ncfm2.util.server.lookup.LookUpServerResources;
import java.sql.*;
import java.util.*;
/**
* Session Bean implementation class ProductionDataChangesRequestsBean
*/
@Stateless(name = "ProductionDataChangesRequestsBean", mappedName = "ProductionDataChangesRequestsEJB")
@Remote(ProductionDataChangesRequestsRemote.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ProductionDataChangesRequestsBean implements
ProductionDataChangesRequestsRemote {
/**
* Default constructor.
*/
public ProductionDataChangesRequestsBean() {
// TODO Auto-generated constructor stub
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public boolean shiftCandidateDetails(String sourceNcfmId,
String destinationNcfmId, Collection<String> specialCasesList,
String shiftingRemarks, String user, Audit updtAudit)
throws NamingException, SQLException {
// TODO Auto-generated method stub
Connection conn = null;
PreparedStatement pstmt = null;
int updtCnt = 0;
boolean areDetailsShifted = false;
try {
..............
..............
..............
/* Start: update table-1 */
..............
..............
..............
updtCnt = pstmt.executeUpdate();
..............
..............
..............
/* End: update table-1 */
/* Start: update table-2 */
..............
..............
..............
updtCnt = pstmt.executeUpdate();
..............
..............
..............
/* End: update table-2 */
areDetailsShifted = true;
} /*catch (SQLException e) {
// TODO Auto-generated catch block
System.out
.println("SQLException in ProductionDataChangesRequestsBean.shiftCandidateDetails(...) "
+ e.getMessage());
// e.printStackTrace();
context.setRollbackOnly();
} */finally {
LookUpServerResources.closeStatement(pstmt);
LookUpServerResources.closeConnection(conn);
}
return areDetailsShifted;
}
}
目前,如果第一个表更新成功并且第二个表更新发出异常,则不会发生回滚,即更新第一个表中的记录。
我希望在发生SQLException时回滚事务(或者就此而言,如果发生任何运行时异常)。
我尝试了两种方法:
context.setRollbackOnly()
进行SQLException 在这两种情况下,交易都没有回滚。
我怎样才能做到这一点:
context.setRollbackOnly()
或者标准方式是什么?
答案 0 :(得分:3)
您必须抛出RuntimeException
答案 1 :(得分:1)
标准方法是使用底层 JPA 进行持久化,而不是使用JDBC。 JPA 提供了一个标准的OR映射解决方案,它很好地集成到符合EJB 3.x的容器中。
同样来自您的代码,它反映出您拥有TransactionManagementType.CONTAINER
,但仍然手动管理交易。
在bean管理的事务中 划分,会话中的代码 或显式的消息驱动bean 标志着边界 交易。虽然有豆子 容器管理的事务需要 编码较少,它们有一个限制: 当一个方法正在执行时,它可以 与单一相关联 交易或根本没有交易。 如果此限制将进行编码 你的豆很难,你应该 考虑使用bean管理 交易。
答案 2 :(得分:-1)
看起来您在bean中使用JDBC API。我认为容器不管理那些JDBC事务。对于CMT,您必须在容器管理实体管理器上调用操作才能使回滚按预期工作。