PersistentObjectException: detached entity passed to persist thrown by JPA and Hibernate

前端 未结 18 2347
醉酒成梦
醉酒成梦 2020-11-22 05:10

I have a JPA-persisted object model that contains a many-to-one relationship: an Account has many Transactions. A Transaction has one

相关标签:
18条回答
  • 2020-11-22 05:39

    You need to set Transaction for every Account.

    foreach(Account account : accounts){
        account.setTransaction(transactionObj);
    }
    

    Or it colud be enough (if appropriate) to set ids to null on many side.

    // list of existing accounts
    List<Account> accounts = new ArrayList<>(transactionObj.getAccounts());
    
    foreach(Account account : accounts){
        account.setId(null);
    }
    
    transactionObj.setAccounts(accounts);
    
    // just persist transactionObj using EntityManager merge() method.
    
    0 讨论(0)
  • 2020-11-22 05:42

    Since this is a very common question, I wrote this article, on which this answer is based on.

    In order to fix the problem you need to follow these steps:

    1. Removing child association cascading

    So, you need to remove the @CascadeType.ALL from the @ManyToOne association. Child entities should not cascade to parent associations. Only parent entities should cascade to child entities.

    @ManyToOne(fetch= FetchType.LAZY)
    

    Notice that I set the fetch attribute to FetchType.LAZY because eager fetching is very bad for performance.

    2. Set both sides of the association

    Whenever you have a bidirectional association, you need to synchronize both sides using addChild and removeChild methods in the parent entity:

    public void addTransaction(Transaction transaction) {
        transcations.add(transaction);
        transaction.setAccount(this);
    }
    
    public void removeTransaction(Transaction transaction) {
        transcations.remove(transaction);
        transaction.setAccount(null);
    }
    

    For more details about why it's important to synchronize both ends of a bidirectional association, check out this article.

    0 讨论(0)
  • 2020-11-22 05:42

    In your entity definition, you're not specifying the @JoinColumn for the Account joined to a Transaction. You'll want something like this:

    @Entity
    public class Transaction {
        @ManyToOne(cascade = {CascadeType.ALL},fetch= FetchType.EAGER)
        @JoinColumn(name = "accountId", referencedColumnName = "id")
        private Account fromAccount;
    }
    

    EDIT: Well, I guess that would be useful if you were using the @Table annotation on your class. Heh. :)

    0 讨论(0)
  • 2020-11-22 05:44

    In my case I was committing transaction when persist method was used. On changing persist to save method , it got resolved.

    0 讨论(0)
  • 2020-11-22 05:45

    Don't pass id(pk) to persist method or try save() method instead of persist().

    0 讨论(0)
  • 2020-11-22 05:45
    cascadeType.MERGE,fetch= FetchType.LAZY
    
    0 讨论(0)
提交回复
热议问题