2010-10-22 4 views
1

Я столкнулся с странной проблемой с атрибутом JPA CascadeType.REFRESH. У меня есть простой родитель-потомок, в котором в родительском домене объекта (LineEquipmentFormat) я добавил каскад атрибутов, как показано нижеJPA CascadeType.REFRESH не работает?

OneToMany(cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST, 
    CascadeType.REMOVE}, mappedBy = "lineEquipmentFormat") 
public List<LineEquipmentFormatDivision> getLineEquipmentFormatDivisions() { 
    return lineEquipmentFormatDivisions; 
} 

Но когда я извлечь родительский объект LineEquipmentFormat из БД, я не получаю список of LineEquipmentFormatDivisions.

Ошибка я получаю

17:46:34,251 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: LineEquipmentFormat.lineEquipmentFormatDivisions, no session or session was closed 
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: LineEquipmentFormat.lineEquipmentFormatDivisions, no session or session was closed 
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380) 
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372) 
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365) 
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108) 
    at org.hibernate.collection.PersistentBag.toString(PersistentBag.java:506) 

Я использую Jboos 5.1 и Oracle 10G.

Просьба предоставить дополнительные сведения о возможной основной причине этой ошибки.

Благодаря

ответ

0

Спасибо за ваши комментарии.

Вот как мы, наконец, внедрили его.

  1. При получении родительского объекта «LineEquipmentFormat» мы добавили следующий дополнительный код.

    LineEquipmentFormat lef = entityManager.find (LineEquipmentFormat.class, sysId); if (lef! = Null & & lef.getLineEquipmentFormatDivisions()! = Null) { lef.getLineEquipmentFormatDivisions(). Size(); }
    return lef;

  2. Теперь, если мы можем получить дочерний список из этого родительского объекта.

+0

вместо этого вы должны использовать FETCH JOIN –

1

При определении типа каскадного как обновления, это означает, что, когда entityManager.refresh() вызывается на родительском LineEquipmentFormat, он будет также призвал детей LineEquipmentFormatDivisions. Однако ошибка, которую вы получаете, указывает на то, что вы пытались лениво инициализировать коллекцию во время закрытия сеанса. Если вам нужна эта коллекция после закрытия сеанса, вам нужно получить их с нетерпением, установив fetchType.

+0

Но я не понял вашу точку зрения на сессии. Если я делаю эту выборку LineEquipmentFormat в одной транзакции и сразу на следующей строке, если я пытаюсь получить список разделов, то, конечно, сессия не закрыта rt? Также нам не рекомендуется использовать атрибуты fetchType, чтобы исключить эту опцию! –

+0

Если вам нужны дочерние элементы каждый раз, когда вы инициализировали родительский объект, тогда нет проблемы с настройкой fetchType как нетерпеливого. Если это не так, вам нужно получить их с нетерпением только тогда, когда вам нужны они, для которых вы можете сделать запрос с помощью соединения для извлечения. Если вы разместите код, где вы запрашиваете LineEquipmentFormat и где вы пытаетесь получить доступ к LineEquipmentFormatDivisions, мы можем быть более полезными. Если вы, например, говорите, что entityManager.find (LineEquipmentFormat.class, id), сеанс открывается и закрывается в рамках этого метода. – hakan

1

Я добавил атрибуты каскада, как показано ниже (...) Но когда я получаю родительский объект LineEquipmentFormat из БД, я не получаю список объектов LineEquipmentFormatDivisions.

Каскадные операции имеет мало общего с жадным или отложенной загрузки и в вашем случае ошибка вы получаете (пресловутый LazyInitializationException) означает, что вы пытаетесь получить доступ к ленивым ассоциации, но что сессия уже закрыта (поэтому Hibernate не может загрузить его).

Чтобы избежать этой «проблемы», либо:

  • нетерпеливый нагрузки ассоциация с помощью атрибута fetchType (который IMO положить «помадой на свинье», если вам не нужно объединение в большинстве сценарии)
  • использовать FETCH JOIN для данного конкретного случая использования для извлечения ассоциации при выполнении запросов, например:

    SELECT f 
    FROM LineEquipmentFormat f LEFT JOIN FETCH f.lineEquipmentFormatDivisions 
    WHERE f.id = 1 
    
  • использовать O pen EntityManager In View pattern (в контексте MVC), чтобы открыть диспетчер сущности при поступлении запроса и оставить его открытым до тех пор, пока запрос не будет обработан (у Spring есть Serlvet filter или Interceptor, реализующий этот шаблон).