简体   繁体   中英

save working but persist not working in hibernate 4.1.1

I am trying to save data usign hsqldb and I am using hibernate 4.1.4.Final. My problem is I want to save data using persist but when I tried to do it's showing following error:

org.hibernate.PersistentObjectException: detached entity passed to persist: main.java.entity.Advocate
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:835)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:828)
    at org.hibernate.engine.spi.CascadingAction$7.cascade(CascadingAction.java:315)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:844)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:819)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:823)
    at main.java.service.LegalService.registerCase(LegalService.java:46)
    at main.java.tester.Tester.registerCase(Tester.java:52)
    at main.java.tester.Tester.main(Tester.java:28)

But when I use save method it worked.So I want to know how persist and save makes difference? and my entity classes are serialized.How to solve this persist error.

Here is my class

package main.java.service;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import main.java.businessTier.CaseTO;
import main.java.entity.Advocate;
import main.java.entity.Case;

public class LegalService {

     Configuration configuration = new Configuration().configure();

     ServiceRegistry  serviceRegistry = new ServiceRegistryBuilder().applySettings(
               configuration.getProperties()). buildServiceRegistry();
    SessionFactory   sessionFactory = configuration.buildSessionFactory(serviceRegistry);







    public int registerCase(CaseTO caseTO) {
        try
        {
             Session session;
           session=sessionFactory.openSession();
           session.beginTransaction();

        Case c = new Case();
        Advocate a = new Advocate();
         a.setAdvocateId(caseTO.getAdvocateId());
        c.setAdvocate(a);
        c.setClientAge(caseTO.getClientAge());
        c.setClientName(caseTO.getClientName());
        c.setDate(caseTO.getDate());
        c.setDescription(caseTO.getDescription());

        session.persist(c);
        session.getTransaction().commit();
        return c.getCaseNo();
        }
        catch(Exception e){
            e.printStackTrace();
            return 0;
        }



    }

}

Here are my entity class Advocate.java

package main.java.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

@Entity
@Table(name="Db_Advocate")
@DynamicInsert(value=true)
@DynamicUpdate(value=true)
public class Advocate {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="advocateId")
    private Integer advocateId;

    @Column(name="name")
    private String name;
    @Column(name="age")
    private Integer age;
    @Column(name="category")
    private String category;
    @Column(name="court")
    private String court;
    @Column(name="city")
    private String city;
    public Integer getAdvocateId() {
        return advocateId;
    }
    public void setAdvocateId(Integer advocateId) {
        this.advocateId = advocateId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getCategory() {
        return category;
    }
    public void setCategory(String category) {
        this.category = category;
    }
    public String getCourt() {
        return court;
    }
    public void setCourt(String court) {
        this.court = court;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }



}

Case.java

package main.java.entity;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;


import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

@Entity
@Table(name="DB_CASE")
@DynamicInsert(value=true)
@DynamicUpdate(value=true)
public class Case {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer caseNo;
    @JoinColumn(name="advocateId")
    @ManyToOne(cascade=CascadeType.ALL)
    private Advocate advocate;
    private String clientName;
    private Integer clientAge;
    private String description;
    private Date date;


    public Integer getCaseNo() {
        return caseNo;
    }

    @Column(name="caseNo")
    public void setCaseNo(Integer caseNo) {
        this.caseNo = caseNo;
    }
    public Advocate getAdvocate() {
        return advocate;
    }


    public void setAdvocate(Advocate advocateId) {
        this.advocate = advocateId;
    }
    public String getClientName() {
        return clientName;
    }
    public void setClientName(String clientName) {
        this.clientName = clientName;
    }
    public Integer getClientAge() {
        return clientAge;
    }
    public void setClientAge(Integer clientAge) {
        this.clientAge = clientAge;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Date getDate() {
        return date;
    }

    @Column(name="data",nullable=true)
    public void setDate(Date date) {
        this.date = date;
    }



}

Please Add below code at id

@Id @GeneratedValue(strategy = GenerationType.AUTO)

Then persist will work

First you need to understand behaviour of persist(). Below are the links that will help you understand the behaviour Whats the difference between persist() and save() in Hibernate? http://javarevisited.blogspot.in/2012/09/difference-hibernate-save-vs-persist-and-saveOrUpdate.html

Now in order to solve this problem in your code .. use merge() instead of persist().

Why persist() gave the exception

persist() does not work for detached objects .You need to know how hibernate determines whether an object is detached or not.

UPDATE

Why the identifier generation strategy auto solved your problem

As i mentioned above that you need to understand the rules by which hibernate identifies whether an object is detached or transient. Below are the rule

  1. If the the entity has a null value for identifier or the version attribute is null it is considered as transient other wise detached.

  2. If you use auto-generated identifiers, and the identifier is not null, then Hibernate considers it as a detached entity.

  3. If you are using assigned identifier strategy then hibernate will issue a fetch to determine whether the identifier exists in db based on that your entity will be either transient or detached.

Now that being said .. we analyse your code.

In your code you have Advocate entity whose identifier strategy is IDENTITY.In the below code

  Case c = new Case();
    Advocate a = new Advocate();
     a.setAdvocateId(caseTO.getAdvocateId());

You are setting the identifier property of Advocate instance manually.At the time of flush when transaction commits ,hibernate will see that the identifier generation strategy is IDENTITY and the identifier value is set in the advocate instance hence it will conclude that the entity instance is detached (this is from the rule 1 described above).And hence the persist() method gave exception for the advocate instance as it is deemed to be detached from hibernate.

From rule 2 we can say that your code will not work just by changing the generation strategy to auto.You might have done some other changes.

I have tried your code on my system it is giving the same exception even if i change the generation strategy to auto which is in consistent with the rules

You might be doing something different in your code .. please check and update.

Please also post the identifier that you are setting in the advocate and the actual identifier generated for that advocate in database with auto generation strategy, that might be helpful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM