10

I'm trying to insert a person pojo to mysql db using Hibernate EntityManager persist method,

entityManagerTransactionService.getEntityManager().persist(TemplateObject);

and getting this exception,

 javax.persistence.PersistenceException:
 org.hibernate.PersistentObjectException: detached entity passed to
 persist: com.esupu.base.model.pojo.common.TitleType    at
 org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)....

and there is more..

 Caused by: org.hibernate.PersistentObjectException: detached entity
 passed to persist: com.esupu.base.model.pojo.common.TitleType  at
 org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
    at
 org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:843)

My Person.java class is,

@Entity
public class Person extends TemplateObject {

    @OneToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST,CascadeType.REFRESH })
        private TitleType titleType;
        private String middle;
        private String last;
        @OneToOne(cascade = { CascadeType.ALL })
        private Address address;
        private Date birthdate;
        private String email;
        private String telephone;
        private String fax;
        @OneToOne(cascade = { CascadeType.ALL })
        private Location location;
        @OneToOne(cascade = { CascadeType.ALL })
        private Country country;

and then the getter setter methods of the pojo ..

the error throwing TitleType class is a "public static final" title type definition provider,

@Entity
public class TitleType extends TemplateObject {

    /**
     * 
     */
    private static final long serialVersionUID = 3104954552111621034L;

    private TitleType(int id, String name) {
        setId(id);
        setName(name);
    }

    public static final TitleType MR = new TitleType(1, "Mr");
    public static final TitleType MISS = new TitleType(2, "Miss");
    public static final TitleType MRS = new TitleType(3, "Mrs");
    public static final TitleType MS = new TitleType(4, "Ms");
    public static final TitleType DOCTOR = new TitleType(5, "Doctor");
    public static final TitleType PROFESSOR = new TitleType(6, "Professor");
    public static final TitleType SIR = new TitleType(7, "Sir");
    public static final TitleType MADAM = new TitleType(8, "Madam");

}

I'm setting the title type class to the the person as,

person.setTitleType(TitleType.MR);

is it impossible to pass a public static final type defined class to Hibernate? or is there anything that I'm doing wrong?

Thanks in advance

Vikrant Kashyap
  • 5,028
  • 1
  • 23
  • 46
Supun Sameera
  • 2,553
  • 3
  • 15
  • 13

2 Answers2

21

The objects you are trying to persist include TitleType that should not have ID values. Otherwise Hibernate will check to see if that object is persistent or detached in the session context. If you don't want to persist some fields of your object like that you could use @Transient annotation to exclude those fields from the fields map when persisting the entity. This is not good to hardcode IDs in the DAOs or entities because these values could be generated by some generator but if you manually updated the database with this constants you could at least define these IDs as constants in your code and load objects from session by ID before initialize the transient or persistent instance.

Chris Betti
  • 2,374
  • 1
  • 24
  • 36
13

Instead of doing this: public static final TitleType MR = new TitleType(1, "Mr");

You should use the EntityManager to fetch that Object. Otherwhise Hibernate will notice, that this Object (with id 1) is already stored, but since you did not load it, the entity manager does not have it inside its own collection -> that's a detached entity.

So, you should do:

TitleType MR = em.find(TitleType.class, 1);
Person p = new Person(...);
p.setTitleType(MR);

em.merge(p);
dognose
  • 18,985
  • 9
  • 54
  • 99
  • I tested and find out that your answer is working also correct but i chose to remove the id from TitleType DAO as nikpon suggested so i had to choose his answer as the accepted one, many thanks for the help for both of you :) – Supun Sameera Oct 28 '13 at 12:29
  • This is a dirty approach because this mixes controller level code with persistence layer code. – CodeMed May 14 '15 at 00:32
  • 2
    @CodeMed No, it isn't. The example is quite short yes, but it is the way to go. If you want to add a new `user` to a `group`, you also need to *load* the existing group, add the new user, and finally flush your changes to the database without touching the existing group. – dognose Aug 18 '15 at 20:23