I have two classes: Person and PersonDetail
Person:
JavaScript
x
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
JavaScript
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:
JavaScript
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:
JavaScript
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?