OptmisticLockingException для внутреннего поля - PullRequest
2 голосов
/ 09 января 2012

У меня есть этот класс Person, который является частью различных других транзакций, таких как, например, продажа или платеж.У меня есть этот класс Person, связанный с оплатой и продажей без каскадирования.Поэтому, когда я хочу сохранить продажи, которые также имеют платежи.Я делаю это.

OBS: у меня есть SalesBean, PaymentBean, PersonBean

1 - Sales Bean сначала пытается сохранить платеж.2 - SalesBean вызывает PaymentBean.persistPayment (), чтобы сохранить платеж.Внутри PaymentBean.persistPayment () PersonBean вызывается для сохранения персоны, которой назначен платеж, при возврате persistPerson ().и платеж сохраняется и возвращается в SalesBean.3 - В SalesBean он получает возвращенный платеж, получает уже существующего клиента, присваивает его обратно объекту «Продажа» и пытается его сохранить.

В настоящее время я получаю OptmisticLockingException с жалобой на то, что телефон внутри клиента был изменен, удален и т. Д. С момента его последнего чтения.Я не думаю, что это правда, потому что я нахожусь на ранних стадиях разработки, и я вызываю этот метод из юнит-теста.

OBS: 1 - Все сущности наследуют поле версии от одного AbstractEntity

PS: позже я попытался выполнить refresh () с помощью диспетчера сущностей SalesBean, но я получил исключение EntityNotFoundException, даже сначала проверяя его с помощью EntityManager.contains ().

public class Person extends AbstractCRMEntity {

    static private final long serialVersionUID = 201111151919L;

    @Id @GeneratedValue
    private long id;

    ...

    @JoinTable(name="PERSON_TELEPHONES")
    @ManyToMany(cascade=CascadeType.ALL)
    private Set<Telephone> telephones;

public class Telephone extends AbstractCRMEntity {

    static private final long serialVersionUID = 201111151918L;

    @EmbeddedId
    private TelephoneID phone;

    ...

    @ManyToMany(mappedBy="telephones", fetch=FetchType.LAZY)
    private Set<Person> owners;

if (saleEntity.getOwner() != null && saleEntity.getOwner().getId() <= 0) {
    OpResult clientResult = personManager.persistPerson(saleEntity.getOwner());
    if (clientResult.getOutcome().equals(OpResult.FAILURE)) {
        retorno.append(clientResult);
    } else {
            Person client = (Person) clientResult.getResult();
//                if (em.contains(client)) {
//                  logger.log(Level.INFO, "SalesManagerBean refresh client {0}", client.getName());
//                  em.refresh(client);
//                } else {
//                  logger.log(Level.INFO, "SalesManagerBean find client {0}", client.getName());
//                        client = em.find(Person.class, client.getId());
//                }
                saleEntity.setOwner((Person) clientResult.getResult());
        }
}


********************************

if (availableCreditToPay.compareTo(saleEntity.getBalance().getAmount()) > 0) {
    em.merge(saleEntity);
        // APLLY THE PAYMENTS TO THE SALE UNTIL PAID ...
} else { // not enough unapplied payments to pay
    BigDecimal unpaidDifference = saleEntity.getBalance().getAmount().subtract(availableCreditToPay);
        if (saleEntity.getOwner().getCreditLimit() != null && saleEntity.getOwner().getCreditLimit().getAmount() != null  && saleEntity.getOwner().getCreditLimit().getAmount().floatValue() >= unpaidDifference.floatValue()) { // customer has credit limit
            em.merge(saleEntity);
        } else { // customer does not have credit limit
            if (saleEntity.getCoSigner() == null ? false : (saleEntity.getCoSigner().getCreditLimit().getAmount().floatValue() >= unpaidDifference.floatValue())) {
                    em.merge(saleEntity);
                }
        }
}

**********************************

Первый блок кода выполняется до слияния.Я пытаюсь проверить, сохранился ли клиент уже.Если нет, я стараюсь это упорствовать.Иногда клиент сохраняется здесь, но в большинстве случаев он сохраняется раньше с помощью аналогичного вызова, например «paymentManager.persistCreditTransaction (currentPmt);»который сохраняет любой платеж, если таковой имеется, от этого клиента, который, следовательно, сохраняет Персона и присваивает его обратно в saleEntity

1 Ответ

4 голосов
/ 09 января 2012

Я предполагаю, что вы объединяете один и тот же объект несколько раз из одного и того же оригинала.

т.е.

  • вы получаете объект с версией 1
  • вы объединяете его (подтвержденная версия теперь 2, но версия вашей локальной копии по-прежнему 1)
  • вы снова вызываете merge и получаете ошибку блокировки, потому что вы пытаетесь зафиксировать старые данные

Вам необходимо обновлять локальную копию после каждого слияния, возвращая зафиксированный объект после каждого коммита или начала каждой транзакции.

...