Hibernate JPA one-to-one saving child class entity

16,072

The problem here is that the @Id of EmployeeInfo is declared as being auto-generated and you're thus not supposed to set it manually (Hibernate looks at the Entity passed to persist and assumes it is already in the database because the @Id field is populated).

In other words, remove the @GeneratedValue on EmployeeInfo if you want to set the PK manually.

Note that Hibernate provides support for OneToOne association using a shared primary key in JPA 1.0 through a custom extension. See:

In JPA 2.0, derived identifiers are well supported and you can annotate OneToOne and ManyToOne associations with @Id. See:

Share:
16,072
PaiS
Author by

PaiS

A complete techie, who realised that he cannot stay away from technology, after being away from technology (into management stuffs) for a short while in his career. Working mainly on Java and related open-source technologies/frameworks like Spring, Hibernate. Passionate about mushrooming open-source frameworks and inter-systems integration, which are the way to go these days...!

Updated on June 19, 2022

Comments

  • PaiS
    PaiS almost 2 years

    I have a one-to-one relationship using PrimaryKeyJoinColumn annotated on the parent side. And now I want to save the child entity by itself.

    For example, I have Employee and EmpInfo as the child entity, I need to save EmpInfo (of course after setting the id property of the parent to it). However, when such an arrangement is used, I get an exception listed below...

    org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist
    

    Any ideas why hibernate does not allow this? To be more clear, the code I have is below...

    ParentEntity:

    public class Employee {
        private Long id;
        private String name;
        private EmployeeInfo info;
        private Integer enumId;
    
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        public Long getId() {
            return id;
        }
    
        @Column(name="EMP_NAME")
        public String getName() {
            return name;
        }
    
        @PrimaryKeyJoinColumn
        @OneToOne(cascade = CascadeType.REMOVE)
        public EmployeeInfo getInfo() {
            return info;
        }
      }
    

    ChildEntity:

    @Table(name="EMP_INFO")
    @Entity
    public class EmployeeInfo {
        private Long id;
        private String email;
    
        @Column(name="EMPLOYEE_EMAIL")
        public String getEmail() {
            return email;
        }
    
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        @Column(name = "emp_id", nullable = false)
        public Long getId() {
            return id;
        }
    }
    

    The way I try to save it is...

    Employee emp = new Employee();
    emp.setEnumId(SimpleEnum.COMPLETE);
    emp.setName("Shreyas");
    EmployeeInfo info = new EmployeeInfo();
    info.setEmail("Sh@gmail");
    concreteDAO.save(emp);   // This uses the JPATemplate provided by Spring JpaDaoSupport
    
    
    info.setId(emp.getId());
    concreteDAO.saveEmpInfo(info);
    

    Any pointers would be much appreciated, as to how can I try to save the child entity?