JPA thinks I'm deleting a detached object

前端 未结 7 2190
萌比男神i
萌比男神i 2020-12-14 00:30

I\'ve got a DAO that I used to load and save my domain objects using JPA. I finally managed to get the transaction stuff working, now I\'ve got another issue.

In my

相关标签:
7条回答
  • 2020-12-14 00:42

    I suspect that you are running your code outside a transaction so your find and delete operations occur in a separate persistence context and the find actually returns a detached instance (so JPA is right and you ARE deleting a detached object).

    Wrap your find / delete sequence inside a transaction.

    Update: Below an excerpt of the chapter 7.3.1. Transaction Persistence Context:

    If you use an EntityManager with a transaction persistence context model outside of an active transaction, each method invocation creates a new persistence context, performs the method action, and ends the persistence context. For example, consider using the EntityManager.find method outside of a transaction. The EntityManager will create a temporary persistence context, perform the find operation, end the persistence context, and return the detached result object to you. A second call with the same id will return a second detached object.

    0 讨论(0)
  • 2020-12-14 00:43

    +1 to Pascal Thivent's post and just a followup.

        @Transactional
        public void remove(long purchaseId){
            Purchase attached = jpaTemplate.find(Purchase.class,purchaseId);
            jpaTemplate.remove(attached);
        }
    
    0 讨论(0)
  • 2020-12-14 00:43

    What worked for me was calling flush so the changes are made as in the following example:

    @PersistanceContext
    EntityManager em;
    
    public SomeObject(...parameters){
        repository.save();
        em.flush();
        repository.delete();
    }
    
    0 讨论(0)
  • 2020-12-14 00:46

    Transaction ensures the ACID properties but not whether the entity is attached or detached. Even if you are running entityManager.find and entityManager.remove() in the same transaction , there is not guarantee that the entity will be attached. So before issuing entityManager.remove() check if the entity is attached, if not attach it using enitityManger.merge(entity) and then issue entityManager.remove on it as follows:

    @Transactional
     public void delete (long id)
        {
    ModelObj modelObj=entityManager.find(ModelObj.class,id);
    modelObj=entityManager.contains(modelObj)?modelObj:entityManager.merge(modelObj);
            em.remove (modelObj);
        }
    
    0 讨论(0)
  • 2020-12-14 00:54

    Get the instance by using em.getReference() instead of em.find().

    For instance, try:

    em.remove(em.getReference(INTFC.class, id)); 
    
    0 讨论(0)
  • 2020-12-14 01:00
    public void remove(Object obj){
        em.remove(em.merge(obj));
    }
    

    The above code is similar to that proposed by zawhtut

    0 讨论(0)
提交回复
热议问题