Устаревший объект в памяти (mysql, spring 3, hibernate) - PullRequest
3 голосов
/ 03 января 2011

Я использую Spring 3, Hibernate 3.3.1 и MySQL 5.1.x (на Red Hat 5, также наблюдайте то же поведение, когда на Windows, однако). Я замечаю, что строка в базе данных обновляется, но одна из ссылок на объекты в памяти не обновляется. Я постараюсь описать структуру класса в упрощенной форме ..

class A {
  @OneToMany(cascade = CascadeType.ALL)
  List<Widget> widgets;

  @OneToMany(cascade = CascadeType.ALL)
  @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
  List<B> bObjects;

  @Transactional
  public void turnOnWidgets() { ... }
}

class B {
  @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
  @Cascade(value = { org.hibernate.annotations.CascadeType.LOCK, org.hibernate.annotations.CascadeType.EVICT})
  private A aObj;

  @Transactional(propagation=Propagation.REQUIRES_NEW)
  public void turnOnWidgets() { 
    for (Widget w : aObj.getWidgets()) {
      w.setOn(true);
    }
  }
}

class Widget {
  Boolean on;
}

Вот последовательность действий. Когда вызывается A.turnOnWidgets, он перебирает свою коллекцию «bObjects» и вызывает «turnOnWidgets» для каждого объекта B. Объект B изменяет свойство «on» для каждого виджета, на который ссылается объект A (как показано выше в B.turnOnWidgets).

Когда это происходит, я могу посмотреть на базу данных и увидеть, что значение "on" изменилось для виджетов. Однако, когда я захожу в код с помощью отладчика, я замечаю, что объект B ссылается на другой экземпляр A (например, тот же A из базы данных, но в памяти это другой экземпляр объекта Java), чем A, который я вызвал "turnOnWidgets" на.

По сути, я вижу, что когда я перемещаюсь по графу объектов, просматривая виджеты, содержащиеся в экземпляре A, свойство "on" виджетов имеет значение false. Однако, если я посмотрю на виджеты, перейдя от B.aObj.getWidgets(), их свойство "on" будет истинным.

Когда мое приложение работало с базой данных Oracle, все это работало нормально, как только я переключился на MySQL, я начал видеть эту проблему.

Кто-нибудь знает, есть ли что-то особенное в MySQL (возможно, в сочетании с Hibernate и / или Spring)?

UPDATE Так что я думаю, что я сузил его до раздела в коде, где JPA-обновление выполняется для объекта "B". При работе с oracle это приводит к правильному обновлению объектов в памяти, однако при работе с MySQL объекты не обновляются должным образом. Еще нужно выяснить почему.

Ответы [ 2 ]

0 голосов
/ 04 января 2011

оказалось, что проблема была в уровне изоляции БД, вот вопрос, который я начал с того, что решило проблему, с которой я столкнулся.

Внешняя транзакция в случае использования вложенной транзакции не видит обновления в базе данных (JPA, MySQL, Spring Framework и Hibernate)

0 голосов
/ 03 января 2011

Не уверен насчет вашей проблемы, но, думаю, вам нужно mappedBy, поскольку оно требуется для двунаправленных отношений:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "aObj")
@Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
List<B> bObjects;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...