diff --git a/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/Author.java b/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/Author.java new file mode 100644 index 000000000000..a39297c607cf --- /dev/null +++ b/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/Author.java @@ -0,0 +1,57 @@ +package com.baeldung.hibernate.hibernateexception; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; + +@Entity +public class Author { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @OneToMany(mappedBy = "author", cascade = CascadeType.ALL) + private List books; + + public Author(String name) { + this.name = name; + this.books = new ArrayList<>(); + } + + Author() { + } + + 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 List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } + +} diff --git a/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/Book.java b/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/Book.java new file mode 100644 index 000000000000..2e531556bc51 --- /dev/null +++ b/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/Book.java @@ -0,0 +1,52 @@ +package com.baeldung.hibernate.hibernateexception; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; + +@Entity +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String title; + + @ManyToOne + private Author author; + + public Book(String title) { + this.title = title; + } + + Book() { + } + + 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; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + +} diff --git a/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/HibernateUtil.java b/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/HibernateUtil.java new file mode 100644 index 000000000000..30a33debf964 --- /dev/null +++ b/persistence-modules/hibernate-exceptions-2/src/main/java/com/baeldung/hibernate/hibernateexception/HibernateUtil.java @@ -0,0 +1,39 @@ +package com.baeldung.hibernate.hibernateexception; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; + +public class HibernateUtil { + private static SessionFactory sessionFactory; + + public static SessionFactory getSessionFactory() { + if (sessionFactory == null) { + Map settings = new HashMap<>(); + settings.put("hibernate.connection.driver_class", "org.h2.Driver"); + settings.put("hibernate.connection.url", "jdbc:h2:mem:test"); + settings.put("hibernate.connection.username", "sa"); + settings.put("hibernate.connection.password", ""); + settings.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + settings.put("hibernate.show_sql", "true"); + settings.put("hibernate.hbm2ddl.auto", "create-drop"); + + ServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().applySettings(settings) + .build(); + + Metadata metadata = new MetadataSources(standardRegistry).addAnnotatedClasses(Author.class, Book.class) + .getMetadataBuilder() + .build(); + + sessionFactory = metadata.getSessionFactoryBuilder() + .build(); + } + + return sessionFactory; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-exceptions-2/src/test/java/com/baeldung/hibernate/hibernateexception/HibernateExceptionUnitTest.java b/persistence-modules/hibernate-exceptions-2/src/test/java/com/baeldung/hibernate/hibernateexception/HibernateExceptionUnitTest.java new file mode 100644 index 000000000000..b3397fa6025a --- /dev/null +++ b/persistence-modules/hibernate-exceptions-2/src/test/java/com/baeldung/hibernate/hibernateexception/HibernateExceptionUnitTest.java @@ -0,0 +1,85 @@ +package com.baeldung.hibernate.hibernateexception; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.junit.jupiter.api.Test; + +class HibernateExceptionUnitTest { + + @Test + void givenAnEntity_whenChangesUseTheSameHibernateSession_thenThoseChangesCanBeUpdated() { + try (Session session1 = HibernateUtil.getSessionFactory() + .openSession()) { + session1.beginTransaction(); + + Author author = new Author("Jane Austen"); + session1.persist(author); + + Book newBook = new Book("Pride and Prejudice"); + author.getBooks() + .add(newBook); + + session1.update(author); + + session1.getTransaction() + .commit(); + } + } + + @Test + void givenAnEntity_whenChangesSpanMultipleHibernateSessions_thenThoseChangesCanBeMerged() { + try (Session session1 = HibernateUtil.getSessionFactory() + .openSession(); + Session session2 = HibernateUtil.getSessionFactory() + .openSession()) { + session1.beginTransaction(); + + Author author = new Author("Leo Tolstoy"); + session1.persist(author); + session1.getTransaction() + .commit(); + + session2.beginTransaction(); + + Book newBook = new Book("War and Peace"); + author.getBooks() + .add(newBook); + session2.merge(author); + + session2.getTransaction() + .commit(); + } + } + + @Test + void givenAnEntity_whenChangesSpanMultipleHibernateSessions_thenThoseChangesCanNotBeUpdated() { + assertThatThrownBy(() -> { + try (Session session1 = HibernateUtil.getSessionFactory() + .openSession(); + Session session2 = HibernateUtil.getSessionFactory() + .openSession()) { + session1.beginTransaction(); + + Author author = new Author("Leo Tolstoy"); + session1.persist(author); + + session1.getTransaction() + .commit(); + + session2.beginTransaction(); + + Book newBook = new Book("War and Peace"); + author.getBooks() + .add(newBook); + session2.update(author); + + session2.getTransaction() + .commit(); + } + }).isInstanceOf(HibernateException.class) + .hasMessageContaining("Illegal attempt to associate a collection with two open sessions"); + } + +}