Подтвердить что ты не робот

Java.lang.IllegalArgumentException: Удаление отдельного экземпляра com.test.User # 5

У меня есть проект Java EE с использованием JPA (transaction-type = "JTA" ), спящий режим как поставщик. Я пишу свой beans для обработки вещей CRUD. Программа работает в JBOSS 7 AS.

У меня есть EntityManagerDAO:

@Stateful
public class EntityManagerDao implements Serializable {

    @PersistenceContext(unitName = "dtdJpa")
    private EntityManager entityManager;

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public Object updateObject(Object object) {
        object = entityManager.merge(object);
        return object;
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void createObject(Object object) {
        entityManager.persist(object);
    }

    public void refresh(Object object) {
        entityManager.refresh(object);
    }

    public <T> T find(Class<T> clazz, Long id) {
        return entityManager.find(clazz, id);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void deleteObject(Object object) {
        entityManager.remove(object);
    }
}

но когда я вызываю deleteObject, это исключение появляется.

java.lang.IllegalArgumentException: удаление отсоединенного экземпляра com.test.User # 5

Как это вызвано и как я могу его решить?

4b9b3361

Ответ 1

EntityManager#remove() работает только для объектов, которые управляются в текущей транзакции/контексте. В вашем случае вы извлекаете объект в более раннюю транзакцию, сохраняете ее в сеансе HTTP и затем пытаетесь удалить ее в другой транзакции/контексте. Это просто не сработает.

Вам нужно проверить, управляется ли объект с помощью EntityManager#contains(), а если нет, то заставьте его управлять EntityManager#merge().

В принципе, метод delete() вашего бизнес-класса должен выглядеть следующим образом:

em.remove(em.contains(entity) ? entity : em.merge(entity));

Ответ 2

В моем случае я получил ту же ошибку, когда попытался удалить объект используя

session.delete(obj)

не создавая транзакций до этого.

И проблема решена путем создания транзакции сначала (session.beginTransaction(), а затем удаления объекта.

Я надеюсь, что мой ответ поможет кому-то:)

Ответ 3

Я столкнулся с той же проблемой. Отделяемый объект должен быть повторно присоединен. Как упоминал @BalusC, использование EntityManager.merge() должно использоваться для прикрепления отдельного объекта. EntityManager.merge() генерирует SQL-запрос, который извлекает текущее состояние объекта, на котором должен выполняться EntityManager.remove(). Но в моем случае это не сработало. Вместо этого попробуйте EntityManager.remove(EntityManager.find(Class<T>,arg)). Это сработало для меня.

Ответ 4

Иногда это просто потому, что вам не хватает аннотации @Transaction для операций добавления, удаления и обновления.

Ответ 5

По моему опыту, если я запрашиваю объект из БД, затем закрываю менеджер сущностей, а затем делаю удаление БД, возникает проблема. Или, если я скопирую этот загруженный объект в другой экземпляр, затем выполню удаление, эта проблема также произойдет. На мой взгляд, есть две вещи, на которые стоит обратить внимание:

  • Объект должен находиться в том же сеансе, который был создан Entity Manager
  • И объект не должен быть передан другому объекту, пока сеанс Entity Manager все еще открыт.

ура

Ответ 6

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

String petId = pet.getId().toString();
entityManager.createQuery("DELETE FROM Pet pet WHERE id=" + petId).executeUpdate();

После того, как вы можете очистить контекст

if (em.contains(pet)){
     em.remove(pet);
}