JPA One-To-One Association Tutorial

Issue: BAEL-2394
This commit is contained in:
raghav-jha 2018-11-30 11:40:11 +05:30 committed by Josh Cummings
parent ea6aa58fdf
commit f4c5f8b8ae
13 changed files with 669 additions and 0 deletions

View File

@ -0,0 +1,38 @@
package com.baeldung.hibernate.onetoone;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static SessionFactory buildSessionFactory(Strategy strategy) {
try {
// Create the SessionFactory from hibernate-annotation.cfg.xml
Configuration configuration = new Configuration();
for (Class<?> entityClass : strategy.getEntityClasses()) {
configuration.addAnnotatedClass(entityClass);
}
configuration.configure("one-to-one.cfg.xml");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties())
.build();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
} catch (Throwable ex) {
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory(Strategy strategy) {
if (sessionFactory == null)
sessionFactory = buildSessionFactory(strategy);
return sessionFactory;
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.hibernate.onetoone;
import java.util.Arrays;
import java.util.List;
public enum Strategy {
//See that the classes belongs to different packages
FOREIGN_KEY(Arrays.asList(com.baeldung.hibernate.onetoone.foreignkeybased.User.class,
com.baeldung.hibernate.onetoone.foreignkeybased.Address.class)),
SHARED_PRIMARY_KEY(Arrays.asList(com.baeldung.hibernate.onetoone.sharedkeybased.User.class,
com.baeldung.hibernate.onetoone.sharedkeybased.Address.class)),
JOIN_TABLE_BASED(Arrays.asList(com.baeldung.hibernate.onetoone.jointablebased.Employee.class,
com.baeldung.hibernate.onetoone.jointablebased.WorkStation.class));
private List<Class<?>> entityClasses;
Strategy(List<Class<?>> entityClasses) {
this.entityClasses = entityClasses;
}
public List<Class<?>> getEntityClasses() {
return entityClasses;
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.hibernate.onetoone.foreignkeybased;
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;
@Entity
@Table(name = "address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "street")
private String street;
@Column(name = "city")
private String city;
@OneToOne(mappedBy = "address")
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

View File

@ -0,0 +1,51 @@
package com.baeldung.hibernate.onetoone.foreignkeybased;
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;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "username")
private String userName;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}

View File

@ -0,0 +1,53 @@
package com.baeldung.hibernate.onetoone.jointablebased;
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.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "ename")
private String name;
@OneToOne(cascade = CascadeType.ALL)
@JoinTable(name = "emp_workstation", joinColumns = {@JoinColumn(name = "employee_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "workstation_id", referencedColumnName = "id")})
private WorkStation workStation;
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 WorkStation getWorkStation() {
return workStation;
}
public void setWorkStation(WorkStation workStation) {
this.workStation = workStation;
}
}

View File

@ -0,0 +1,61 @@
package com.baeldung.hibernate.onetoone.jointablebased;
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;
@Entity
@Table(name = "workstation")
public class WorkStation {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "workstation_number")
private Integer workstationNumber;
@Column(name = "floor")
private String floor;
@OneToOne(mappedBy = "workStation")
private Employee employee;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getWorkstationNumber() {
return workstationNumber;
}
public void setWorkstationNumber(Integer workstationNumber) {
this.workstationNumber = workstationNumber;
}
public String getFloor() {
return floor;
}
public void setFloor(String floor) {
this.floor = floor;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.hibernate.onetoone.sharedkeybased;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name = "address")
public class Address {
@Id
@Column(name = "id")
private Long id;
@Column(name = "street")
private String street;
@Column(name = "city")
private String city;
@OneToOne
@MapsId
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.hibernate.onetoone.sharedkeybased;
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;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "username")
private String userName;
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private Address address;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.connection.url">jdbc:h2:mem:spring_hibernate_one_to_one</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>
</session-factory>
</hibernate-configuration>

View File

@ -0,0 +1,80 @@
package com.baeldung.hibernate.onetoone;
import com.baeldung.hibernate.onetoone.foreignkeybased.Address;
import com.baeldung.hibernate.onetoone.foreignkeybased.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class HibernateOneToOneAnnotationFKBasedIntegrationTest {
private static SessionFactory sessionFactory;
private Session session;
@BeforeClass
public static void beforeTests() {
sessionFactory = HibernateUtil.getSessionFactory(Strategy.FOREIGN_KEY);
}
@Before
public void setUp() {
session = sessionFactory.openSession();
session.beginTransaction();
}
@Test
public void givenData_whenInsert_thenCreates1to1relationship() {
User user = new User();
user.setUserName("alice@baeldung.com");
Address address = new Address();
address.setStreet("FK Street");
address.setCity("FK City");
address.setUser(user);
user.setAddress(address);
//Address entry will automatically be created by hibernate, since cascade type is specified as ALL
session.persist(user);
session.getTransaction().commit();
assert1to1InsertedData();
}
private void assert1to1InsertedData() {
@SuppressWarnings("unchecked")
List<User> userList = session.createQuery("FROM User").list();
assertNotNull(userList);
assertEquals(1, userList.size());
User user = userList.get(0);
assertEquals("alice@baeldung.com", user.getUserName());
Address address = user.getAddress();
assertNotNull(address);
assertEquals("FK Street", address.getStreet());
assertEquals("FK City", address.getCity());
}
@After
public void tearDown() {
session.close();
}
@AfterClass
public static void afterTests() {
sessionFactory.close();
}
}

View File

@ -0,0 +1,80 @@
package com.baeldung.hibernate.onetoone;
import com.baeldung.hibernate.onetoone.jointablebased.Employee;
import com.baeldung.hibernate.onetoone.jointablebased.WorkStation;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class HibernateOneToOneAnnotationJTBasedIntegrationTest {
private static SessionFactory sessionFactory;
private Session session;
@BeforeClass
public static void beforeTests() {
sessionFactory = HibernateUtil.getSessionFactory(Strategy.JOIN_TABLE_BASED);
}
@Before
public void setUp() {
session = sessionFactory.openSession();
session.beginTransaction();
}
@Test
public void givenData_whenInsert_thenCreates1to1relationship() {
Employee employee = new Employee();
employee.setName("bob@baeldung.com");
WorkStation workStation = new WorkStation();
workStation.setWorkstationNumber(626);
workStation.setFloor("Sixth Floor");
employee.setWorkStation(workStation);
workStation.setEmployee(employee);
session.persist(employee);
session.getTransaction().commit();
assert1to1InsertedData();
}
private void assert1to1InsertedData() {
@SuppressWarnings("unchecked")
List<Employee> employeeList = session.createQuery("FROM Employee").list();
assertNotNull(employeeList);
assertEquals(1, employeeList.size());
Employee employee = employeeList.get(0);
assertEquals("bob@baeldung.com", employee.getName());
WorkStation workStation = employee.getWorkStation();
assertNotNull(workStation);
assertEquals((long) 626, (long) workStation.getWorkstationNumber());
assertEquals("Sixth Floor", workStation.getFloor());
}
@After
public void tearDown() {
session.close();
}
@AfterClass
public static void afterTests() {
sessionFactory.close();
}
}

View File

@ -0,0 +1,79 @@
package com.baeldung.hibernate.onetoone;
import com.baeldung.hibernate.onetoone.sharedkeybased.Address;
import com.baeldung.hibernate.onetoone.sharedkeybased.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class HibernateOneToOneAnnotationSPKBasedIntegrationTest {
private static SessionFactory sessionFactory;
private Session session;
@BeforeClass
public static void beforeTests() {
sessionFactory = HibernateUtil.getSessionFactory(Strategy.SHARED_PRIMARY_KEY);
}
@Before
public void setUp() {
session = sessionFactory.openSession();
session.beginTransaction();
}
@Test
public void givenData_whenInsert_thenCreates1to1relationship() {
User user = new User();
user.setUserName("alice@baeldung.com");
Address address = new Address();
address.setStreet("SPK Street");
address.setCity("SPK City");
address.setUser(user);
user.setAddress(address);
//Address entry will automatically be created by hibernate, since cascade type is specified as ALL
session.persist(user);
session.getTransaction().commit();
assert1to1InsertedData();
}
private void assert1to1InsertedData() {
@SuppressWarnings("unchecked")
List<User> userList = session.createQuery("FROM User").list();
assertNotNull(userList);
assertEquals(1, userList.size());
User user = userList.get(0);
assertEquals("alice@baeldung.com", user.getUserName());
Address address = user.getAddress();
assertNotNull(address);
assertEquals("SPK Street", address.getStreet());
assertEquals("SPK City", address.getCity());
}
@After
public void tearDown() {
session.close();
}
@AfterClass
public static void afterTests() {
sessionFactory.close();
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.connection.url">jdbc:h2:mem:spring_hibernate_one_to_one</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>
</session-factory>
</hibernate-configuration>