Siva Kumar
Siva Kumar

Reputation: 31

org.hibernate.PersistentObjectException: detached entity passed to persist: Many to one unidirectional

Am trying Many to one unidirectional mapping with hibernate in spring boot. I have the following student class -many

package jpa.many.to.one.unidirectional.model;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
 
@Entity
@Table(name = "STUDENT")
public class Student {
 
    @Id
    @GeneratedValue
    @Column(name = "STUDENT_ID")
    private long id;
 
    @Column(name = "FIRST_NAME")
    private String firstName;
 
    @Column(name = "LAST_NAME")
    private String lastName;
 
    @Column(name = "SECTION")
    private String section;
 
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="UNIVERSITY_ID")
    private University university;
 
 
    public Student() {
    }
 
    public Student(String firstName, String lastName, String section, University university) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.section = section;
        this.university = university;
    }
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getFirstName() {
        return firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
    public String getLastName() {
        return lastName;
    }
 
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
 
    public String getSection() {
        return section;
    }
 
    public void setSection(String section) {
        this.section = section;
    }
 
    public University getUniversity() {
        return university;
    }
 
    public void setUniversity(University university) {
        this.university = university;
    }
 
    @Override
    public String toString() {
        return "Student [id=" + id + ", firstName=" + firstName + ", lastName="
                + lastName + ", section=" + section + "]";
    }
 
}

University - one class

package jpa.many.to.one.unidirectional.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name = "UNIVERSITY")
public class University {
 
    @Id
    @GeneratedValue
    @Column(name = "UNIVERSITY_ID")
    private long id;
 
    @Column(name = "NAME")
    private String name;
 
    @Column(name = "COUNTRY")
    private String country;
 
    public University() {
 
    }
 
    public University(String name, String country) {
        this.name = name;
        this.country = country;
    }
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getCountry() {
        return country;
    }
 
    public void setCountry(String country) {
        this.country = country;
    }
 
    @Override
    public String toString() {
        return "University [id=" + id + ", name=" + name + ", country=" + country + "]";
    }
 
}

The application save and run as

package jpa.many.to.one.unidirectional;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import jpa.many.to.one.unidirectional.model.Student;
import jpa.many.to.one.unidirectional.model.University;
import jpa.many.to.one.unidirectional.repo.StudentRepo;
import jpa.many.to.one.unidirectional.repo.UniversityRepo;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
//      SpringApplication.run(Application.class, args);

        ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(Application.class, args);
        UniversityRepo universityRepo = configurableApplicationContext.getBean(UniversityRepo.class);
        StudentRepo studentRepo = configurableApplicationContext.getBean(StudentRepo.class);

        University university = new University("MG", "India");
        
        Student fstudent = new Student("Deeksha", "Sivakumar", "A", university);
        fstudent.setUniversity(university);
        studentRepo.save(fstudent);
        
        
        Student fstudent1 = new Student("Sivakumar", "Nair", "A", university);
        fstudent1.setUniversity(university);
        studentRepo.save(fstudent1);

    }

}

But I get Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: jpa.many.to.one.unidirectional.model.University at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:120) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:744) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:712) at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298) at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:492) at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:416) at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:151) at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:427) 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:135) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:55) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:720) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:706) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314) at com.sun.proxy.$Proxy55.persist(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:554) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at org.springframework.data.repository.core.support.ImplementationInvocationMetadata.invoke(ImplementationInvocationMetadata.java:72) at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:382) at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:205) at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:550) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:155) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ... 13 more

i tried cascade.merge and optional-=false in many to one annoation. but i get the above mentioned error please help

Upvotes: 3

Views: 1855

Answers (1)

Azzabi Haythem
Azzabi Haythem

Reputation: 2413

@ManyToOne(cascade = CascadeType.ALL) it seems in your case to be a bad idea, as removing an Student would lead to removing the related University. As a University can have multiple Student, the other Student would become orphans

I think you should use this relation in the University Entity , instead of Student Entity

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="STUDENT_ID")
private List<Student> students;

and if you want to use your model try to save the university before setting it in a student (because in your code you are trying to save the same univesity two times,first with fstudent and second with fstudent1 ) and in this case i advice you to not use the cascade:

  University university = universityRepo.save(new University("MG", "India"));
    
    Student fstudent = new Student("Deeksha", "Sivakumar", "A", university);
    fstudent.setUniversity(university);
    studentRepo.save(fstudent);
    
    
    Student fstudent1 = new Student("Sivakumar", "Nair", "A", university);
    fstudent1.setUniversity(university);
    studentRepo.save(fstudent1);

Upvotes: 4

Related Questions