Hibernate One to One Unidirectional Shared Primary Key
In this tutorial, we show you how to configure a Hibernate One-to-One Unidirectional Association with shared primary key using either annotations or xml mapping files.
- A one-to-one mapping means that one object can have only one relation – at most.
- With shared primary key, the primary key of both tables are equal. The foreign key constraint is the primary key of the reference table.
- A unidirectional relationship means that only one side (the owning side) is able to navigate to the relationship. In the following example only the dog can retrieve the collar reference and not vice versa.
Maven Dependencies
We use Apache Maven to manage the projects dependencies. Add the following dependencies to your projects pom.xml file.
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.4</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.3.Final</version> </dependency>
Create Model Classes + Annotation Mappings
Following classes are simple POJOs, annotated with standard Java Persistence Api (JPA) annotations. These annotations are the mapping between the Java Class and the corresponding Database Tables. The first POJO is the Dog class.
package com.memorynotfound.hibernate; import javax.persistence.*; @Entity @Table(name = "TBL_DOG") public class Dog { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "DOG_ID") private Integer id; @Column(name = "NAME") private String name; @PrimaryKeyJoinColumn @OneToOne(cascade = CascadeType.ALL, optional = false) private Collar collar; public Dog() { } public Dog(String name, Collar collar) { this.name = name; this.collar = collar; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Collar getCollar() { return collar; } public void setCollar(Collar collar) { this.collar = collar; } @Override public String toString() { return "Dog{" + "id=" + id + ", name='" + name + '\'' + ", collar=" + collar + '}'; } }
Note that the @OneToOne annotation has a optional attribute. When this is set to false, hibernate will automatically create the foreign key constraint on the reference table by primary key.
The second POJO is the Collar class.
package com.memorynotfound.hibernate; import javax.persistence.*; @Entity @Table(name = "TBL_COLLAR") public class Collar { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "COLLAR_ID") private Integer id; @Column(name = "COLOR") private String color; public Collar() { } public Collar(String color) { this.color = color; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } @Override public String toString() { return "Collar{" + "id=" + id + ", color='" + color + '\'' + '}'; } }
Hibernate HBM XML Mapping
If you prefer Hibernate XML HBM Mapping files over Annotations, you can use the equivalent hibernate xml mapping for the Dog class. This file is located in the src/main/resources folder and is named Dog.hbm.xml.
Note: the one-to-one element has a constrained attribute – when used – hibernate will create a foreign key constraint on the primary key of the reference table.
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.memorynotfound.hibernate.Dog" table="TBL_DOG"> <id name="id" type="java.lang.Integer" column="DOG_ID"> <generator class="identity" /> </id> <property name="name" column="NAME"/> <one-to-one name="collar" cascade="all" constrained="true"/> </class> </hibernate-mapping>
And the equivalent hibernate xml mapping for the Collar class. This file is located in the src/main/resources folder and is named Collar.hbm.xml.
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.memorynotfound.hibernate.Collar" table="TBL_COLLAR"> <id name="id" type="java.lang.Integer" column="COLLAR_ID"> <generator class="identity" /> </id> <property name="color" column="COLOR"/> </class> </hibernate-mapping>
Configure Hibernate Connection Properties
We can configure the database properties using the hibernate hibernate.cfg.xml file, located on the classpath in the src/main/resources folder.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- database connection properties --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/dogstore?serverTimezone=Europe/Brussels</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"></property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- show mysql queries output in console --> <property name="hibernate.show_sql">true</property> <!-- manage automatic database creation --> <property name="hibernate.hbm2ddl.auto">create-drop</property> <!-- add annotated resources here --> <mapping class="com.memorynotfound.hibernate.Collar"/> <mapping class="com.memorynotfound.hibernate.Dog"/> </session-factory> </hibernate-configuration>
HibernateUtil
This class is used to configure hibernate during startup and create a standalone SessionFactory.
package com.memorynotfound.hibernate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public static Session getSession() throws HibernateException { return sessionFactory.openSession(); } public static void shutdown() { sessionFactory.close(); } }
Create app
Finally, we can test the application. We create a new Dog object and associate a Collar object. Afterwards, we save the object and commit the transaction.
package com.memorynotfound.hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import java.util.Arrays; import java.util.List; public class App { public static void main (String...args){ Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Collar favoriteCollar = new Collar("spiked-collar"); Dog pluto = new Dog("pluto", favoriteCollar); session.save(pluto); tx.commit(); Listdogs = (List )session.createQuery("from Dog").list(); System.out.println("Dogs: " + Arrays.toString(dogs.toArray())); session.close(); HibernateUtil.shutdown(); } }
The previous application prints the following info to the console.
... Hibernate: insert into TBL_COLLAR (COLOR) values (?) Hibernate: insert into TBL_DOG (NAME) values (?, ?) Hibernate: select dog0_.DOG_ID as DOG_ID1_1_, dog0_.NAME as NAME2_1_ from TBL_DOG dog0_ Dogs: [Dog{id=1, name='pluto', collar=Collar{id=1, color='spiked-collar'}}] ...
Records inserted in the database
Download
From:一号门
COMMENTS