Ошибка возникает потому что пытаемся сохранить/удалить/проапдейтить объект из другой сессии, который уже загружен в нашей сессии(закэширован).
Лечение:
1) 100% лекарство использовать hibernateTemplate.merge(object);
2) 100% лекарство которое приводит к обнулению всего кэша
hibernateTemplate.flush();
hibernateTemplate.clear();
hibernateTemplate.saveOrUpdate(object);
3) лекарство может не помочь
hibernateTemplate.evict(object); - убирает объекты из кэша сравнивая их по объектной ссылке
hibernateTemplate.saveOrUpdate(object); - проверяет наличие объектов в кэше(прежде чем их сохранить) по айдишнику. Вывод: такая пара смысла не имеет(ну, имеет смысл в рамках одной сессии и совсем для другого).
Можно написать так:
Class dataObjectClass = object.getClass();
long id = object.getId();
T dataObject = (T) hibernateTemplate.get(dataObjectClass, id);
if (dataObject != null) {
hibernateTemplate.evict(dataObject );
}
Но это спасёт нас только в том случае - если в ентитях нигде нету перекрёстных ссылок. Если они есть - то при каскадном сохранении будут ентити добавляться в кэш по нескольку раз и в результате получим тот же иксэпшн(Зы: иксэпшн будет валиться непосредственно при комите транзакции и всякие flush перед evict тут непомогут).
4) делать всё в одной сессии
5)загрузить по id, выставить необходимые поля, сохранить
четверг, 24 сентября 2009 г.
org.hibernate.LazyInitializationException
Возникает потому что сессия, в которой был получен объект - закрыта, а поля объекта были помечены как @XXXToXXX(fetch = FetchType.LAZY).
Лечение:
1)меняем аннотацию на @XXXToXXX(fetch =FetchType.EAGER) - самый простой способ но вызывает осложнения типа долгой загрузки объекта
2)вычитав объект впервые тут же инициализируем поле с FetchType.LAZY -
делаем это так - hibernateTemplate.initialize(entity) - самый бестолковый способ
3)даём новой сессии права на работу с объектом -
if (!hibernateTemplate.contains(track)) {
you only use lock() if you are sure that the object has not been modified - иначе
org.springframework.dao.InvalidDataAccessApiUsageException: cannot lock an unsaved transient instance:
4) делать всё в одной сессии
5)прикрепляем к новой сессии через
if (!hibernateTemplate.contains(track)) {
List<Customer> list = hibernateTemplate.find(
"select distinct с from Customer с " +
"left join fetch c.orders where c=?", customer);
в sql
http://bwinterberg.blogspot.com/2009/08/how-to-eagerly-fetch-associations-with.html
7)Есть спец фильтры для загрузки нужных частей сущностей см. тут
http://bwinterberg.blogspot.com/2009/09/hibernate-preload-pattern.html
8)держать сессию открытой(паттерн типа '...а после нас хоть потоп') http://alekseiko.blogspot.com/2010/02/hibernate-lazyinitializationexception.html
9)загрузить по id, выставить необходимые поля, сохранить
10)Написать свою аннотацию, которая будет проверять необходимость переподключения коллекции к новой сессии: http://9mmedia.com/blog/?p=272
Лечение:
1)меняем аннотацию на @XXXToXXX(fetch =FetchType.EAGER) - самый простой способ но вызывает осложнения типа долгой загрузки объекта
2)вычитав объект впервые тут же инициализируем поле с FetchType.LAZY -
делаем это так - hibernateTemplate.initialize(entity) - самый бестолковый способ
3)даём новой сессии права на работу с объектом -
if (!hibernateTemplate.contains(track)) {
hibernateTemplate.lock(track, LockMode.READ);;- самый клёвый способ НО!
you only use lock() if you are sure that the object has not been modified - иначе
org.springframework.dao.InvalidDataAccessApiUsageException: cannot lock an unsaved transient instance:
4) делать всё в одной сессии
5)прикрепляем к новой сессии через
if (!hibernateTemplate.contains(track)) {
hibernateTemplate.merge(track);}
6)если таки точно собрались загружать поля то можно сделать hql запрос типа:List<Customer> list = hibernateTemplate.find(
"select distinct с from Customer с " +
"left join fetch c.orders where c=?", customer);
в sql
select
distinct
c
from
Customer c
left
join
fetch
c.orders
http://bwinterberg.blogspot.com/2009/08/how-to-eagerly-fetch-associations-with.html
7)Есть спец фильтры для загрузки нужных частей сущностей см. тут
http://bwinterberg.blogspot.com/2009/09/hibernate-preload-pattern.html
8)держать сессию открытой(паттерн типа '...а после нас хоть потоп') http://alekseiko.blogspot.com/2010/02/hibernate-lazyinitializationexception.html
9)загрузить по id, выставить необходимые поля, сохранить
10)Написать свою аннотацию, которая будет проверять необходимость переподключения коллекции к новой сессии: http://9mmedia.com/blog/?p=272
среда, 23 сентября 2009 г.
Тик-так, ж-ж-ж
Тик-так, ж-ж-ж.
Огромный серый грибулонский разведывательный корабль тихо плыл сквозь черную пустоту (а может, пустую черноту?). Он несся с невероятной, захватывающей дух скоростью, и все же на фоне биллионов далеких-далеких звезд казалось, будто он не движется вовсе. Так, темная крапинка, примерзшая к бархатной подкладке бриллиантовой ночи.
На борту корабля все шло так, как было тысячелетиями. Тишь-гладь-темень.
Тик-так, ж-ж-ж.
Ну-у-у, редкие исключения не в счет.
Тик-тик-так, ж-ж-ж.
Тик-ж-ж-так-ж-ж-тик-ж-ж.
Тик-тик-тик-тик-так-ж-ж.
Хм-м-м.
Огромный серый грибулонский разведывательный корабль тихо плыл сквозь черную пустоту (а может, пустую черноту?). Он несся с невероятной, захватывающей дух скоростью, и все же на фоне биллионов далеких-далеких звезд казалось, будто он не движется вовсе. Так, темная крапинка, примерзшая к бархатной подкладке бриллиантовой ночи.
На борту корабля все шло так, как было тысячелетиями. Тишь-гладь-темень.
Тик-так, ж-ж-ж.
Ну-у-у, редкие исключения не в счет.
Тик-тик-так, ж-ж-ж.
Тик-ж-ж-так-ж-ж-тик-ж-ж.
Тик-тик-тик-тик-так-ж-ж.
Хм-м-м.
Подписаться на:
Сообщения (Atom)