I am currently learning about Hibernate and I was going through @GenericGenerator
and the strategy
parameter that can be passed in the above mentioned annotation.
There is a strategy in Hibernate called:- assigned
. According to Hibernate if we use this strategy, then the application has to assign the primary key.
Now please find below the entity class and my main class:-
Entity Class:-
package org.example.bean;
import lombok.Data;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
@Entity
@Data
public class Subject {
@Id
@GeneratedValue( generator = "subject_sequence")
@GenericGenerator(name = "subject_sequence",
strategy = "assigned")
Long subjectId;
String subjectName;
}
Main class:-
package org.example.service;
import org.example.bean.Subject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Scanner;
public class SubjectService {
public static void main(String[] args) {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("Subject");
EntityManager entityManager = entityManagerFactory.createEntityManager();
Scanner sc = new Scanner(System.in);
System.out.print("Enter the number of subjects:-");
int noofSubjects = sc.nextInt();
sc.nextLine();
String subjectName="";
for(int i=1; i<=noofSubjects; i++){
System.out.print("Enter the subject name:-");
subjectName = sc.nextLine();
Subject subject = new Subject();
subject.setSubjectName(subjectName);
subject.setSubjectId(Long.valueOf(i));
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
entityManager.persist(subject);
System.out.println("Subject persisted with id:-"+subject.getSubjectId());
entityTransaction.commit();
}
}
}
If I try to execute the above code and pass the no of subjects and the subject name, I am getting the below error:-
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: org.example.bean.Subject
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:166)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:193)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:200)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:709)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:689)
at org.example.service.SubjectService.main(SubjectService.java:35)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: org.example.bean.Subject
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:120)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:55)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:101)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:703)
... 2 more
Can you please help me to understand why this error is coming as Hibernate has to save the object. Why is Hibernate assuming that an entity like this is already present?
When you use the assigned strategy, you're telling Hibernate that YOU will manage the ID values, not Hibernate. However, when you set an ID value manually and then try to use persist(), Hibernate assumes that since the entity has an ID value, it must be a detached entity (an entity that was previously persisted but is no longer attached to the session).
to fix this :
merge()
instead of persist()
:entityManager.merge(subject);
or remove the @GeneratedValue
annotation since you're using the assigned strategy:
@Id
@GenericGenerator(name = "subject_sequence",
strategy = "assigned")
Long subjectId;