BAEL-5439: PersistentObjectException: detached entity passed to persist thrown by JPA and Hibernate (#12303)

* BAEL-5439: added code samples for article

* BAEL-5439: added static import for assertj
This commit is contained in:
etrandafir93 2022-06-26 18:33:25 +02:00 committed by GitHub
parent e798355a92
commit ff3cc7b948
4 changed files with 252 additions and 0 deletions

View File

@ -0,0 +1,46 @@
package com.baeldung.hibernate.exception.detachedentity;
import java.util.Properties;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;
import com.baeldung.hibernate.exception.detachedentity.entity.Comment;
import com.baeldung.hibernate.exception.detachedentity.entity.Post;
public class HibernateUtil {
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
Configuration configuration = new Configuration();
Properties settings = new Properties();
settings.put(Environment.DRIVER, "org.hsqldb.jdbcDriver");
settings.put(Environment.URL, "jdbc:hsqldb:mem:transient");
settings.put(Environment.USER, "sa");
settings.put(Environment.PASS, "");
settings.put(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect");
settings.put(Environment.SHOW_SQL, "true");
settings.put(Environment.FORMAT_SQL, "true");
settings.put(Environment.USE_SQL_COMMENTS, "true");
settings.put(Environment.HBM2DDL_AUTO, "update");
configuration.setProperties(settings);
configuration.addAnnotatedClass(Comment.class);
configuration.addAnnotatedClass(Post.class);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties())
.build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
e.printStackTrace();
}
}
return sessionFactory;
}
}

View File

@ -0,0 +1,56 @@
package com.baeldung.hibernate.exception.detachedentity.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String text;
public Comment(String text) {
this.text = text;
}
public Comment() {
}
@ManyToOne
private Post post;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Post getPost() {
return post;
}
public void setPost(Post post) {
this.post = post;
}
@Override
public String toString() {
return "Comment{" + "id=" + id + ", name='" + text + '\'' + ", post=" + post + '}';
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.hibernate.exception.detachedentity.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
public Post() {
}
public Post(String title) {
this.title = title;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "Post{" + "id=" + id + ", text='" + title + '\'' + '}';
}
}

View File

@ -0,0 +1,106 @@
package com.baeldung.hibernate.exception.detachedentity;
import com.baeldung.hibernate.exception.detachedentity.entity.Comment;
import com.baeldung.hibernate.exception.detachedentity.entity.Post;
import org.assertj.core.api.Assertions;
import org.hibernate.Session;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.PersistenceException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class DetachedEntityUnitTest {
private static Session session;
private Post detachedPost;
@Before
public void beforeEach() {
session = HibernateUtil.getSessionFactory()
.openSession();
session.beginTransaction();
this.detachedPost = new Post("Hibernate Tutorial");
session.persist(detachedPost);
session.evict(detachedPost);
}
@After
public void afterEach() {
clearDatabase();
session.close();
}
@Test
public void givenDetachedPost_whenTryingToPersist_thenThrowException() {
detachedPost.setTitle("Hibernate Tutorial for Absolute Beginners");
assertThatThrownBy(() -> session.persist(detachedPost))
.isInstanceOf(PersistenceException.class)
.hasMessageContaining("org.hibernate.PersistentObjectException: detached entity passed to persist");
}
@Test
public void givenDetachedPost_whenTryingToMerge_thenNoExceptionIsThrown() {
detachedPost.setTitle("Hibernate Tutorial for Beginners");
session.merge(detachedPost);
session.getTransaction()
.commit();
List<Post> posts = session.createQuery("Select p from Post p", Post.class)
.list();
assertThat(posts).hasSize(1);
assertThat(posts.get(0)
.getTitle()).isEqualTo("Hibernate Tutorial for Beginners");
}
@Test
public void givenDetachedPost_whenPersistingNewCommentWithIt_thenThrowException() {
Comment comment = new Comment("nice article!");
comment.setPost(detachedPost);
session.persist(comment);
session.getTransaction()
.commit();
assertThatThrownBy(() -> session.persist(detachedPost))
.isInstanceOf(PersistenceException.class)
.hasMessageContaining("org.hibernate.PersistentObjectException: detached entity passed to persist");
}
@Test
public void givenDetachedPost_whenMergeAndPersistComment_thenNoExceptionIsThrown() {
Comment comment = new Comment("nice article!");
Post mergedPost = (Post) session.merge(detachedPost);
comment.setPost(mergedPost);
session.persist(comment);
session.getTransaction()
.commit();
List<Comment> comments = session.createQuery("Select c from Comment c", Comment.class)
.list();
Comment savedComment = comments.get(0);
assertThat(savedComment.getText()).isEqualTo("nice article!");
assertThat(savedComment.getPost()
.getTitle()).isEqualTo("Hibernate Tutorial");
}
private void clearDatabase() {
if (!session.getTransaction()
.isActive()) {
session.beginTransaction();
}
session.createQuery("DELETE FROM Comment")
.executeUpdate();
session.createQuery("DELETE FROM Post")
.executeUpdate();
}
}