Hibernate One-to-Many Using Join Table XML Mapping Example
- Details
- Written by Nam Ha Minh
- Last Updated on 12 December 2023   |   Print Email
In this Hibernate tutorial, we will learn how to use XML to map a one-to-many association on join table in relational database with Java objects. The following entity relationship diagram depicts the association:
One-to-Many association on a join table
Here, a category can contain from one to many occurrences of article. The CategoryArticle is the join table between them. Let’s see how to model this association in Hibernate framework.
The sample application in this tutorial was developed and tested in the following environment (of course you can use newer versions):
Table of content:
1. Creating Database Tables
Create a MySQL database called newsdb with three tables: category, article and CategoryArticle (join table), by executing the following script in MySQL Workbench’s SQL Editor:
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 `categoryarticle` ( `category_id` int(11) NOT NULL, `article_id` int(11) NOT NULL, PRIMARY KEY (`category_id`,`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`) );
If you are using MySQL Command Line Client, type the following command:
source Path\To\The\Script\File\MySQLscript.sql
Create the MySQLscript.sql file from the above script or find it in the attached project. The database newsdb will have the following structure:
2. Setting up an Eclipse Project
Create a Java project in Eclipse IDE called HibernateOne2ManyJoinTableXMLExample with the following structure:
We will create/add to this project the following files:
- Model classes: Category.java and Article.java
- Hibernate XML mapping files: Category.hbm.xmland Article.hbm.xml
- Hibernate XML configuration file: hibernate.cfg.xml
- Test program: ArticlesManager.java
- Hibernate required JAR libraries and MySQL Connector Java driver:
- hibernate-core-4.2.2.Final.jar
- hibernate-commons-annotations-4.0.2.Final.jar
- mysql-connector-java-5.1.25-bin.jar
- jboss-transaction-api_1.1_spec-1.0.1.Final.jar
- hibernate-jpa-2.0-api-1.0.1.Final.jar
- jboss-logging-3.1.0.GA.jar
- antlr-2.7.7.jar
- dom4j-1.6.1.jar
- javassist-3.15.0-GA.jar
- MySQL script file: MySQLscript.sql
Find the Hibernate and MySQL jar files from their distribution archives.
3. Coding Hibernate Model Classes
Create two Java files Category.java and Article.java corresponding to the tables category and article:
File net\codejava\hibernate\Category.java:
package net.codejava.hibernate; import java.util.Set; public class Category { private long id; private String name; private Set<Article> articles; public Category() { } public Category(String name) { this.name = name; } // getters and setters... }
File net\codejava\hibernate\Article.java:
package net.codejava.hibernate; public class Article { private long id; private String title; private String description; private String keywords; private String content; private Category category; public Article() { } public Article(String title, String description, String keywords, String content, Category category) { this.title = title; this.description = description; this.keywords = keywords; this.content = content; this.category = category; } // getters and setters... }
NOTES: The Category class has a set of articles and the Article class has a reference to its category. This is a typical configuration for a bidirectional one-to-many association. And note that we don’t have to write model class for the join table.
4. Writing Hibernate Mapping Files
Create two Hibernate mapping files Category.hbm.xml and Article.hbm.xml with the following content:
File net\codejava\hibernate\Category.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="net.codejava.hibernate"> <class name="Category" table="CATEGORY"> <id name="id" column="CATEGORY_ID"> <generator class="native"/> </id> <property name="name" column="NAME" /> <set name="articles" table="CategoryArticle" cascade="all"> <key column="CATEGORY_ID" not-null="true" /> <many-to-many column="ARTICLE_ID" class="Article" unique="true"/> </set> </class> </hibernate-mapping>
File net\codejava\hibernate\Article.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="net.codejava.hibernate"> <class name="Article" table="ARTICLE"> <id name="id" column="ARTICLE_ID"> <generator class="native"/> </id> <property name="title" column="TITLE" /> <property name="description" column="DESCRIPTION" /> <property name="keywords" column="KEYWORDS" /> <property name="content" column="CONTENT" /> <join table="CategoryArticle" inverse="true"> <key column="ARTICLE_ID"/> <many-to-one name="category" column="CATEGORY_ID" not-null="true"/> </join> </class> </hibernate-mapping>
NOTES:
- We specify the join table CategoryArticle for both sides, in the <set> element of the Category.hbm.xml file and in the <join> element of the Article.hbm.xml file.
- Category.hbm.xml: The attribute cascade=”all” tells Hibernate to update changes to the children (article) automatically when the parent (category) has changed.
- Article.hbm.xml: The attribute inverse=”true” tells Hibernate that the relationship owner is on the reverse side (the join table). Specifying this attribute is required for a one-to-many association.
5. Writing Hibernate Configuration File
Write code for the Hibernate configuration file (hibernate.cfg.xml) 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/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 resource="net/codejava/hibernate/Category.hbm.xml"/> <mapping resource="net/codejava/hibernate/Article.hbm.xml"/> </session-factory> </hibernate-configuration>
You may need to change the username and password according to your MySQL account.
6. Coding a Test Program
To wire all the above pieces together, create a test program that persists some sample data as follows:
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 Hibernate framework to manage * a one-to-many association on a join table. * @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", category); 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", category); 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", category); 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 (TITLE, DESCRIPTION, KEYWORDS, CONTENT) values (?, ?, ?, ?)
Hibernate: insert into ARTICLE (TITLE, DESCRIPTION, KEYWORDS, CONTENT) values (?, ?, ?, ?)
Hibernate: insert into ARTICLE (TITLE, DESCRIPTION, KEYWORDS, CONTENT) values (?, ?, ?, ?)
Hibernate: insert into CategoryArticle (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Hibernate: insert into CategoryArticle (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Hibernate: insert into CategoryArticle (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Result in the category table:
Result in the article table:
Result in the CategoryArticle table:
You can get the code examples 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 Association on Join Table Annotations 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
Nice article.
As per the problem statement, one category has many Articles, then why there is many to many mapping in category.hbm.xml.
Can you please, help me in understanding.
What was the error? Could you post more details?