ProgramingTip

org.hibernate.PersistentObjectException : 분리 된 지속가 지속 전달.

bestdevel 2020. 10. 24. 11:20
반응형

org.hibernate.PersistentObjectException : 분리 된 지속가 지속 전달.


최대 포맷 모드로 첫 번째 마스터 마이어 예제를 사용으로 작성했습니다. 며칠 후 다시 가져 오기 일부 라이브러리를 업그레이드했습니다. 내가 뭘했는지는 모르겠지만 다시는 수 없습니다. 다음 오류 메시지를 반환하는 코드에서 어떤 것이 있는지 알아낼 수 있습니까?

org.hibernate.PersistentObjectException: detached entity passed to persist: example.forms.InvoiceItem
    at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
    at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:799)
    at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:791)
    .... (truncated)

최대 매핑 매핑 :

<hibernate-mapping package="example.forms">
    <class name="Invoice" table="Invoices">
        <id name="id" type="long">
            <generator class="native" />
        </id>
        <property name="invDate" type="timestamp" />
        <property name="customerId" type="int" />
        <set cascade="all" inverse="true" lazy="true" name="items" order-by="id">
            <key column="invoiceId" />
            <one-to-many class="InvoiceItem" />
        </set>
    </class>
    <class name="InvoiceItem" table="InvoiceItems">
        <id column="id" name="itemId" type="long">
            <generator class="native" />
        </id>
        <property name="productId" type="long" />
        <property name="packname" type="string" />
        <property name="quantity" type="int" />
        <property name="price" type="double" />
        <many-to-one class="example.forms.Invoice" column="invoiceId" name="invoice" not-null="true" />
    </class>
</hibernate-mapping>

편집 : InvoiceManager.java

class InvoiceManager {

    public Long save(Invoice theInvoice) throws RemoteException {
        Session session = HbmUtils.getSessionFactory().getCurrentSession();
        Transaction tx = null;
        Long id = null;
        try {
            tx = session.beginTransaction();
            session.persist(theInvoice);
            tx.commit();
            id = theInvoice.getId();
        } catch (RuntimeException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
            throw new RemoteException("Invoice could not be saved");
        } finally {
            if (session.isOpen())
                session.close();
        }
        return id;
    }

    public Invoice getInvoice(Long cid) throws RemoteException {
        Session session = HbmUtils.getSessionFactory().getCurrentSession();
        Transaction tx = null;
        Invoice theInvoice = null;
        try {
            tx = session.beginTransaction();
            Query q = session
                    .createQuery(
                            "from Invoice as invoice " +
                            "left join fetch invoice.items as invoiceItems " +
                            "where invoice.id = :id ")
                    .setReadOnly(true);
            q.setParameter("id", cid);
            theInvoice = (Invoice) q.uniqueResult();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
        } finally {
            if (session.isOpen())
                session.close();
        }
        return theInvoice;
    }
}

Invoice.java

public class Invoice implements java.io.Serializable {

    private Long id;
    private Date invDate;
    private int customerId;
    private Set<InvoiceItem> items;

    public Long getId() {
        return id;
    }

    public Date getInvDate() {
        return invDate;
    }

    public int getCustomerId() {
        return customerId;
    }

    public Set<InvoiceItem> getItems() {
        return items;
    }

    void setId(Long id) {
        this.id = id;
    }

    void setInvDate(Date invDate) {
        this.invDate = invDate;
    }

    void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    void setItems(Set<InvoiceItem> items) {
        this.items = items;
    }
}

InvoiceItem.java

public class InvoiceItem implements java.io.Serializable {

    private Long itemId;
    private long productId;
    private String packname;
    private int quantity;
    private double price;
    private Invoice invoice;

    public Long getItemId() {
        return itemId;
    }

    public long getProductId() {
        return productId;
    }

    public String getPackname() {
        return packname;
    }

    public int getQuantity() {
        return quantity;
    }

    public double getPrice() {
        return price;
    }

    public Invoice getInvoice() {
        return invoice;
    }

    void setItemId(Long itemId) {
        this.itemId = itemId;
    }

    void setProductId(long productId) {
        this.productId = productId;
    }

    void setPackname(String packname) {
        this.packname = packname;
    }

    void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    void setPrice(double price) {
        this.price = price;
    }

    void setInvoice(Invoice invoice) {
        this.invoice = invoice;
    }
}

편집 : 클라이언트에서 보낸 JSON 개체 :

{"id":null,"customerId":3,"invDate":"2005-06-07T04:00:00.000Z","items":[
{"itemId":1,"productId":1,"quantity":10,"price":100},
{"itemId":2,"productId":2,"quantity":20,"price":200},
{"itemId":3,"productId":3,"quantity":30,"price":300}]}

편집 : 일부 세부 정보 :
다음 두 가지 방법으로 송장을 저장했습니다.

  1. 위에서 언급 한 json 객체를 수동으로 제작하여 서버의 새로운 세션에 전달했습니다. 이 경우 save 메소드를 호출하기 전에 아무런 활동도하지 않았으므로 save 메소드에서 열린 세션을 제외하고는 열린 세션이 없어야합니다.

  2. getInvoice 메소드를 사용하여 기존 데이터를로드하고 키 값을 제거한 후 동일한 데이터를 전달했습니다. 이것도 트랜잭션이 getInvoice 메소드에서 커밋되므로 저장하기 전에 세션을 닫아야한다고 생각합니다.

두 경우 모두 최대 절전 모드 구성 파일이나 엔티티 클래스 또는 저장 방법에 문제가 있다고 믿도록하는 동일한 오류 메시지가 표시됩니다.

더 자세한 정보를 제공해야하는지 알려주세요.


관련 세부 정보를 많이 제공하지 않았으므로 호출 getInvoice한 다음 결과 개체를 사용하여 일부 값을 설정하고 save개체 변경 사항이 저장된다는 가정하에 호출 했습니다.

그러나 persist작업은 새로운 임시 개체를위한 것이며 id가 이미 할당되어 있으면 실패합니다. 귀하의 경우에는 saveOrUpdate대신 persist.

JPA / EJB 코드와 함께 "오류를 지속하기 위해 전달 된 분리 된 엔티티"에서 몇 가지 논의 및 참조를 찾을 수 있습니다.


여기에서는 기본을 사용하고 기본 키에 값을 할당했으며 기본 기본 키는 자동으로 생성됩니다.

따라서 문제가 다가오고 있습니다.


대부분의 경우 문제는 여기에 표시되는 코드 외부에 있습니다. 현재 세션과 연결되지 않은 개체를 업데이트하려고합니다. 인보이스가 아니라면 이미 유지되고 db에서 얻은 InvoiceItem 일 수 있으며 일종의 세션에서 살아남은 다음 새 세션에서 유지하려고합니다. 이건 불가능 해. 일반적으로 세션간에 지속 된 개체를 유지하지 마십시오.

솔루션은 즉, 유지하려는 동일한 세션에서 전체 개체 그래프를 얻는 것입니다. 웹 환경에서 이것은 다음을 의미합니다.

  • 세션 얻기
  • 연결을 업데이트하거나 추가해야하는 개체를 가져옵니다. 기본 키에 의한 선호
  • 필요한 사항 변경
  • 원하는 것을 저장 / 업데이트 / 제거 / 삭제
  • 세션 / 트랜잭션 닫기 / 커밋

계속 문제가 발생하면 서비스를 호출하는 일부 코드를 게시하십시오.


이것은 @ManyToOne 관계에 있습니다. CascadeType.PERSIST 또는 CascadeType.ALL 대신 CascadeType.MERGE를 사용하여이 문제를 해결했습니다. 도움이되기를 바랍니다.

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="updated_by", referencedColumnName = "id")
private Admin admin;

해결책:

@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name="updated_by", referencedColumnName = "id")
private Admin admin;

persist () 대신 EntityManager merge ()를 사용하여 수정 된 JPA의 경우

EntityManager em = getEntityManager();
    try {
        em.getTransaction().begin();
        em.merge(fieldValue);
        em.getTransaction().commit();
    } catch (Exception e) {
        //do smthng
    } finally {
        em.close();
    }

참고 URL : https://stackoverflow.com/questions/6378526/org-hibernate-persistentobjectexception-detached-entity-passed-to-persist

반응형