2015-03-09 2 views
2

У меня есть проблема, пытаясь удалить объект, вот мой код:Не удается удалить отдельностоящий объект после слияния()

@Transactional 
    private <K> void delete(String type, EntityWithId<K> entity) { 
    try { 
     em.remove(em.contains(entity) ? entity : em.merge(entity)); 
    } catch (Exception e) { 
     logger.warn("Unable to delete " + type + " with id " + entity.getId()); 
    } 
    } 

Я не понимаю, почему, но заявление удалить не удается, выбрасывая

java.lang.IllegalArgumentException: Removing a detached instance 

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

Я что-то не так?

Вот StackTrace для пойманной Exception:

Unable to delete log with id 14091612 
java.lang.IllegalArgumentException: Removing a detached instance myproj.jpa.AdvertisementLog#14091612 
    at org.hibernate.ejb.event.EJB3DeleteEventListener.performDetachedEntityDeletionCheck(EJB3DeleteEventListener.java:67) 
    at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:107) 
    at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74) 
    at org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:822) 
    at org.hibernate.internal.SessionImpl.delete(SessionImpl.java:801) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.remove(AbstractEntityManagerImpl.java:880) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365) 
    at com.sun.proxy.$Proxy59.remove(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) 
    at com.sun.proxy.$Proxy59.remove(Unknown Source) 
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.delete(DeleteOldAdvertisementsImpl.java:93) 
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.deleteAll(DeleteOldAdvertisementsImpl.java:86) 
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.deleteAll(DeleteOldAdvertisementsImpl.java:80) 
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.deleteAd(DeleteOldAdvertisementsImpl.java:69) 
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.clean(DeleteOldAdvertisementsImpl.java:54) 
    at myproj.batch.main.DeleteOldAdvertisementsMain.main(DeleteOldAdvertisementsMain.java:13) 
+0

Вы уверены, что 'remove' бросает исключение? Дайте нам трассировку стека. Это может быть «слияние», выбрасывающее исключение, возможно, он видит «сущность» как снятую/удаленную, следовательно, «IllegalArgumentException». – Dragan

+0

Что делать, если вы делаете em.contains() на возвращенном объекте em.merge() - исключение указывает, что объект, который вы пытаетесь удалить, не подключен –

+0

Исключение выбрано из вызова remove() и после вызова слияния объект все еще не содержится внутри EntityManager ... но у меня нет никакой подсказки, почему это происходит. – DocKuro

ответ

1

Я вижу аннотации на частном методе, поэтому его называют из класса. Является ли этот класс классом @Service? Можете ли вы предоставить более подробную информацию о методе, который внутренне вызывает функцию удаления. Spring Transactional аннотации игнорируются для частных/защищенных методов. Они поддерживаются только общественными методами.

EDIT

Это не достаточно просто сделать метод общественности, что точка входа в бобе (откуда вы назвали, что частный метод)? Если этот метод записи не вызывается из весеннего компонента (например, из поля с автоподстановкой), и он не аннотируется с @Transactional, то это причина вашей проблемы.

+0

Я делаю manteinance старой базы данных, и этот класс - это просто пакет, который восстанавливает старые объекты и удаляет их; класс не аннотируется сам. Я попытаюсь завернуть вызов remove() в транзакцию, запущенную программно, и опубликовать результаты. – DocKuro

+0

Я сделал метод общедоступным для работы аннотации, но все равно не повезло ... ошибка все тот же. – DocKuro

+1

@DocKuro Недостаточно просто сделать метод общедоступным, какова точка входа в компонент (откуда вы назвали этот частный метод)? Если этот метод записи не вызывается из весеннего компонента (например, из поля с автоподстановкой), и он не аннотируется с помощью '@ Transactional', то это является причиной вашей проблемы. –

1

Вам не нужно использовать слияние перед удалением, почему вы объединяете то, что хотите удалить?

Вместо просто сделать, как показано ниже:

//begin transaction 
YourEntity entity = entityManager.getReference(The_Class, The_ID); 
entityManager.remove(entity); 
+0

Я изменил код, чтобы восстановить ссылку на объект вместо слияния. Таким образом, исключение не выбрасывается, но исключение не выдается! Глядя на журнал, я вижу, что единственными выданными командами являются команды выбора ... – DocKuro

+0

Возможно, транзакция не обрабатывается автоматически, и вы должны вывести 'entityManager.getTransaction(). Begin()' перед удалением и 'entityManager .getTransaction(). commit() 'после него. – Giovanni

+0

Нет, удаление аннотации @Transactional и завершение команды в транзакции вручную приводит к другому Исключение: «Не разрешено создавать транзакцию на совместно используемом EntityManager - используйте Spring-транзакции или EJB CMT вместо этого» Кажется, что Spring хочет управлять транзакциями :) – DocKuro

Смежные вопросы