Проблема в единице обработки с использованием Hibernate JPA - PullRequest
0 голосов
/ 24 января 2019

Я использую Spring + Hibernate + JPA

Мне нужно обработать список клиентов, вставив их заказы.

Вот Единица работы:

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

Фиксация требуется, когда все процессы обработки заказов и клиентских БД в порядке.

  1. Вставить заказ

    1.a Если дублирующийся заказ не откатывается.Но выберите этот порядок из таблицы и обновите его, если статус заказа отличается в запросе от статуса в db

    1.b Если при вставке ORDER произойдет любая другая ошибка, выполните откат

    1.c Если нет ошибок, тогда продолжайте вставку заказов конкретного Клиента

  2. После выполнения заказов конкретного Клиента обновите таблицу Клиентов

  3. Цикл продолжается ..

  4. При работе с пунктами 1, 2 и 3 Если все в порядке, тогда требуется фиксация.Если возникают какие-либо проблемы в середине, то все транзакции откатываются

Контроллер -> Фасадный слой -> Сервис -> Репозиторий / 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(); 
}

Проблема:

Когда я отправляю запрос с одним клиентом, у которого есть один заказ, гдеПорядок дублируется, я вижу, что PersistException перехватывается в методе Service, и когда он существует из метода Service, он также генерирует TransactionSystemException (вложенное исключение - RollbackException: транзакция помечается как только откат, не удалось зафиксировать транзакцию JPA), выбрасывается в слой Facade независимо откак я подавляю исключение во внутренней транзакции.

Добрый совет Если я смогу добиться фиксации или отката Единицы работы таким способом.

Ожидается:

Я хочу Spring's @Транзакционный, чтобы игнорировать дублирующиеся исключения ключа, не откатываясь и не влияя на следующую транзакцию.

1 Ответ

0 голосов
/ 28 января 2019

Ваша внешняя транзакция все еще не выполнена, потому что вы добавляете ApplicationDuplOrderException() в службу.

Вы должны настроить свои услуги, как показано ниже:

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