не удается создать версию для одного владельца коллекции - PullRequest
1 голос
/ 27 апреля 2010

данный родительский объект

@Entity
public class Expenditure implements Serializable {
...
    @OneToMany(mappedBy = "expenditure", cascade = CascadeType.ALL, orphanRemoval = true)
    @OrderBy()
    private List<ExpenditurePeriod> periods = new ArrayList<ExpenditurePeriod>();

    @Version
    private Integer version = 0;
...
}

и ребенок один

@Entity
public class ExpenditurePeriod implements Serializable {
...
    @ManyToOne
    @JoinColumn(name="expenditure_id", nullable = false)
    private Expenditure expenditure;
...
}

При обновлении родительского и дочернего элементов в одной транзакции генерируется исключение org.hibernate.StaleObjectStateException: строка была обновлена ​​или удалена другой транзакцией (или отображение несохраненного значения было неверным):

Действительно, hibernate выпускает два обновления sql: одно изменяет родительские свойства, а другое - дочерние свойства. Знаете ли вы, как избавиться от родительского обновления, меняющего ребенка? Обновление приводит к неэффективности и ложному срабатыванию для оптимистической блокировки. Обратите внимание, что и ребенок, и родитель сохраняют свое состояние в БД правильно.

Hibernate версия 3.5.1-Final

1 Ответ

0 голосов
/ 28 апреля 2010

(...) Действительно, hibernate выпускает два обновления sql: одно изменяет родительские свойства, а другое - дочерние свойства.

Если вы обновили родитель и потомок в одной транзакции , разве это не ожидаемый результат?

Знаете ли вы, как избавиться от родительского обновления, меняющего ребенка? Обновление приводит к неэффективности и ложному срабатыванию для оптимистической блокировки.

Я не понимаю проблемы и не могу ее воспроизвести. Следующий метод тестирования (который выполняется внутри транзакции) работает для меня (и он генерирует два обновления, как и ожидалось, так как я изменил и родительский и один дочерний).

@Test
public void testUpdate() {
    Expenditure expenditure = new Expenditure();
    ExpenditurePeriod expenditurePeriod1 = new ExpenditurePeriod();
    ExpenditurePeriod expenditurePeriod2 = new ExpenditurePeriod();

    expenditure.getPeriods().add(expenditurePeriod1);
    expenditure.getPeriods().add(expenditurePeriod2);
    expenditurePeriod1.setExpenditure(expenditure);
    expenditurePeriod2.setExpenditure(expenditure);

    em.persist(expenditure);
    em.flush();

    assertNotNull(expenditure.getId());
    assertNotNull(expenditurePeriod1.getId());
    assertNotNull(expenditurePeriod2.getId());
    assertEquals(Integer.valueOf(0), expenditure.getVersion());
    assertEquals(Integer.valueOf(0), expenditurePeriod1.getVersion());
    assertEquals(Integer.valueOf(0), expenditurePeriod2.getVersion());

    expenditure.setProperty("a");
    expenditurePeriod1.setProperty("b");

    em.merge(expenditure);
    em.flush();

    assertEquals(Integer.valueOf(1), expenditure.getVersion());
    assertEquals(Integer.valueOf(1), expenditurePeriod1.getVersion());
    assertEquals(Integer.valueOf(0), expenditurePeriod2.getVersion());
}

Если это не соответствует вашей ситуации, уточните.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...