diff --git a/persistence-modules/hibernate-jpa/pom.xml b/persistence-modules/hibernate-jpa/pom.xml
index 67f40d5017..07b1ee1c51 100644
--- a/persistence-modules/hibernate-jpa/pom.xml
+++ b/persistence-modules/hibernate-jpa/pom.xml
@@ -81,11 +81,17 @@
jmh-generator-annprocess
${openjdk-jmh.version}
+
+ org.postgresql
+ postgresql
+ ${postgresql.version}
+
5.3.7.Final
- 6.0.6
+ 8.0.13
+ 42.2.11
2.2.3
3.8.0
1.21
diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitymanager/getreference/Game.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitymanager/getreference/Game.java
new file mode 100644
index 0000000000..1de8de0327
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitymanager/getreference/Game.java
@@ -0,0 +1,38 @@
+package com.baeldung.hibernate.entitymanager.getreference;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class Game {
+
+ @Id
+ private Long id;
+
+ private String name;
+
+ public Game() {
+ }
+
+ public Game(Long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ 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;
+ }
+
+}
diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitymanager/getreference/Player.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitymanager/getreference/Player.java
new file mode 100644
index 0000000000..459a3a00ad
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/entitymanager/getreference/Player.java
@@ -0,0 +1,50 @@
+package com.baeldung.hibernate.entitymanager.getreference;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class Player {
+
+ @Id
+ private Long id;
+
+ private String name;
+
+ @ManyToOne
+ private Game game;
+
+ public Player() {
+ }
+
+ public Player(Long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ 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 Game getGame() {
+ return game;
+ }
+
+ public void setGame(Game game) {
+ this.game = game;
+ }
+
+}
diff --git a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/create-db.sql b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/create-db.sql
new file mode 100644
index 0000000000..7074b603f6
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/create-db.sql
@@ -0,0 +1,3 @@
+create table Game (id bigint not null, name varchar(255), primary key (id));
+create table Player (id bigint not null, name varchar(255), game_id bigint, primary key (id));
+alter table Player add constraint FKohr86afuapoujklti79wo27aa foreign key (game_id) references Game(id);
\ No newline at end of file
diff --git a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/data.sql b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/data.sql
new file mode 100644
index 0000000000..1e83082801
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/data.sql
@@ -0,0 +1,5 @@
+insert into Game (id, name) values (1, 'Game 1');
+insert into Game (id, name) values (2, 'Game 2');
+insert into Player (game_id, name, id) values (null, 'Player 1', 1);
+insert into Player (game_id, name, id) values (null, 'Player 2', 2);
+insert into Player (game_id, name, id) values (null, 'Player 3', 3);
\ No newline at end of file
diff --git a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/drop-db.sql b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/drop-db.sql
new file mode 100644
index 0000000000..275324fcae
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/drop-db.sql
@@ -0,0 +1,2 @@
+drop table if exists Player;
+drop table if exists Game;
\ No newline at end of file
diff --git a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml
index 4dfade1af3..c2d5bf59ab 100644
--- a/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml
+++ b/persistence-modules/hibernate-jpa/src/main/resources/META-INF/persistence.xml
@@ -5,7 +5,7 @@
version="2.0">
Hibernate EntityManager Demo
- com.baeldung.hibernate.pojo.Movie
+ com.baeldung.hibernate.pojo.Movie
true
@@ -16,4 +16,88 @@
+
+
+ EntityManager getReference persistence unit
+ com.baeldung.hibernate.entitymanager.getreference.Game
+ com.baeldung.hibernate.entitymanager.getreference.Player
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EntityManager getReference persistence unit
+ com.baeldung.hibernate.entitymanager.getreference.Game
+ com.baeldung.hibernate.entitymanager.getreference.Player
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EntityManager getReference persistence unit
+ com.baeldung.hibernate.entitymanager.getreference.Game
+ com.baeldung.hibernate.entitymanager.getreference.Player
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferenceH2IntegrationTest.java b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferenceH2IntegrationTest.java
new file mode 100644
index 0000000000..e8e6aeed7c
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferenceH2IntegrationTest.java
@@ -0,0 +1,194 @@
+package com.baeldung.hibernate.entitymanager.getreference;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import org.junit.jupiter.api.*;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class GetReferenceH2IntegrationTest {
+
+ private static EntityManagerFactory entityManagerFactory;
+ private static EntityManager entityManager;
+
+ private static final PrintStream SystemOut = System.out;
+ private static OutputStream output;
+
+ @BeforeAll
+ public static void setup() {
+ // close some specific loggers so that we can clearly see Hibernate: SQL queries
+ ((Logger) LoggerFactory.getLogger("org.hibernate.SQL")).setLevel(Level.OFF);
+ ((Logger) LoggerFactory.getLogger("org.hibernate.type.descriptor.sql")).setLevel(Level.OFF);
+ ((Logger) LoggerFactory.getLogger("org.hibernate.stat")).setLevel(Level.OFF);
+
+ entityManagerFactory = Persistence.createEntityManagerFactory("com.baeldung.hibernate.entitymanager.game_player_h2");
+ entityManager = entityManagerFactory.createEntityManager();
+ entityManager.getTransaction().begin();
+
+ entityManager.persist(new Game(1L, "Game 1"));
+ entityManager.persist(new Game(2L, "Game 2"));
+ entityManager.persist(new Player(1L, "Player 1"));
+ entityManager.persist(new Player(2L, "Player 2"));
+ entityManager.persist(new Player(3L, "Player 3"));
+
+ entityManager.getTransaction().commit();
+ entityManager.clear();
+ entityManager.close();
+ }
+
+ private void runInTransaction(Runnable task) {
+ // We create new persistence context for each test method to discard Hibernate first level cache.
+ // So that we can see the behavior of getReference() method in a non-cached environment.
+ entityManager = entityManagerFactory.createEntityManager();
+ entityManager.getTransaction().begin();
+ task.run();
+ entityManager.getTransaction().commit();
+ // In any case, we use clear() and close() to make all the managed entities detached and cleared.
+ // So, we can be sure we test always on a clear persistence context.
+ entityManager.clear();
+ entityManager.close();
+ }
+
+ @BeforeEach
+ public void beforeEach() {
+ // stubbing System.out printStream
+ output = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(output));
+ }
+
+ @AfterEach
+ public void afterEach() {
+ System.setOut(SystemOut);
+ // we print to see original output after each test method
+ System.out.print(output.toString());
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ entityManagerFactory.close();
+ }
+
+ @Test
+ public void whenUsingFindMethodToUpdateGame_thenExecutesSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game1 = entityManager.find(Game.class, 1L);
+ game1.setName("Game Updated 1");
+
+ entityManager.persist(game1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: update Game set name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToUpdateGame_thenExecutesSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game1 = entityManager.getReference(Game.class, 1L);
+ game1.setName("Game Updated 2");
+
+ entityManager.persist(game1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: update Game set name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingFindMethodToDeletePlayer_thenExecutesSelectForPlayer() {
+
+ runInTransaction(() -> {
+ Player player2 = entityManager.find(Player.class, 2L);
+ entityManager.remove(player2);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: delete from Player where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToDeletePlayer_thenExecutesSelectForPlayer() {
+
+ runInTransaction(() -> {
+ Player player3 = entityManager.getReference(Player.class, 3L);
+ entityManager.remove(player3);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: delete from Player where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingFindMethodToUpdatePlayersGame_thenExecutesSelectForGame() {
+
+ runInTransaction((() -> {
+ Game game1 = entityManager.find(Game.class, 1L);
+
+ Player player1 = entityManager.find(Player.class, 1L);
+ player1.setGame(game1);
+
+ entityManager.persist(player1);
+ }));
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: update Player set game_id=?, name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToUpdatePlayersGame_thenDoesNotExecuteSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game2 = entityManager.getReference(Game.class, 2L);
+
+ Player player1 = entityManager.find(Player.class, 1L);
+ player1.setGame(game2);
+
+ entityManager.persist(player1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: update Player set game_id=?, name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+}
diff --git a/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferenceMySQLManualTest.java b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferenceMySQLManualTest.java
new file mode 100644
index 0000000000..2b7c5e8119
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferenceMySQLManualTest.java
@@ -0,0 +1,185 @@
+package com.baeldung.hibernate.entitymanager.getreference;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import org.junit.jupiter.api.*;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * We need to have a running MySQL instance and a schema named "baeldung" ready in order to execute this integration test
+ */
+public class GetReferenceMySQLManualTest {
+
+ private static EntityManagerFactory entityManagerFactory;
+ private static EntityManager entityManager;
+
+ private static final PrintStream SystemOut = System.out;
+ private static OutputStream output;
+
+ @BeforeAll
+ public static void setup() {
+ // close some specific loggers so that we can clearly see Hibernate: SQL queries
+ ((Logger) LoggerFactory.getLogger("org.hibernate.SQL")).setLevel(Level.OFF);
+ ((Logger) LoggerFactory.getLogger("org.hibernate.type.descriptor.sql")).setLevel(Level.OFF);
+ ((Logger) LoggerFactory.getLogger("org.hibernate.stat")).setLevel(Level.OFF);
+
+ entityManagerFactory = Persistence.createEntityManagerFactory("com.baeldung.hibernate.entitymanager.game_player_mysql");
+ }
+
+ private void runInTransaction(Runnable task) {
+ // We create new persistence context for each test method to discard Hibernate first level cache.
+ // So that we can see the behavior of getReference() method in a non-cached environment.
+ entityManager = entityManagerFactory.createEntityManager();
+ entityManager.getTransaction().begin();
+ task.run();
+ entityManager.getTransaction().commit();
+ // In any case, we use clear() and close() to make all the managed entities detached and cleared.
+ // So, we can be sure we test always on a clear persistence context.
+ entityManager.clear();
+ entityManager.close();
+ }
+
+ @BeforeEach
+ public void beforeEach() {
+ // stubbing System.out printStream
+ output = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(output));
+ }
+
+ @AfterEach
+ public void afterEach() {
+ System.setOut(SystemOut);
+ // we print to see original output after each test method
+ System.out.print(output.toString());
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ entityManagerFactory.close();
+ }
+
+ @Test
+ public void whenUsingFindMethodToUpdateGame_thenExecutesSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game1 = entityManager.find(Game.class, 1L);
+ game1.setName("Game Updated 1");
+
+ entityManager.persist(game1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: update Game set name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToUpdateGame_thenExecutesSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game1 = entityManager.getReference(Game.class, 1L);
+ game1.setName("Game Updated 2");
+
+ entityManager.persist(game1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: update Game set name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingFindMethodToDeletePlayer_thenExecutesSelectForPlayer() {
+
+ runInTransaction(() -> {
+ Player player2 = entityManager.find(Player.class, 2L);
+ entityManager.remove(player2);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: delete from Player where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToDeletePlayer_thenExecutesSelectForPlayer() {
+
+ runInTransaction(() -> {
+ Player player3 = entityManager.getReference(Player.class, 3L);
+ entityManager.remove(player3);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: delete from Player where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingFindMethodToUpdatePlayersGame_thenExecutesSelectForGame() {
+
+ runInTransaction((() -> {
+ Game game1 = entityManager.find(Game.class, 1L);
+
+ Player player1 = entityManager.find(Player.class, 1L);
+ player1.setGame(game1);
+
+ entityManager.persist(player1);
+ }));
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: update Player set game_id=?, name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToUpdatePlayersGame_thenDoesNotExecuteSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game2 = entityManager.getReference(Game.class, 2L);
+
+ Player player1 = entityManager.find(Player.class, 1L);
+ player1.setGame(game2);
+
+ entityManager.persist(player1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: update Player set game_id=?, name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+}
diff --git a/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferencePostgreSQLManualTest.java b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferencePostgreSQLManualTest.java
new file mode 100644
index 0000000000..17f6b10b8a
--- /dev/null
+++ b/persistence-modules/hibernate-jpa/src/test/java/com/baeldung/hibernate/entitymanager/getreference/GetReferencePostgreSQLManualTest.java
@@ -0,0 +1,185 @@
+package com.baeldung.hibernate.entitymanager.getreference;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import org.junit.jupiter.api.*;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * We need to have a running PostgreSQL instance in order to execute this integration test
+ */
+public class GetReferencePostgreSQLManualTest {
+
+ private static EntityManagerFactory entityManagerFactory;
+ private static EntityManager entityManager;
+
+ private static final PrintStream SystemOut = System.out;
+ private static OutputStream output;
+
+ @BeforeAll
+ public static void setup() {
+ // close some specific loggers so that we can clearly see Hibernate: SQL queries
+ ((Logger) LoggerFactory.getLogger("org.hibernate.SQL")).setLevel(Level.OFF);
+ ((Logger) LoggerFactory.getLogger("org.hibernate.type.descriptor.sql")).setLevel(Level.OFF);
+ ((Logger) LoggerFactory.getLogger("org.hibernate.stat")).setLevel(Level.OFF);
+
+ entityManagerFactory = Persistence.createEntityManagerFactory("com.baeldung.hibernate.entitymanager.game_player_postgresql");
+ }
+
+ private void runInTransaction(Runnable task) {
+ // We create new persistence context for each test method to discard Hibernate first level cache.
+ // So that we can see the behavior of getReference() method in a non-cached environment.
+ entityManager = entityManagerFactory.createEntityManager();
+ entityManager.getTransaction().begin();
+ task.run();
+ entityManager.getTransaction().commit();
+ // In any case, we use clear() and close() to make all the managed entities detached and cleared.
+ // So, we can be sure we test always on a clear persistence context.
+ entityManager.clear();
+ entityManager.close();
+ }
+
+ @BeforeEach
+ public void beforeEach() {
+ // stubbing System.out printStream
+ output = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(output));
+ }
+
+ @AfterEach
+ public void afterEach() {
+ System.setOut(SystemOut);
+ // we print to see original output after each test method
+ System.out.print(output.toString());
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ entityManagerFactory.close();
+ }
+
+ @Test
+ public void whenUsingFindMethodToUpdateGame_thenExecutesSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game1 = entityManager.find(Game.class, 1L);
+ game1.setName("Game Updated 1");
+
+ entityManager.persist(game1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: update Game set name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToUpdateGame_thenExecutesSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game1 = entityManager.getReference(Game.class, 1L);
+ game1.setName("Game Updated 2");
+
+ entityManager.persist(game1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: update Game set name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingFindMethodToDeletePlayer_thenExecutesSelectForPlayer() {
+
+ runInTransaction(() -> {
+ Player player2 = entityManager.find(Player.class, 2L);
+ entityManager.remove(player2);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: delete from Player where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToDeletePlayer_thenExecutesSelectForPlayer() {
+
+ runInTransaction(() -> {
+ Player player3 = entityManager.getReference(Player.class, 3L);
+ entityManager.remove(player3);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: delete from Player where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingFindMethodToUpdatePlayersGame_thenExecutesSelectForGame() {
+
+ runInTransaction((() -> {
+ Game game1 = entityManager.find(Game.class, 1L);
+
+ Player player1 = entityManager.find(Player.class, 1L);
+ player1.setGame(game1);
+
+ entityManager.persist(player1);
+ }));
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select game0_.id as id1_0_0_, game0_.name as name2_0_0_ from Game game0_ where game0_.id=?\n");
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: update Player set game_id=?, name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+ @Test
+ public void whenUsingGetReferenceMethodToUpdatePlayersGame_thenDoesNotExecuteSelectForGame() {
+
+ runInTransaction(() -> {
+ Game game2 = entityManager.getReference(Game.class, 2L);
+
+ Player player1 = entityManager.find(Player.class, 1L);
+ player1.setGame(game2);
+
+ entityManager.persist(player1);
+ });
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("Hibernate: select ");
+ expected.append("player0_.id as id1_1_0_, player0_.game_id as game_id3_1_0_, ");
+ expected.append("player0_.name as name2_1_0_, game1_.id as id1_0_1_, game1_.name as name2_0_1_ ");
+ expected.append("from Player player0_ left outer join Game game1_ on player0_.game_id=game1_.id where player0_.id=?\n");
+ expected.append("Hibernate: update Player set game_id=?, name=? where id=?\n");
+
+ assertEquals(expected.toString(), output.toString());
+ }
+
+}