A many-to-many association
We are going to develop a sample Hibernate application that manages the above association in which a user may belong to many groups, and a group may contain many users. The UsersGroups is the join table between the groups and users tables.The following pieces of software/library are used in this tutorial:create database usersdb; use usersdb; CREATE TABLE `users` ( `user_id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(45) NOT NULL, `password` varchar(45) NOT NULL, `email` varchar(45) NOT NULL, PRIMARY KEY (`user_id`) ); CREATE TABLE `groups` ( `group_id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, PRIMARY KEY (`group_id`) ); CREATE TABLE `UsersGroups` ( `user_id` int(11) NOT NULL, `group_id` int(11) NOT NULL, PRIMARY KEY (`user_id`,`group_id`), KEY `fk_user` (`user_id`), KEY `fk_group` (`group_id`), CONSTRAINT `fk_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`), CONSTRAINT `fk_group` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`) );Or type the following command in case you are using MySQL Command Line Client program:
source Path\To\The\Script\File\MySQLscript.sql
In which the MySQLscript.sql file can be created from the above script or picked up from the attached project. The newly created database would have the following structure:package net.codejava.hibernate; import java.util.HashSet; import java.util.Set; public class Group { private long id; private String name; private Set<User> users = new HashSet<User>(); public Group(String name) { this.name = name; } public void addUser(User user) { this.users.add(user); } // setters and getters }File net\codejava\hibernate\User.java:
package net.codejava.hibernate; import java.util.HashSet; import java.util.Set; public class User { private long id; private String username; private String password; private String email; private Set<Group> groups = new HashSet<Group>(); public User(String username, String password, String email) { this.username = username; this.password = password; this.email = email; } public void addGroup(Group group) { this.groups.add(group); } // setters and getters }NOTES: For a bidirectional many-to-many association, we should specify a collection of another side from each side (using java.util.Set implementation in this tutorial). For example:
<?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="Group" table="GROUPS"> <id name="id" column="GROUP_ID"> <generator class="native"/> </id> <property name="name" column="NAME" /> <set name="users" table="UsersGroups" cascade="save-update"> <key column="GROUP_ID"/> <many-to-many column="USER_ID" class="User" /> </set> </class> </hibernate-mapping>File net\codejava\hibernate\User.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="User" table="USERS"> <id name="id" column="USER_ID"> <generator class="native"/> </id> <property name="username" column="USERNAME" /> <property name="password" column="PASSWORD" /> <property name="email" column="EMAIL" /> <set name="groups" table="UsersGroups" inverse="true"> <key column="USER_ID"/> <many-to-many column="GROUP_ID" class="Group" /> </set> </class> </hibernate-mapping>NOTES:
<?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/usersdb</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/User.hbm.xml"/> <mapping resource="net/codejava/hibernate/Group.hbm.xml"/> </session-factory> </hibernate-configuration>NOTES: Change the username and password according to your MySQL account.
package net.codejava.hibernate; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; /** * A program that demonstrates using Hibernate framework to manage * a bidirectional many-to-many association in relational database. * @author www.codejava.net * */ public class UsersManager { 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(); Group groupAdmin = new Group("Administrator Group"); Group groupGuest = new Group("Guest Group"); User user1 = new User("Tom", "tomcat", "tom@codejava.net"); User user2 = new User("Mary", "mary", "mary@codejava.net"); groupAdmin.addUser(user1); groupAdmin.addUser(user2); groupGuest.addUser(user1); user1.addGroup(groupAdmin); user2.addGroup(groupAdmin); user1.addGroup(groupGuest); session.save(groupAdmin); session.save(groupGuest); session.getTransaction().commit(); session.close(); } }Output of the program:
Hibernate: insert into GROUPS (NAME) values (?)
Hibernate: insert into USERS (USERNAME, PASSWORD, EMAIL) values (?, ?, ?)
Hibernate: insert into USERS (USERNAME, PASSWORD, EMAIL) values (?, ?, ?)
Hibernate: insert into GROUPS (NAME) values (?)
Hibernate: insert into UsersGroups (GROUP_ID, USER_ID) values (?, ?)
Hibernate: insert into UsersGroups (GROUP_ID, USER_ID) values (?, ?)
Hibernate: insert into UsersGroups (GROUP_ID, USER_ID) values (?, ?)
Result in the groups table:Result in the users table:Result in the UsersGroups table: