From 53609d6594c8c6888b64572ac2c1c40c3b379bc6 Mon Sep 17 00:00:00 2001 From: mdabrowski-eu <57441874+mdabrowski-eu@users.noreply.github.com> Date: Fri, 9 Oct 2020 06:59:51 +0200 Subject: [PATCH] BAEL-4565 Object States in Hibernate's Session (#10107) --- .../java/com/baeldung/states/Application.java | 12 ++ .../java/com/baeldung/states/UserEntity.java | 27 ++++ .../states/UserEntityWithCascade.java | 28 ++++ .../states/UserEntityIntegrationTest.java | 136 ++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/Application.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntity.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntityWithCascade.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/Application.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/Application.java new file mode 100644 index 0000000000..38118354e0 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.states; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntity.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntity.java new file mode 100644 index 0000000000..90bd275240 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntity.java @@ -0,0 +1,27 @@ +package com.baeldung.states; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class UserEntity { + @Id + private String name; + + @ManyToOne + private UserEntity manager; + + public UserEntity(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntityWithCascade.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntityWithCascade.java new file mode 100644 index 0000000000..de0d62bfe2 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntityWithCascade.java @@ -0,0 +1,28 @@ +package com.baeldung.states; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class UserEntityWithCascade { + @Id + private String name; + + @ManyToOne(cascade = CascadeType.PERSIST) + private UserEntityWithCascade manager; + + public UserEntityWithCascade(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java new file mode 100644 index 0000000000..5d0dc99ad7 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java @@ -0,0 +1,136 @@ +package com.baeldung.states; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.persistence.EntityManagerFactory; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@RunWith(SpringRunner.class) +@SpringBootTest +class UserEntityIntegrationTest { + @Autowired + private EntityManagerFactory entityManagerFactory; + + @Test + void givenName_thenShouldCreateDetachedUserEntity() { + // given + Session session = openSession(); + UserEntity userEntity = new UserEntity("John"); + + // then + assertThat(session.contains(userEntity)).isFalse(); + session.close(); + } + + @Test + void givenName_whenPersisted_thenShouldCreatePersistentUserEntity() { + // given + Session session = openSession(); + UserEntity userEntity = new UserEntity("John"); + + // when + session.persist(userEntity); + + // then + assertThat(session.contains(userEntity)).isTrue(); + session.close(); + } + + @Test + void givenPersistentEntity_whenSessionClosed_thenShouldDetachEntity() { + // given + Session session = openSession(); + UserEntity userEntity = new UserEntity("John"); + session.persist(userEntity); + assertThat(session.contains(userEntity)).isTrue(); + + // when + session.close(); + + // then + assertThat(session.isOpen()).isFalse(); + assertThatThrownBy(() -> session.contains(userEntity)); + } + + @Test + void givenPersistentEntity_whenAddedTransientManager_thenShouldThrowException() { + // given + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + UserEntity userEntity = new UserEntity("John"); + session.persist(userEntity); + UserEntity manager = new UserEntity("Adam"); + + // when + userEntity.setManager(manager); + + + // then + assertThatThrownBy(() -> { + session.saveOrUpdate(userEntity); + transaction.commit(); + }); + session.close(); + } + + @Test + void givenPersistentEntity_whenAddedPersistentManager_thenShouldSave() { + // given + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + UserEntity userEntity = new UserEntity("John"); + session.persist(userEntity); + UserEntity manager = new UserEntity("Adam"); + session.persist(manager); + + // when + userEntity.setManager(manager); + + + // then + session.saveOrUpdate(userEntity); + transaction.commit(); + session.close(); + + Session otherSession = openSession(); + UserEntity savedUser = otherSession.get(UserEntity.class, "John"); + assertThat(savedUser.getManager().getName()).isEqualTo("Adam"); + } + + @Test + void givenPersistentEntityWithCascade_whenAddedTransientManager_thenShouldSave() { + // given + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + UserEntityWithCascade userEntity = new UserEntityWithCascade("John"); + session.persist(userEntity); + UserEntityWithCascade manager = new UserEntityWithCascade("Adam"); + + // when + userEntity.setManager(manager); + + + // then + session.saveOrUpdate(userEntity); + transaction.commit(); + session.close(); + + Session otherSession = openSession(); + UserEntityWithCascade savedUser = otherSession.get(UserEntityWithCascade.class, "John"); + assertThat(savedUser.getManager().getName()).isEqualTo("Adam"); + } + + + private Session openSession() { + return entityManagerFactory.unwrap(SessionFactory.class).openSession(); + } +} \ No newline at end of file