【问题标题】:@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) doesn't work@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 不起作用
【发布时间】:2015-09-07 20:39:34
【问题描述】:

我需要在 glassfish3.0 上使用 JPA 2.0 和 EJB3.0 删除忽略任何完整性约束的员工列表(即成功删除尚未与任何其他人相关的实体或跳过与其他人相关的实体) :

我在列表中迭代并在 try/catch 中的 require_new 事务中调用实体管理器,我希望这将在大事务中打开小型嵌套事务,并且我使用 em.flush() 来强制更新。

但在它抛出的相关实体的迭代中;

异常 [EclipseLink-4002](Eclipse 持久性服务 - 2.4.2.v20130514-5956486):org.eclipse.persistence.exceptions.DatabaseException 内部 例外: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 无法删除或更新父行:外键约束失败

并继续下一位员工,但在提交大事务时,它会回滚并抛出相同的异常!

我希望在 new-small 事务中抛出/捕获异常,并提交列表其余部分成功删除的实体...

我有什么想念的吗?

编辑:

这里是一些代码,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());
                }

    }

【问题讨论】:

  • 我们需要更多地了解您的模型,是否某些实体与您要删除的实体有关系?您是否在同一事务中删除了该关系?
  • 有另一个实体引用我要删除的员工实体,因为违反了完整性约束,我需要保留从另一个实体引用的所有员工并删除其他员工
  • @Ajan 我用一些代码编辑了这个问题
  • 好的,这很重要,应该在问题中得到精确说明:你不想引入约束,但是当约束异常发生时你忽略删除(这不是真正的好方法,但是 . .无论如何)
  • 你为什么用@TransactionAttribute而不是@Transactional

标签: java jpa glassfish ejb-3.0


【解决方案1】:

您的问题似乎是您希望在 try catch 中以编程方式捕获事务错误,但您的事务传播是声明性的(使用注释),这通常会创建一个代理堆栈并通过它们透明地处理事务失败。您需要使用程序化事务并将其包装在您的异常处理代码中。

【讨论】:

【解决方案2】:

deleteEmployee 方法未包装到新事务中,因为您正在引用 this 上的方法。您可以做的是注入对外观本身的引用,然后在其上调用deleteEmployee 方法(它应该是公共的)。

或多或少是这样的:

@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);
    }

}

【讨论】:

【解决方案3】:

要调用本地方法并用新事务包装它,

@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

【讨论】:

    猜你喜欢
    • 2013-11-24
    • 1970-01-01
    • 2012-07-21
    • 2016-11-18
    • 1970-01-01
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多