Hibernate One-to-One Mapping with Foreign Key Annotations Example
- Details
- Written by Nam Ha Minh
- Last Updated on 12 December 2023   |   Print Email
This Hibernate tutorial demonstrates how to use JPA annotations in order to implement a unidirectional one-to-one association on a foreign key. This is similar to the tutorial Hibernate One-to-One With Foreign Key XML Mapping Example but using annotations instead of XML descriptor. The following diagram recalls the one-to-one entity relationship:
A book belongs to only one author, and we can only know the author from the book, not vice-versa. Thus the association is called unidirectional (one-way).
We are going to develop a sample Hibernate application using the following technologies/software programs:
- Hibernate 4.2.6.Final
- JDK 7
- Eclipse IDE 4.3 (Kepler)
- Maven 3
- MySQL Community Server 5.5.23
- MySQL Connector Java driver 5.1.26
Note that we use the latest stuffs to date, you can use little bit lower or higher versions. Now, let’s following the steps below:
Table of content:
- Creating Database and Tables
- Creating Eclipse Project
- Coding Model Classes with Annotations
- Writing Hibernate Configuration File
- Writing a Test Program
1. Creating Database and Tables
Execute the following MySQL script to create the database booksdb with two tables author and book:
create database booksdb; use booksdb; CREATE TABLE `author` ( `author_id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, `email` varchar(45) NOT NULL, PRIMARY KEY (`author_id`) ); CREATE TABLE `book` ( `book_id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(128) NOT NULL, `description` varchar(512) NOT NULL, `published` date NOT NULL, `author_id` int(11) NOT NULL, PRIMARY KEY (`book_id`), KEY `author_fk` (`author_id`), CONSTRAINT `author_fk` FOREIGN KEY (`author_id`) REFERENCES `author` (`author_id`) );
The database structure looks like this:
2. Creating Eclipse Project
Create a Maven project in Eclipse with the following structure:
The project consists of the following files:
- Model classes: Author.java and Book.java
- Hibernate XML configuration file: hibernate.cfg.xml
- Test program: BooksManager.java
- Maven project: pom.xml
Here’s content of the pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>HibernateOne2OneAnnnotationsExample</groupId> <artifactId>HibernateOne2OneAnnnotationsExample</artifactId> <version>0.0.1-SNAPSHOT</version> <description>Example of a Hibernate one-to-one mapping with foreign key using annotations</description> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.2.7.SP1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.26</version> </dependency> </dependencies> </project>
Here, we specify two main dependencies: hibernate-core and mysql-connector-java. Maven will resolve other related dependencies automatically.
3. Coding Model Classes with Annotations
The followings are code of the two model classes: Author.java and Book.java.
File net\codejava\hibernate\Author.java:
package net.codejava.hibernate; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "AUTHOR") public class Author { private long id; private String name; private String email; public Author() { } public Author(String name, String email) { this.name = name; this.email = email; } @Id @Column(name = "AUTHOR_ID") @GeneratedValue 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 String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
File net\codejava\hibernate\Book.java:
package net.codejava.hibernate; import java.util.Date; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; @Entity @Table(name = "BOOK") public class Book { private long id; private String title; private String description; private Date publishedDate; private Author author; public Book() { } @Id @Column(name = "BOOK_ID") @GeneratedValue public long getId() { return id; } public void setId(long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Temporal(TemporalType.DATE) @Column(name = "PUBLISHED") public Date getPublishedDate() { return publishedDate; } public void setPublishedDate(Date publishedDate) { this.publishedDate = publishedDate; } @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "AUTHOR_ID") public Author getAuthor() { return author; } public void setAuthor(Author author) { this.author = author; } }
As you notice, we use the following JPA annotations:
- @Entity: is required for every model class.
- @Table: maps the class with the corresponding database table. If omitted, Hibernate will use the class name.
- @Column: maps the field with the corresponding table column. If omitted, Hibernate will infer the column name and type based on signatures of the getter/setter.
- @Id and @GeneratedValue: are used in conjunction for a field that maps to the primary key. The values for this field are auto generated.
- @Temporal: must be used with a java.util.Date field to specify the actual SQL type of the column.
- @OneToOne and @JoinColumn: are used together to specify a one-to-one association and the join column.
Using annotations is usually preferred over XML descriptor because it’s simple and straightforward in the code.
4. Writing Hibernate Configuration File
Write XML configuration for database settings and mapping classes in the hibernate.cfg.xml file as follows:
<?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 settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/booksdb</property> <property name="connection.username">root</property> <property name="connection.password">P@ssw0rd</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <mapping class="net.codejava.hibernate.Book"/> <mapping class="net.codejava.hibernate.Author"/> </session-factory> </hibernate-configuration>
5. Writing a Test Program
Write code for the test program (BooksManager.java) as follows:
package net.codejava.hibernate; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; /** * This program demonstrates using Hibernate framework to manage * a one-to-one mapping with foreign key using annotations. * @author www.codejava.net * */ public class BooksManager { public static void main(String[] args) { // loads configuration and mappings Configuration configuration = new Configuration().configure(); ServiceRegistryBuilder registry = new ServiceRegistryBuilder(); registry.applySettings(configuration.getProperties()); ServiceRegistry serviceRegistry = registry.buildServiceRegistry(); // builds a session factory from the service registry SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); // obtains the session Session session = sessionFactory.openSession(); session.beginTransaction(); // creates a Book entity Book newBook = new Book(); newBook.setTitle("Hibernate Made Easy"); newBook.setDescription("Simplified Data Persistence with Hibernate and JPA"); newBook.setPublishedDate(new Date()); newBook.setAuthor(new Author("Cameron Wallace McKenzie", "Cameron@gmail.com")); // persists the book entity Long bookId = (Long) session.save(newBook); // gets the book entity back Book book = (Book) session.get(Book.class, bookId); System.out.println("Book's Title: " + book.getTitle()); System.out.println("Book's Description: " + book.getTitle()); Author author = book.getAuthor(); System.out.println("Author's Name: " + author.getName()); System.out.println("Author's Email: " + author.getEmail()); session.getTransaction().commit(); session.close(); } }
Output of the program:
Hibernate: insert into AUTHOR (email, name) values (?, ?) Hibernate: insert into BOOK (AUTHOR_ID, description, PUBLISHED, title) values (?, ?, ?, ?) Book's Title: Hibernate Made Easy Book's Description: Hibernate Made Easy Author's Name: Cameron Wallace McKenzie
Result in the Book table:
Result in the Author table:
You can download the sample project attached below, or check the code on GitHub here.
Related Hibernate One-to-One Tutorials:
- Hibernate One-to-One Association on Primary Key Annotations Example
- Hibernate One-to-One With Foreign Key XML Mapping Example
- Hibernate One-to-One With Primary Key XML Mapping Example
Other Hibernate Tutorials:
- Java Hibernate JPA Annotations Tutorial for Beginners
- Hibernate Hello World Tutorial for Beginners with Eclipse and MySQL
- Hibernate One-to-Many Using Join Table XML Mapping Example
- Hibernate Many-to-Many Association with Extra Columns in Join Table Example
- Hibernate Enum Type Mapping Example
- Hibernate Binary Data and BLOB Mapping Example
- Hibernate Query Language (HQL) Example
- Java Hibernate Reverse Engineering Tutorial with Eclipse and MySQL
- Hibernate Basics - 3 ways to delete an entity from the datastore
Comments
Caused by: org.dom4j.DocumentException: Error on line 1 of document : Content is not allowed in prolog. Nested exception: Content is not allowed in prolog.
this is the example