使用 Hibernate JPA 处理工作单元的问题 [英] Problem in Handling Unit of work using Hibernate JPA

查看:52
本文介绍了使用 Hibernate JPA 处理工作单元的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Spring + Hibernate + JPA

I use Spring + Hibernate + JPA

我需要通过插入他们的订单来处理客户列表.

I need to handle the list of customers by inserting their orders.

这是工作单元:

for(Customer customer: CustomerList) {
    List<Order> orderList =  customer.getOrders();
    for(Order order: OrderList) {
       //1. Insert order into ORDER table
            //If insert fails due to Duplicate key then no rollback and I follow steps 2 & 3. 
            //If insert fails due to any reason except duplicate key then rollback all the previous transactions
       //2. select the order record (If any issue during selection then rollbackall the previous transactions)
       //3. Update the order If status of the order is different from that in DB (If any issue during update then rollback all the previous transactions)
    }
    // 4. Update Customer record into CUSTOMER table (If any issue during update then rollback all the previous transactions)
}

当所有订单和客户数据库进程都正常时需要提交.

Commit is required when all the orders and customer db processes are ok.

  1. 插入订单

  1. Insert order

1.a 如果重复订单不回滚.但是,如果 req 中的订单状态与 db 中的订单状态不同,则从 table 中选择该订单并更新

1.a If duplicate order do not roll back. But select that order from table and update if the status of the order is different in the req compared to the one in db

1.b 如果在插入 ORDER 过程中出现任何其他错误,则回滚

1.b If any other error during inserting of ORDER then roll back

1.c 如果没有错误,则继续插入特定客户的订单

1.c If no error then proceed inserting orders of the particular Customer

完成特定客户的订单后,更新客户表

Once orders of the particular Customer is done, then update Customer table

循环继续......

在处理第1、2、3点时,如果一切正常,则需要commit.如果中间有任何问题,则回滚所有事务

While handling point 1, 2 and 3 If everything is ok, then commit is required. If any issues in the middle then all transactions are rolled back

Controller --> Facade layer --> Service --> Repository/Dao

Controller --> Facade layer --> Service --> Repository/Dao

立面:

@Autowired
MyServiceBean serviceBean;

@Transactional(noRollbackFor = {EntityExistsException.class, PersistException.class, ConstraintViolationException.class, DataIntegrityViolationException.class})
@override
public void facadeMethod(MyReq req) { 
     List<Customer> custList = req.getCustomers():
     for(Customer customer: CustList) {
        List<Order> orderList = customer.getOrders();
        for(Order order: orderList) {
          String dbAction = "";
           try {
               dbAction = serviceBean.insertOrder(order);
            }  catch(Exception e) {
               // log exception and roll back completely
            } 
            if("handleDupl".equalsTo(dbAction) {
                  serviceBean.handleDuplOrder(order);
            }
        }
        myService.updateCustomer(customer);
     }
}

服务:

@Autowired
MyRepository repo;

@Transactional(propagation = propagation.REQUIRES_NEW)
@override
public String inserOrder() {
  String dbAction = "";
  try {
       repo.insertOrderDao(order);
  } catch(all duplicate key exceptions like entityExist, persist, ConstraintVioaltion, DataIntegrity e) {
      dbAction = "handleDuplOrder";
  } catch(all other Exception except duplicate key e) {
        // roll back and throw exception to Facade layer
  } 
  return dbAction;
}

@Transactional(propagation = propagation.REQUIRES_NEW)
@override
public void handleDuplOrder(Order order) {
  try {
       repo.selectOrderDao(order);
       repo.updateOrder(order);
  } catch(Exception e) {
        // roll back and throw exception to Facade layer
  }
}

存储库:

@PersistentContext(unitNmae = "MY_SHCEMA")
EntityManager entityManager;

@Override
public void insertOrderDao(Order order) {
     entityManager.persist(order);
     entityManager.flush(); 
}

问题:

当我向一个有单一订单的客户发送请求时,订单是重复的,我看到在 Service 方法中捕获了 PersistException,当它从 Service 方法中存在时,它也会抛出 TransactionSystemException(嵌套异常是 RollbackException:事务被标记为仅回滚,无法提交 JPA 事务)被抛出到 Facade 层,而不管我如何抑制内部事务中的异常.

When I send req with One customer who has single order, where the order is duplicate, I see PersistException is caught inside Service method and when it exists from Service method it also throws TransactionSystemException(nested exception is RollbackException: Transaction is marked as rollback only, could not commit JPA transaction) is thrown to Facade layer irrespective of the how I suppress the exception in inner transaction.

如果我能以这种方式实现工作单元的提交或回滚,请指教.

Kindly advice If I can achieve Unit of work commit or rollback in this way.

预期:

我希望 Spring 的 @Transactional 通过不回滚和不影响下一个事务来忽略重复键异常.

I want Spring's @Transactional to ignore Duplicate key exceptions by not rolling back and not affecting the next transaction.

推荐答案

你的外部事务仍然失败,因为你在你的服务中抛出了 ApplicationDuplOrderException().

Your outer transaction still fail because you throw ApplicationDuplOrderException() inside your service.

您应该像下面这样设置您的服务:

You should setup your services like below:

@Transactional
@Override
public void facadeMethod(MyReq req) { 
     List<Customer> custList = req.getCustomers():
     for(Customer customer: CustList) {
        List<Order> orderList = customer.getOrders();
        for(Order order: orderList) {
           try {
               myService.insertOrder(order);
            } catch(Exception e) {
               // log exception and roll back completely
               throw e; // important, you must rethrow
            }
        }
        myService.updateCustomer(customer);
     }
}

@Transactional(propagation = propagation.REQUIRES_NEW)
@Override
public void inserOrder() {
  try {
       repo.insertOrderDao(order);
  } catch(all duplicate key exceptions like entityExist, persist, ConstraintVioaltion, DataIntegrity e) {
       log.error(xxx); // instead of throwing
  } catch(all other Exception except duplicate key e) {
        throw e; 
  }
}

这篇关于使用 Hibernate JPA 处理工作单元的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆