I have two classes: Person and PersonDetail
Person:
package com.sam.entity; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; @Entity @Table(name = "person") @ToString @NoArgsConstructor @RequiredArgsConstructor public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @Getter @Setter private int id; @Column(name = "first_name") @Getter @Setter @NonNull private String firstName; @Column(name = "last_name") @Getter @Setter @NonNull private String lastName; @Column(name = "email") @Getter @Setter @NonNull private String email; // Defining the relationship between instructor and instructor detail @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "person_detail_id") @Getter @Setter @ToString.Exclude private PersonDetail personDetail; }
PersonDetail
package com.sam.entity; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Table; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; @Entity @Table(name = "person_detail") @ToString @NoArgsConstructor @RequiredArgsConstructor public class PersonDetail { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @Getter @Setter private int id; @Column(name = "youtube_channel") @Getter @Setter @NonNull private String youtubeChannel; @Column(name = "hobby") @Getter @Setter @NonNull private String hobby; // adding a reference to the person for bi-directional mapping @OneToOne(mappedBy = "personDetail", cascade = CascadeType.ALL) // this references the personDetail in the person class @Getter @Setter private Person person; }
I have set up a bi-directional one-to-one mapping between these classes. I am trying to save a person and that person’s details and then I am trying to fetch the person using the person’s details. The code for that is:
package com.sam.tests; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import com.sam.demo.HibernateUtil; import com.sam.entity.Person; import com.sam.entity.PersonDetail; public class HibernateOneToOneBidirectional { private static SessionFactory sessionFactory; private Session session; @BeforeAll public static void setup() { sessionFactory = HibernateUtil.getSessionFactory("hibernate.onetoone.bidirectional.xml"); } @AfterAll public static void teardown() { sessionFactory.close(); } @BeforeEach public void openSession() { session = sessionFactory.getCurrentSession(); } @AfterEach public void closeSession() { session.close(); } @Test @DisplayName("Get person from person detail(Testing out bi-directional mapping)") public void testBiDirectional() { session.beginTransaction(); Person person = new Person("John", "Smith", "johnsmith@movie.com"); PersonDetail personDetails = new PersonDetail("youtube.com/johnsmith", "Acting"); person.setPersonDetail(personDetails); session.save(person); // fetch the stored personDetail System.out.println("Person detail id is: " + personDetails.getId()); PersonDetail savedDetail = session.get(PersonDetail.class, personDetails.getId()); System.out.println("Fetched person details are: " + savedDetail); // using the fetched personDetail, fetch the person Person associatedPerson = savedDetail.getPerson(); session.getTransaction().commit(); Assertions.assertTrue(associatedPerson != null); } }
My test is failing because the person detail object has a null value for the associated person. Can someone help me?
Advertisement
Answer
I tried fetching the person details in another session and that worked. I could see the details of the person. The edited code is:
package com.sam.tests; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import com.sam.demo.HibernateUtil; import com.sam.entity.Person; import com.sam.entity.PersonDetail; public class HibernateOneToOneBidirectional { private static SessionFactory sessionFactory; private Session session; @BeforeAll public static void setup() { sessionFactory = HibernateUtil.getSessionFactory("hibernate.onetoone.bidirectional.xml"); } @AfterAll public static void teardown() { sessionFactory.close(); } @BeforeEach public void openSession() { session = sessionFactory.getCurrentSession(); } @AfterEach public void closeSession() { session.close(); } @Test @DisplayName("Get person from person detail(Testing out bi-directional mapping)") public void testBiDirectional() { session.beginTransaction(); Person person = new Person("John", "Smith", "johnsmith@movie.com"); PersonDetail personDetails = new PersonDetail("youtube.com/johnsmith", "Acting"); person.setPersonDetail(personDetails); session.save(person); int id = personDetails.getId(); session.close(); Session anotherSession = sessionFactory.getCurrentSession(); anotherSession.beginTransaction(); // fetch the stored personDetail PersonDetail savedDetail = anotherSession.get(PersonDetail.class, id); System.out.println("Fetched person details are: " + savedDetail); // using the fetched personDetail, fetch the person Person associatedPerson = savedDetail.getPerson(); anotherSession.getTransaction().commit(); anotherSession.close(); Assertions.assertTrue(associatedPerson != null); } }
Is this correct? Or can this be done in the same transaction?