Many-to-many relationships occur when each record in an entity may have
many linked records in another entity and vice-versa.
このチュートリアルでは、HibernateでXMLマッピングファイル(hbm)を使用して多対多のテーブル関係を操作する方法を説明します。
このチュートリアルで使用されるツールとテクノロジ:
-
Hibernate 3.6.3.Final
-
MySQL 5.1.15
-
Maven 3.0.3
-
Eclipse 3.6
プロジェクト構造
このチュートリアルのプロジェクト構造。
プロジェクトの依存関係
JBossリポジトリから最新の
hibernate.jar
を入手してください。
File:pom.xml
<project ...>
<repositories>
<repository>
<id>JBoss repository</id>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<!-- MySQL database driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.15</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.3.Final</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
</dependencies>
</project>
1.「多対多」の例
これは多対多リレーションシップテーブル設計であり、STOCKテーブルには複数のCATEGORYがあり、CATEGORYは複数のSTOCKに属することができます。この関係はSTOCK__CATEGORYという3番目のテーブルにリンクされています。
表STOCK__CATEGORYは、2つの主キーと、STOCKおよびCATEGORYへの外部キー参照で構成されています。
MySQLテーブルスクリプト
CREATE TABLE `stock` ( `STOCK__ID` int(10) unsigned NOT NULL AUTO__INCREMENT, `STOCK__CODE` varchar(10) NOT NULL, `STOCK__NAME` varchar(20) NOT NULL, PRIMARY KEY (`STOCK__ID`) USING BTREE, UNIQUE KEY `UNI__STOCK__NAME` (`STOCK__NAME`), UNIQUE KEY `UNI__STOCK__ID` (`STOCK__CODE`) USING BTREE ) CREATE TABLE `category` ( `CATEGORY__ID` int(10) unsigned NOT NULL AUTO__INCREMENT, `NAME` varchar(10) NOT NULL, `DESC` varchar(255) NOT NULL, PRIMARY KEY (`CATEGORY__ID`) USING BTREE ) CREATE TABLE `stock__category` ( `STOCK__ID` int(10) unsigned NOT NULL, `CATEGORY__ID` int(10) unsigned NOT NULL, PRIMARY KEY (`STOCK__ID`,`CATEGORY__ID`), CONSTRAINT `FK__CATEGORY__ID` FOREIGN KEY (`CATEGORY__ID`) REFERENCES `category` (`CATEGORY__ID`), CONSTRAINT `FK__STOCK__ID` FOREIGN KEY (`STOCK__ID`) REFERENCES `stock` (`STOCK__ID`) )
2. Hibernateモデルクラス
上記の表を表す
Stock.java`と
Category.java`の2つのモデルクラスを作成します。テーブル ‘
stock__category
‘に余分なクラスを作成する必要はありません。
File:Stock.java
package com.mkyong.stock;
import java.util.HashSet;
import java.util.Set;
public class Stock implements java.io.Serializable {
private Integer stockId;
private String stockCode;
private String stockName;
private Set<Category> categories = new HashSet<Category>(0);
//getter, setter and constructor
}
File:Category.java
package com.mkyong.stock;
import java.util.HashSet;
import java.util.Set;
public class Category implements java.io.Serializable {
private Integer categoryId;
private String name;
private String desc;
private Set<Stock> stocks = new HashSet<Stock>(0);
//getter, setter and constructor
}
3. Hibernate XMLマッピング
今度は、2つのHibernateマッピングファイル(hbm) –
Stock.hbm.xml`と
Category.hbm.xml`を作成してください。 3番目の ‘
stock__category
‘テーブルが ”
many-to-many
“タグを介した参照であることに気づくでしょう。
File:Stock.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.mkyong.stock.Stock" table="stock" catalog="mkyongdb">
<id name="stockId" type="java.lang.Integer">
<column name="STOCK__ID"/>
<generator class="identity"/>
</id>
<property name="stockCode" type="string">
<column name="STOCK__CODE" length="10" not-null="true" unique="true"/>
</property>
<property name="stockName" type="string">
<column name="STOCK__NAME" length="20" not-null="true" unique="true"/>
</property>
<set name="categories" table="stock__category"
inverse="false" lazy="true" fetch="select" cascade="all" >
<key>
<column name="STOCK__ID" not-null="true"/>
</key>
<many-to-many entity-name="com.mkyong.stock.Category">
<column name="CATEGORY__ID" not-null="true"/>
</many-to-many>
</set>
</class>
</hibernate-mapping>
File:Category.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.mkyong.stock.Category" table="category" catalog="mkyongdb">
<id name="categoryId" type="java.lang.Integer">
<column name="CATEGORY__ID"/>
<generator class="identity"/>
</id>
<property name="name" type="string">
<column name="NAME" length="10" not-null="true"/>
</property>
<property name="desc" type="string">
<column name="[DESC]" not-null="true"/>
</property>
<set name="stocks" table="stock__category" inverse="true" lazy="true" fetch="select">
<key>
<column name="CATEGORY__ID" not-null="true"/>
</key>
<many-to-many entity-name="com.mkyong.stock.Stock">
<column name="STOCK__ID" not-null="true"/>
</many-to-many>
</set>
</class>
</hibernate-mapping>
4.ハイバネート設定ファイル
次に、
Stock.hbm.xml`と
Category.hbm.xml`とMySQLの詳細を `hibernate.cfg.xml`に入れます。
File:hibernate.cfg.xml
<?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>
<property name="hibernate.connection.driver__class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mkyongdb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show__sql">true</property>
<property name="format__sql">true</property>
<mapping resource="com/mkyong/stock/Stock.hbm.xml"/>
<mapping resource="com/mkyong/stock/Category.hbm.xml"/>
</session-factory>
</hibernate-configuration>
5.それを実行する
これを実行すると、HibernateはSTOCKテーブルにレコードを挿入し、2つのレコードをCATEGORYテーブルに追加し、2つのレコードをSTOCKに追加します)CATEGORYテーブル。
File:App.java
package com.mkyong;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import com.mkyong.stock.Category;
import com.mkyong.stock.Stock;
import com.mkyong.util.HibernateUtil;
public class App {
public static void main(String[]args) {
System.out.println("Hibernate many to many (XML Mapping)");
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Stock stock = new Stock();
stock.setStockCode("7052");
stock.setStockName("PADINI");
Category category1 = new Category("CONSUMER", "CONSUMER COMPANY");
Category category2 = new Category("INVESTMENT", "INVESTMENT COMPANY");
Set<Category> categories = new HashSet<Category>();
categories.add(category1);
categories.add(category2);
stock.setCategories(categories);
session.save(stock);
session.getTransaction().commit();
System.out.println("Done");
}
}
Output …結果は自明でなければならない
Hibernate many to many (XML Mapping)
Hibernate:
insert
into
mkyongdb.stock
(STOCK__CODE, STOCK__NAME)
values
(?, ?)
Hibernate:
insert
into
mkyongdb.category
(NAME, `DESC`)
values
(?, ?)
Hibernate:
insert
into
mkyongdb.category
(NAME, `DESC`)
values
(?, ?)
Hibernate:
insert
into
stock__category
(STOCK__ID, CATEGORY__ID)
values
(?, ?)
Hibernate:
insert
into
stock__category
(STOCK__ID, CATEGORY__ID)
values
(?, ?)
Done
-
Hibernateアノテーション** Hibernateアノテーションの多対多の場合は、//hibernate/hibernate-many-to-many-relationship-example-annotation/[example]のリンクを参照してください。
ダウンロードする –
Hibernate-many-to-many-xml-mapping.zip
(10KB)
リファレンス
ドキュメント – 多対多の関係。]