@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 不起作用
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) doesn't work
我需要在 glassfish3 上使用 JPA 2.0 和 EJB3.0 删除忽略任何完整性约束的员工列表(即成功删除与任何其他人不相关的实体或跳过与其他人相关的实体) .0:
我迭代列表并在 try/catch 的 require_new 事务中调用实体管理器,我希望这将在大事务中打开小嵌套事务,我使用 em.flush() 强制更新。
但在相关实体的迭代中它抛出;
Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DatabaseException Internal
Exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
Cannot delete or update a parent row: a foreign key constraint fails
并继续下一个员工,但在提交大事务时它回滚并抛出相同的异常!
我希望 throw/catch 新小事务中的异常并提交列表其余部分成功删除的实体...
我有什么想念的吗?
编辑:
这是一些代码,Facade中调用实体管理器移除bean的代码,我用required-new注释了函数:
public void deleteEmployeeData(Set<Employees> deleted) throws DatabaseException {
Iterator itr;
Employees emp;
//delete unused recordes
try {
itr = deleted.iterator();
while (itr.hasNext()) {
emp = (Employees) itr.next();
deleteEmployee(emp);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("DONE");
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void deleteEmployee(Employees emp){
try {
this.remove(emp);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
你的问题似乎是你想在 try catch 中以编程方式捕获事务错误,但你的事务传播是声明性的(使用注释),它通常会创建代理堆栈并通过它们透明地处理事务失败。您需要使用编程事务并将其包装在您的异常处理代码中。
deleteEmployee
方法未包装到新事务中,因为您正在引用 this
上的方法。您可以做的是注入对外观本身的引用,然后对其调用 deleteEmployee
方法(应该是 public)。
大致是这样的:
@Stateless
public class MyFacade {
@EJB
private MyFacade self;
public void deleteEmployeeData(Set<Employees> deleted) throws DatabaseException {
...
try {
self.deleteEmployee(emp);
} catch (Exception ex) {
// ...
}
...
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void deleteEmployee(Employees emp) {
this.remove(emp);
}
}
要调用本地方法并用新事务包装它,
@Stateless
public class UserFacade implements UserFacadeLocal {
@Resource
private SessionContext context;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
private void create(User user) {
System.out.println("Users Count: "+count()); //invocation#1
System.out.println("Users Count Through Context: "+context.getBusinessObject(UserFacadeLocal.class).count()); //invocation#2
}
@Override
@TransactionAttribute(TransactionAttributeType.NEVER)
public int count() {
return ((Long) q.getSingleResult()).intValue();
}
}
EJB Transactions in local method-calls
我需要在 glassfish3 上使用 JPA 2.0 和 EJB3.0 删除忽略任何完整性约束的员工列表(即成功删除与任何其他人不相关的实体或跳过与其他人相关的实体) .0:
我迭代列表并在 try/catch 的 require_new 事务中调用实体管理器,我希望这将在大事务中打开小嵌套事务,我使用 em.flush() 强制更新。
但在相关实体的迭代中它抛出;
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails
并继续下一个员工,但在提交大事务时它回滚并抛出相同的异常!
我希望 throw/catch 新小事务中的异常并提交列表其余部分成功删除的实体...
我有什么想念的吗?
编辑:
这是一些代码,Facade中调用实体管理器移除bean的代码,我用required-new注释了函数:
public void deleteEmployeeData(Set<Employees> deleted) throws DatabaseException {
Iterator itr;
Employees emp;
//delete unused recordes
try {
itr = deleted.iterator();
while (itr.hasNext()) {
emp = (Employees) itr.next();
deleteEmployee(emp);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("DONE");
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void deleteEmployee(Employees emp){
try {
this.remove(emp);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
你的问题似乎是你想在 try catch 中以编程方式捕获事务错误,但你的事务传播是声明性的(使用注释),它通常会创建代理堆栈并通过它们透明地处理事务失败。您需要使用编程事务并将其包装在您的异常处理代码中。
deleteEmployee
方法未包装到新事务中,因为您正在引用 this
上的方法。您可以做的是注入对外观本身的引用,然后对其调用 deleteEmployee
方法(应该是 public)。
大致是这样的:
@Stateless
public class MyFacade {
@EJB
private MyFacade self;
public void deleteEmployeeData(Set<Employees> deleted) throws DatabaseException {
...
try {
self.deleteEmployee(emp);
} catch (Exception ex) {
// ...
}
...
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void deleteEmployee(Employees emp) {
this.remove(emp);
}
}
要调用本地方法并用新事务包装它,
@Stateless
public class UserFacade implements UserFacadeLocal {
@Resource
private SessionContext context;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
private void create(User user) {
System.out.println("Users Count: "+count()); //invocation#1
System.out.println("Users Count Through Context: "+context.getBusinessObject(UserFacadeLocal.class).count()); //invocation#2
}
@Override
@TransactionAttribute(TransactionAttributeType.NEVER)
public int count() {
return ((Long) q.getSingleResult()).intValue();
}
}
EJB Transactions in local method-calls