Hibernate One-to-Many Association on Join Table Annotations Example
- Details
- Written by Nam Ha Minh
- Last Updated on 12 December 2023   |   Print Email
- Hibernate 4.2.7.SP1
- JDK 7
- Eclipse IDE 4.3 (Kepler)
- Maven 3
- MySQL Community Server 5.5.23
- MySQL Connector Java driver 5.1.26
- Creating Database and Tables
- Creating Maven-Eclipse Project
- Using Annotations for One-to-Many Association on Join Table
- Writing Hibernate Configuration File
- Writing a Test Program
1. Creating Database and Tables
The following MySQL script is used to create a database called newsdb with three tables: category, article and category_article (join table):CREATE DATABASE `newsdb`; use newsdb; CREATE TABLE `category` ( `category_id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, PRIMARY KEY (`category_id`) ); CREATE TABLE `article` ( `article_id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(70) NOT NULL, `description` varchar(250) NOT NULL, `keywords` varchar(150) NOT NULL, `content` text NOT NULL, PRIMARY KEY (`article_id`) ); CREATE TABLE `category_article` ( `category_id` int(11) NOT NULL, `article_id` int(11) NOT NULL, PRIMARY KEY (`category_id`,`article_id`), UNIQUE KEY `article_id_UNIQUE` (`article_id`), KEY `fk_category` (`category_id`), KEY `fk_article` (`article_id`), CONSTRAINT `fk_article` FOREIGN KEY (`article_id`) REFERENCES `article` (`article_id`), CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`category_id`) );Notice that the column article_id of the join table is set with unique key constraint to enforce the one-to-many association, meaning that there is no one article belongs to more than one category.
2. Creating Maven-Eclipse Project
In Eclipse IDE, create a Maven project named HibernateOne2ManyJoinTableAnnotationsExample with the following structure:This project consists of the following files:- Model classes: Category.java and Article.java
- Hibernate XML configuration file: hibernate.cfg.xml
- Test program: ArticlesManager.java
- Maven project: pom.xml
<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>net.codejava.hibernate</groupId> <artifactId>HibernateOne2ManyJoinTableAnnotationsExample</artifactId> <version>1.0</version> <description>A sample Hibernate application that maps a one-to-many association on join table 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>All other dependencies will be resolved automatically by Maven.
3. Using Annotations for One-to-Many Association on Join Table
To represent the one-to-many association in the object model, let’s create two classes called Category.java and Article.java as follows:File net\codejava\hibernate\Category.java:package net.codejava.hibernate; import java.util.Set; 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.JoinTable; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "CATEGORY") public class Category { private long id; private String name; private Set<Article> articles; public Category() { } public Category(String name) { this.name = name; } @Id @GeneratedValue @Column(name = "CATEGORY_ID") public long getId() { return id; } @OneToMany(cascade = CascadeType.ALL) @JoinTable( name = "CATEGORY_ARTICLE", joinColumns = @JoinColumn(name = "CATEGORY_ID"), inverseJoinColumns = @JoinColumn(name = "ARTICLE_ID") ) // other getters and setters... }File net\codejava\hibernate\Article.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 = "ARTICLE") public class Article { private long id; private String title; private String description; private String keywords; private String content; public Article() { } public Article(String title, String description, String keywords, String content) { this.title = title; this.description = description; this.keywords = keywords; this.content = content; } @Id @GeneratedValue @Column(name = "ARTICLE_ID") public long getId() { return id; } // other getters and setters... }We can see that a Category has a set of Articles, but an Article doesn’t have any back reference to the Category, thus this association is unidirectional.To map the one-to-many association on join table, these JPA annotations are used: @OneToMany, @JoinTable and @JoinColumn, besides the basic annotations (@Entity, @Column, @Id, etc) . Let’s look at the code in the Category side closely:
private Set<Article> articles; @OneToMany(cascade = CascadeType.ALL) @JoinTable( name = "CATEGORY_ARTICLE", joinColumns = @JoinColumn(name = "CATEGORY_ID"), inverseJoinColumns = @JoinColumn(name = "ARTICLE_ID") ) public Set<Article> getArticles() { return articles; }
Here, we use the @JoinTable annotation to specify the details of the join table (table name and two join columns - using the @JoinColumn annotation); and we set the cascade attribute of the @OneToMany annotation so that Hibernate will update the associated articles when the category is updated.
And note that we don’t have to use any special annotations for the Article side, as this association is unidirectional; and there is no need to create a mapping class for the join table.
4. Writing Hibernate Configuration File
To tell Hibernate which database to connect and what the mapping classes are, create the hibernate.cfg.xml file under the classpath with the following content:<?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/newsdb</property> <property name="connection.username">root</property> <property name="connection.password">secret</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <mapping class="net.codejava.hibernate.Category"/> <mapping class="net.codejava.hibernate.Article"/> </session-factory> </hibernate-configuration>
5. Writing a Test Program
To test the association mapping we have made so far, let’s write a test program that saves some dummy data with the following code (ArticlesManager.java):package net.codejava.hibernate; import java.util.HashSet; import java.util.Set; 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 how to use JPA annotations to map * a one-to-many association on join table in Hibernate. * @author www.codejava.net * */ public class ArticlesManager { 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(); Category category = new Category("Hibernate Framework"); Article articleOne = new Article("One-to-One Mapping", "One-to-One XML Mapping Tutorial", "Hibernate,One-to-One", "Content of One-to-One XML Mapping Tutorial"); Article articleTwo = new Article("One-to-Many Mapping", "One-to-Many XML Mapping Tutorial", "Hibernate,One-to-Many", "Content of One-to-Many XML Mapping Tutorial"); Article articleThree = new Article("Many-to-Many Mapping", "Many-to-Many XML Mapping Tutorial", "Hibernate,Many-to-Many", "Content of Many-to-Many XML Mapping Tutorial"); Set<Article> articles = new HashSet<Article>(); articles.add(articleOne); articles.add(articleTwo); articles.add(articleThree); category.setArticles(articles); session.save(category); session.getTransaction().commit(); session.close(); } }Output of the program:
Hibernate: insert into CATEGORY (name) values (?) Hibernate: insert into ARTICLE (content, description, keywords, title) values (?, ?, ?, ?) Hibernate: insert into ARTICLE (content, description, keywords, title) values (?, ?, ?, ?) Hibernate: insert into ARTICLE (content, description, keywords, title) values (?, ?, ?, ?) Hibernate: insert into CATEGORY_ARTICLE (CATEGORY_ID, ARTICLE_ID) values (?, ?) Hibernate: insert into CATEGORY_ARTICLE (CATEGORY_ID, ARTICLE_ID) values (?, ?) Hibernate: insert into CATEGORY_ARTICLE (CATEGORY_ID, ARTICLE_ID) values (?, ?)Result in the category table:Result in the article table:Result in the join table category_article:For your reference, you can check the code on GitHub, or download the sample project attached below.
Related Hibernate One-to-Many Tutorials:
- Hibernate One-to-Many Association Annotations Example
- Hibernate One-to-Many Using Join Table XML Mapping Example
- Hibernate One-to-Many 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-One Association on Primary Key Annotations 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
Joining tables are only needed for many-to-many relationships.
Article simply needs a FK column for category_id that references a row in the category table.
If I want to get all articles with category name, how to get those details.
AWESOME . YOU WONT FIND THIS ANYWHERE EXPLANED IN SO DETAILS . appreciate it a lot.
You need to handle extra columns in the join table, right?
So here's the way:
codejava.net/.../...