Я столкнулся с ленивым инициалом в странных условиях.
- Транзакция: выборка базовых объектов персистентного объекта.
- Транзакция: выборка базовых объектов непостоянного объекта.
Транзакция: объединение постоянного объекта. Тогда сохранятся
непостоянный объект вызывает исключение.
javax.persistence.PersistenceException: org.hibernate.LazyInitializationException: не удалось инициализировать прокси - нет сеанса.
Выдается при сохранении сложного объекта класса Person.
public class Person {
protected List<Person> founders;
protected List<GeoObject> ownedGeoObjects;
}
public class GeoObject {
private List<Person> owners;
private Address address; //complex lazy-fetched structure of pre-defined persistent entities (country, city, etc.)
}
ownGeoObjects и основатели могут быть созданы пользователем или найдены и добавлены в списки как существующие (постоянные). Все существующие и созданные пользователем объекты хранятся в компоненте с отслеживанием состояния между транзакциями (поле person). И полностью извлечены из их отдельных транзакций. Тогда сохранение всех структур происходит из commitPerson ():
@Stateful
public class SessionManager {
private Person person;
private Person commitPerson(Person person) {
personManager.addPerson(person);
commitFounders(person.getFounders());
commitGeoObjects(person);
return person;
}
private void commitFounders(List<Person> founders) throws ValidationError {
for (Person founder : founders) {
if (!founder.getPersistent()) {
personManager.addPerson(founder);
}
}
}
private void commitGeoObjects(Person person) throws ValidationError {
List<GeoObject> objects = person.getOwnedGeoObjects();
for (GeoObject geoObject : objects) {
refetch(geoObject); //this is my workaround
geoObject.getOwners().add(person); //inverse relation
if (!geoObject.getPersistent()) {
geoObjectManager.addGeoObject(geoObject);
} else {
geoObjectManager.updateGeoObject(geoObject);
}
}
}
}
Исключение выдается, если один из принадлежащих GeoObjects является постоянным, а другой - нет.
at ru.vetrf.cerberus.ejb.GeoObjectManager.addGeoObject(GeoObjectManager.java:119)
эта строка
addressManager.addAddress(geoObject.getAddress());
Кажется, что сессия прошла (для непостоянного GeoObject и его адреса) после обновления (слияния) постоянного GeoObject. Почему это могло случиться?
Другие сценарии (один существующий, один новый, несколько существующих, несколько новых) проходит хорошо.
И этот список не влияет на список учредителей.
p.s. можно считать, что методы добавления / обновления состоят только из постоянных / слияния.