[[HOME>http://www.trance.co.jp/]] > [[技術情報]] > [[Java>http://www.trance.co.jp/wiki/index.php?%B5%BB%BD%D1%BE%F0%CA%F3#xe479566]] > Java Persistence API
* Java Persistence API 1.0(JPA) [#p067abdd]
#contents
* Java Persistence API(JPA) [#p067abdd]
** Java Persistence APIとは [#ye590c98]
- Javaオブジェクトの永続化のためのAPI
以前はEJBの仕様に含まれていたものが、EJB3.0より切り離され、EJBコンテナ以外での使用が可能となった.
また、O/Rマッピング、アノテーションを使用することにより、以前のEJBのような複雑な仕組みではなく、よりPOJOとして開発できるようになった.

// ** 特徴
// - アノテーションによるマッピング → XML設定ファイル減
// - 4つのエンティティ状態
// -- new 
// -- managed
// -- detached
// -- removed
// - 
** 特徴 [#s2f8465e]
- ''アノテーションによるマッピング''
-- XML設定ファイル減
-- コード量減
- ''4つのエンティティ状態(ライフサイクル)''
|~状態|~説明|~Persistent Indentity|~Persistence Context|
|&color(blue){''new''};|Entityが生成された状態|持たない|結びつきなし|
|&color(blue){''managed''};|EntityがEntityManagerに管理されている状態|持つ|結びつきあり|
|&color(blue){''removed''};|Entityが削除予約となっている状態|持つ|結びつきあり|
|&color(blue){''detached''};|Entityがデータベースと関連がなくなった状態|持つ|結びつきなし|
 

** 実装プロダクト [#h478525f]
Java Persistence APIは仕様であるため、実装プロダクトがいくつか存在する.
- Hibernate
- TopLink
- OpenJPA

** 使用方法 - 準備 (実装プロダクト:Hibernate) [#hc112776]
今回は、実装プロダクトとして、「Hibernate」を使用する.
*** インストール [#zf7238d6]
- ''ダウンロード''
以下のサイトより、3つのパッケージをダウンロードする.
サイト:http://www.hibernate.org/
パッケージ (2007/09/13時点)
-- Hibernate Core 3.2.5.ga
-- Hibernate Annotations 3.3.0 GA
-- Hibernate EntityManager 3.3.1 GA

- ''クラスパスを通す''
それぞれのパッケージは多くのライブラリに依存しているため、必要なライブラリ全てクラスパスを通す.
必要であるかは、同封のドキュメントにて確認する.
今回は実行時に必要なライブラリのみパスを通す.
-- Hibernate Core 3.2.5.ga
--- jta.jar
--- commons-logging-1.0.4.jar
--- xml-apis.jar
--- asm-attrs.jar
--- dom4j-1.6.1.jar
--- antlr-2.7.6.jar
--- cglib-2.1.3.jar
--- asm.jar
--- jdbc2_0-stdext.jar
--- xerces-2.6.2.jar
--- jaxen-1.1-beta-7.jar
--- commons-collections-2.1.1.jar
--- javassist.jar
--- hibernate3.jar

-- Hibernate Annotations 3.3.0 GA
--- hibernate-annotations.jar
--- ejb3-persistence.jar
--- hibernate-commons-annotations.jar

-- Hibernate EntityManager 3.3.1 GA
--- hibernate-entitymanager.jar
--- hibernate-validator.jar
--- jboss-archive-browsing.jar

*** 設定ファイル [#k3cbb4f0]
persistence.xmlと言うファイルを作成し、DB等の設定を定義する.
*** 設定ファイル - persistence.xml [#k3cbb4f0]
&color(blue){''persistence.xml''};と言うファイルを作成し、DB等の設定を定義する.
ファイルの配置場所は、クラスパスの通った「META-INF」配下に配備する.
META-INF/persistence.xml
以下のサンプルはDBにMySQLを使用した例.
|[DB_ID]|ユーザID|
|[DB_PASSWORD]|パスワード|
|[DB_IP]|DBのIP|
|[DB_PORT]|DBのポート|
|[DB_DBNAME]|使用するDB名|

 <?xml version="1.0" encoding="UTF-8"?>
 <persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="jpa-sample"
        transaction-type="RESOURCE_LOCAL">
    <persistence-unit name="jpa-sample" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>User</class>
        <class>sample.entity.User</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLMyISAMDialect" />
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
            <property name="hibernate.connection.username" value="[DB_ID]" />
            <property name="hibernate.connection.password" value="[DB_PASSWORD]" />
            <property name="hibernate.connection.url" value="jdbc:mysql://[DB_IP]:[DB_PORT]/[DB_DBNAME]" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.use_sql_comments" value="true" />
            
        </properties>
    </persistence-unit>
 </persistence>

** 使用方法 - 実装 [#ycd1e543]
- ''解説''
-- &color(blue){''<class>''}; - ''EntityBeanクラスの定義''
パッケージ名を含むクラス名を定義することで、JPAで使用するEntityBeanとみなされる.

-- &color(blue){''<properties>''}; - ''JDBC接続情報の定義''
Hibernateの''<property>''タグのname属性値
|~<property>タグのname属性値|~説明|
|hibernate.dialect|使用するDBクラス|
|hibernate.connection.driver_class|DBドライバクラス|
|hibernate.connection.username|ユーザ名|
|hibernate.connection.password|パスワード|
|hibernate.connection.url|DBのURL|
|hibernate.hbm2ddl.auto|自動的にDDLを有効にしデータベース出力する&br;validate:&br;update:&br;create:&br;create-drop:|
|hibernate.show_sql|ログにSQLを表示するか&br;true:表示する&br;false:表示しない|
|hibernate.format_sql|ログに表示したSQLをフォーマットするか&br;true:フォーマットする&br;false:フォーマットしない|
|hibernate.use_sql_comments|SQLコメントを表示するか&br;true:表示する&br;false:表示しない|


** 使用方法 - 実装 (単独テーブルへの追加、変更、削除、参照)[#ycd1e543]
以下のテーブルを操作するサンプルを作成する.
''テーブル名:User''
|~フィールド|~種別|~主キー|
|id|varchar(255)|●|
|age|int(11)||
|name|varchar(255)||

*** Entity Bean [#x982fa42]
ユーザ情報を保持するEntityBeanを作成する.
EntityBeanを作成する.

import java.io.Serializable;

import javax.persistence.Column;
 import java.io.Serializable;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.Table;
 
 @Entity
 @Table(name="User")
 public class User implements Serializable {
 	@Id
 	@Column(name="id")
 	private String id;
 
 	@Column(name="name")
 	private String name;
 
 	@Column(name="age")
 	private int age;
 	
  	
 	public int getAge() {
 		return age;
 	}
 	public void setAge(int age) {
 		this.age = age;
 	}
 	public String getId() {
 		return id;
 	}
 	public void setId(String id) {
 		this.id = id;
 	}
 	public String getName() {
 		return name;
 	}
 	public void setName(String name) {
 		this.name = name;
 	}
 	
 }

- ''解説''
ユーザ情報を保持するためのユーザクラス(POJO)を作成し、以下のアノテーションを定義することで、EntityBeanとなる.
-- &color(blue){''@Entity''}; - ''Entity Beanであることを定義''
クラス定義の前に「@Entity」を記述し、「Entity Bean」であることを定義する.

-- &color(blue){''@Table(name="User")''}; - ''このEntity Beanとマッピングするテーブル名を定義''
クラス定義の前に「@Table(name="User")」を記述し、name要素にマッピングするテーブル名記述する.
クラス名テーブル名が同じ場合は、「@Table(name="User")」は省略できる.
クラス名テーブル名が同じ場合は、&color(red){「@Table(name="User")」は省略できる.};

-- &color(blue){''@Id''}; - ''Primary Keyを定義''
「Primary Key」となるインスタンス変数に定義する.

-- &color(blue){''@Column(name="id")''}; - ''このインスタンス変数とマッピングするカラム名を定義''
インスタンス変数定義の前に「@Column(name="id")」を記述し、name要素にマッピングするカラム名を記述する.
インスタンス変数名とカラム名が同じ場合は、「@Column(name="id")」は省略できる.
インスタンス変数名とカラム名が同じ場合は、&color(red){「@Column(name="id")」は省略できる.};

*** EntityManager [#t9605dc6]
Entity Beanを管理するEntityManagerを取得する.
EntityManagerは、Entity Beanの永続性を管理するためのオブジェクト.
EntityManagerは以下のようにして取得する.

 // 永続化
 EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-sample");
 EntityManager entityManager = factory.createEntityManager();

- ''解説''
-- &color(blue){''Persistence.createEntityManagerFactory("jpa-sample");''}; - ''EntityManagerFactoryを取得''
Persistence#createEntityManagerFactory()を使用し、EntityManagerFactoryを取得を取得する.
Persistence#createEntityManagerFactory()を使用し、EntityManagerFactoryを取得する.
引数に、設定ファイル「persistence.xml」で記述した「persistence-unit name="jpa-sample"」の「jpa-sample」を渡す.

*** hibernate.hbm2ddl.autoによるDDL [#uae57a3f]
    create table User (
        id varchar(255) not null,
        age integer not null,
        name varchar(255),
        primary key (id)
    ) type=MyISAM

*** サンプル [#s31d4867]
テストクラスでの使用サンプル(Junit4.4)
データベースへの、新規追加(Insert)、更新(Update)、削除(Delete)、参照(find)のサンプル(Junit4.4).
設定ファイル(persistence.xml)は、上記の設定とする.

 package sample;
 import static org.junit.Assert.*;
 import static org.hamcrest.CoreMatchers.*;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
 
 import org.junit.Test;
 
 import sample.entity.User;
 
 public class JpaHibernateTest {
 	private static final String PERSISTENCE_UNIT_NAME = "jpa-sample1";
 	
 	/**
 	 * 新規追加(Insert)
 	 */
 	@Test
 	public void run() {
 	public void insert() {
 		// 永続化
 		EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-sample");
 		// ------------------------------
 		EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
 		EntityManager entityManager = factory.createEntityManager();
 		
 		// データの追加
 		// ************************************
 		
 		// EntityBeanをnew 
 		// ライフサイクル:new
 		// ------------------------------
 		User user = new User();
 		user.setId("1");
 		user.setName("Insert");
 		user.setAge(10);
 	
 		// Insert
 		// --------------------------
 		{
 			entityManager.getTransaction().begin();
 			User user = new User();
 			user.setId("id");
 			user.setName("name");
 			user.setAge(10);
 			
 			// Insert処理
 			entityManager.persist(user);
 			
 			// 確認
 			User actual = entityManager.find(User.class, "id");
 			assertThat(actual.getId(), is("id"));
 			assertThat(actual.getName(), is("name"));
 			assertThat(actual.getAge(), is(10));
 			entityManager.getTransaction().rollback();
 		}
 		// ライフサイクル:managed
 		// ------------------------------
 		entityManager.getTransaction().begin();
 		entityManager.persist(user);
 		entityManager.getTransaction().commit();
 		
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 	
 		
 		// 確認
 		// ************************************
 		User actual = entityManager.find(User.class, "1");
 		assertThat(actual.getId(), is("1"));
 		assertThat(actual.getName(), is("Insert"));
 		assertThat(actual.getAge(), is(10));
 	}
 
 	/**
 	 * 更新(Update)
 	 */
 	@Test
 	public void update() {
 		// 永続化
 		// ------------------------------
 		EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
 		EntityManager entityManager = factory.createEntityManager();
 		
 		// データの追加
 		// ************************************
 		
 		// EntityBeanをnew 
 		// ライフサイクル:new
 		// ------------------------------
 		User user = new User();
 		user.setId("1");
 		user.setName("Insert");
 		user.setAge(10);
 	
 		// Insert
 		// ライフサイクル:managed
 		// ------------------------------
 		entityManager.getTransaction().begin();
 		entityManager.persist(user);
 		entityManager.getTransaction().commit();
 		
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 	
 		
 		// データの更新
 		// ************************************
 		
 		// Select
 		// ライフサイクル:managed
 		// ------------------------------				
 		User user2 = entityManager.find(User.class, "1");
 		user2.setName("Update");
 		
 		// Update
 		// --------------------------
 		{
 			entityManager.getTransaction().begin();
 			User user = new User();
 			user.setId("id");
 			user.setName("name");
 			user.setAge(10);
 			// Insert処理
 			entityManager.persist(user);
 			
 			
 			User user2 = new User();
 			user2.setId("id");
 			user2.setName("name2");
 			user2.setAge(20);
 			
 			// Update処理
 			entityManager.merge(user2);
 			
 			// 確認
 			User actual = entityManager.find(User.class, "id");
 			assertThat(actual.getName(), is("name2"));
 			assertThat(actual.getAge(), is(20));
 			entityManager.getTransaction().rollback();
 		}
 		// ライフサイクル:managed
 		// ------------------------------		
 		entityManager.getTransaction().begin();
 		entityManager.merge(user2);
 		entityManager.getTransaction().commit();
 	
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 		
 		
 		// 確認
 		// ************************************
 		User actual = entityManager.find(User.class, "1");
 		assertThat(actual.getName(), is("Update"));
 	}
 
 	/**
 	 * 削除(Delete)
 	 */
 	@Test
 	public void delete() {
 		// 永続化
 		// ------------------------------
 		EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
 		EntityManager entityManager = factory.createEntityManager();
 		
 		// データの追加
 		// ************************************
 		
 		// EntityBeanをnew 
 		// ライフサイクル:new
 		// ------------------------------
 		User user = new User();
 		user.setId("1");
 		user.setName("Insert");
 		user.setAge(10);
 
 		// Insert
 		// ライフサイクル:managed
 		// ------------------------------
 		entityManager.getTransaction().begin();
 		entityManager.persist(user);
 		entityManager.getTransaction().commit();
 		
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 
 		
 		// データの削除
 		// ************************************
 		
 		// Select
 		// ライフサイクル:managed
 		// ------------------------------				
 		User user2 = entityManager.find(User.class, "1");
 		
 		// Delete
 		// --------------------------
 		{
 			entityManager.getTransaction().begin();
 			User user = new User();
 			user.setId("id");
 			user.setName("name");
 			user.setAge(10);
 			entityManager.persist(user);
 			
 			entityManager.remove(user);
 			User actual = entityManager.find(User.class, "id");
 			assertThat(actual, nullValue());
 			entityManager.getTransaction().rollback();
 		}
 		// ライフサイクル:removed
 		// ------------------------------		
 		entityManager.getTransaction().begin();
 		entityManager.remove(user2);
 		entityManager.getTransaction().commit();
 
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 		
 		// Select (主キー)
 		// --------------------------
 		{
 			entityManager.getTransaction().begin();
 			User user = new User();
 			user.setId("id");
 			user.setName("name");
 			user.setAge(10);
 			entityManager.persist(user);
 			
 			User actual = entityManager.find(User.class, "id");
 			assertThat(actual.getId(), is("id"));
 			assertThat(actual.getName(), is("name"));
 			assertThat(actual.getAge(), is(10));
 			entityManager.getTransaction().rollback();
 		}
 		
 		// Insert (おまけ)
 		// オブジェクトが同じであれば2回EntityManager#persist()で値を変更できる(Update扱い).
 		// --------------------------
 		{
 			entityManager.getTransaction().begin();
 			User user = new User();
 			user.setId("id");
 			user.setName("name");
 			user.setAge(10);
 			
 			// Insert処理
 			entityManager.persist(user);
 			user.setName("name2");
 			user.setAge(20);
 			entityManager.persist(user);
 			
 			// 確認
 			User actual = entityManager.find(User.class, "id");
 			assertThat(actual.getId(), is("id"));
 			assertThat(actual.getName(), is("name2"));
 			assertThat(actual.getAge(), is(20));
 			entityManager.getTransaction().rollback();
 		}
 		// 確認
 		// ************************************
 		User actual = entityManager.find(User.class, "1");
 		assertThat(actual, nullValue());
 	}
 
 	/**
 	 * 主キーによる参照(Select)
 	 */
 	@Test
 	public void selectByPk() {
 		// 永続化
 		// ------------------------------
 		EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
 		EntityManager entityManager = factory.createEntityManager();
 		
 		// データの追加
 		// ************************************
 		
 		// EntityBeanをnew 
 		// ライフサイクル:new
 		// ------------------------------
 		User user = new User();
 		user.setId("1");
 		user.setName("Insert");
 		user.setAge(10);
 	
 		// Insert
 		// ライフサイクル:managed
 		// ------------------------------
 		entityManager.getTransaction().begin();
 		entityManager.persist(user);
 		entityManager.getTransaction().commit();
 		
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 	
 		
 		// Select
 		// ライフサイクル:managed
 		// ------------------------------
 		User actual = entityManager.find(User.class, "1");
 		
 		// 確認
 		// ************************************
 		assertThat(actual.getId(), is("1"));
 		assertThat(actual.getName(), is("Insert"));
 		assertThat(actual.getAge(), is(10));
 	}
 }
- DBアクセス

- ''解説''
-- &color(blue){''新規追加(Insert)''}; - ''EntityManager#persist(Object[EntityBean]));''
+++ Entityオブジェクトを生成する
ライフサイクル -> ''new''
 User user = new User();
+++ Entityオブジェクトに追加する値をセットする
 user.setId("1");
 user.setName("Insert");
 user.setAge(10);
+++ トランザクションを開始する
 entityManager.getTransaction().begin();
+++ Entityオブジェクトを永続化する
ライフサイクル -> ''managed''
 entityManager.persist(user);
+++ コミットする
 entityManager.getTransaction().commit();
--- 発行されるSQL
    insert 
    into
        User
        (age, name, id) 
    values
        (?, ?, ?)

-- &color(blue){''更新(Update)''}; - ''EntityManager#merge(Object[EntityBean]);''
+++ 更新するEntityオブジェクトを取得する.
ライフサイクル -> ''managed''
 User user2 = entityManager.find(User.class, "1");
+++ Entityオブジェクトに更新する値をセットする
 user2.setName("Update");
+++ トランザクションを開始する
 entityManager.getTransaction().begin();
+++ 永続化しているEntityオブジェクトとマージする
ライフサイクル -> ''managed''
 entityManager.merge(user2);
+++ コミットする
 entityManager.getTransaction().commit();
--- 発行されるSQL
    update
        User 
    set
        age=?,
        name=? 
    where
        id=?

-- &color(blue){''削除(Delete)''}; - ''EntityManager#remove(Object[EntityBean]);''
+++ 削除するEntityオブジェクトを取得する
ライフサイクル -> ''managed''
 User user2 = entityManager.find(User.class, "1");
+++ トランザクションを開始する
 entityManager.getTransaction().begin();
+++ Entityオブジェクトを削除する
ライフサイクル -> ''remove''
 entityManager.remove(user2);
+++ コミットする
 entityManager.getTransaction().commit();
--- 発行されるSQL
    delete 
    from
        User 
    where
        id=?

-- &color(blue){''主キーによる参照(Select)''}; - ''EntityManager#find(EntityClass, String[primary key]);''
+++ 主キーを指定して、Entityオブジェクトを取得する
ライフサイクル -> ''managed''
 User user2 = entityManager.find(User.class, "1");
--- 発行されるSQL
    select
        user0_.id as id0_0_,
        user0_.age as age0_0_,
        user0_.name as name0_0_ 
    from
        User user0_ 
    where
        user0_.id=?

- ''まとめ''
-- &color(blue){''DBアクセス''};
|Insert|EntityManager#persist(Object[EntityBean]));|
|Update|EntityManager#merge(Object[EntityBean]);|
|Delete|EntityManager#remove(Object[EntityBean]);|
|Select (Primary Key)|EntityManager#find(Class, String[primary key]);|
|Select (Primary Key)|EntityManager#find(EntityClass, String[primary key]);|

- トランザクション
//*** Insert
//*** Update
//*** Delete
//*** Select (Primary Key)
//*** トランザクション
-- &color(blue){''トランザクション''};
|トランザクション開始|EntityManager#getTransaction()#begin();|
|コミット|EntityManager#getTransaction()#commit();|
|ロールバック|EntityManager#getTransaction()#rollback();|
//*** アノテーション一覧

*** サンプルダウンロード [#ffb1d2a1]
- [[jpa_hibernate-sample.zip[6.4MB]>http://www.trance.co.jp/wiki/index.php?down=jpa_hibernate-sample.zip]]

** 使用方法 - 実装 (1対多、多対1) [#md02552e]
以下のテーブルを操作するサンプルを作成する.
''テーブル名:OrderInfo''
|~フィールド|~種別|~主キー|
|id|int(11)|●|
|date|datetime||


''テーブル名:OrderInfoDetail''
|~フィールド|~種別|~主キー|
|id|int(11)|●|
|productName|varchar(255)||
|productPrice|int(11)||
|quantity|int(11)||
|orderInfo_id|int(11)||

*** Entity Bean [#q2d3ac2c]

「@Table」と「@Column」アノテーションは省略するため、
クラスメイトテーブル名、インスタンス変数名とカラムを同一にする.

 package sample2.entity;
 
 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.OneToMany;
 @Entity
 public class OrderInfo implements Serializable {
 	@Id
 	private int id;
 	private Date date;
 	@OneToMany(mappedBy="orderInfo")
 	private List<OrderInfoDetail> orderDetailList;
 	
 	public Date getDate() {
 		return date;
 	}
 	public void setDate(Date date) {
 		this.date = date;
 	}
 	public int getId() {
 		return id;
 	}
 	public void setId(int id) {
 		this.id = id;
 	}
 	public List<OrderInfoDetail> getOrderDetailList() {
 		return orderDetailList;
 	}
 	public void setOrderDetailList(List<OrderInfoDetail> orderDetailList) {
 		this.orderDetailList = orderDetailList;
 	}
 }


- ''解説''
-- &color(blue){''@OneToMany''}; - ''1対多のリレーションであることを定義''
インスタンス変数の前に「@OneToMany(mappedBy="orderInfo")」を記述し、mappedBy要素には、リレーション対象のクラスに定義したインスタンス変数名を記述する.
下記、「OrderInfoDetail」クラスの保持するOrderInfoオブジェクトのインスタンス変数「orderInfo」.


 package sample2.entity;
 
 import java.io.Serializable;
 
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 @Entity
 public class OrderInfoDetail implements Serializable {
 	@Id
 	private int id;
 	private String productName;
 	private int productPrice;
 	private int quantity;
 	@ManyToOne
 	private OrderInfo orderInfo;
 	
 	public int getId() {
 		return id;
 	}
 
 	public void setId(int id) {
 		this.id = id;
 	}
 
 	public OrderInfo getOrderInfo() {
 		return orderInfo;
 	}
 
 	public void setOrderInfo(OrderInfo orderInfo) {
 		this.orderInfo = orderInfo;
 	}
 
 	public String getProductName() {
 		return productName;
 	}
 
 	public void setProductName(String productName) {
 		this.productName = productName;
 	}
 
 	public int getProductPrice() {
 		return productPrice;
 	}
 
 	public void setProductPrice(int productPrice) {
 		this.productPrice = productPrice;
 	}
 
 	public int getQuantity() {
 		return quantity;
 	}
 
 	public void setQuantity(int quantity) {
 		this.quantity = quantity;
 	}
 
 }

- ''解説''
-- &color(blue){''@ManyToOne''}; - ''多対1のリレーションであることを定義''
インスタンス変数の前に「@ManyToOne」を記述する.


*** persistence.xml [#oda9de4f]
上記persistence.xmlに以下を追記

     <persistence-unit name="jpa-sample2" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
         <class>sample2.entity.OrderInfo</class>
         <class>sample2.entity.OrderInfoDetail</class>
         <properties>
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLMyISAMDialect" />
             <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
             <property name="hibernate.connection.username" value="taadmin" />
             <property name="hibernate.connection.password" value="trance" />
             <property name="hibernate.connection.url" value="jdbc:mysql://192.168.3.150:3306/jpasample2" />
             <property name="hibernate.hbm2ddl.auto" value="create-drop" />
             <property name="hibernate.show_sql" value="true" />
             <property name="hibernate.format_sql" value="true" />
             <property name="hibernate.use_sql_comments" value="false" />
         </properties>
     </persistence-unit>

*** hibernate.hbm2ddl.autoによるDDL [#u3da96f4]
    create table OrderInfo (
        id integer not null,
        date datetime,
        primary key (id)
    ) type=MyISAM

    create table OrderInfoDetail (
        id integer not null,
        productName varchar(255),
        productPrice integer not null,
        quantity integer not null,
        orderInfo_id integer,
        primary key (id)
    ) type=MyISAM

    alter table OrderInfoDetail 
        add index FKFD49806D9973955 (orderInfo_id), 
        add constraint FKFD49806D9973955 
        foreign key (orderInfo_id) 
        references OrderInfo (id)

*** サンプル [#a75f0069]
 package sample2;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
 import java.util.Date;
 import java.util.List;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
 
 import org.junit.Test;
 
 import sample2.entity.OrderInfo;
 import sample2.entity.OrderInfoDetail;
 
 public class JpaHibernateTest2 {
 	
 	private static final String PERSISTENCE_UNIT_NAME = "jpa-sample2";
 
 	@Test
 	public void oneToMany() {
 		// 永続化
 		// ------------------------------
 		EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
 		EntityManager entityManager = factory.createEntityManager();
 		
 		// データの追加
 		// ************************************
 		
 		// EntityBeanをnew 
 		// ライフサイクル:new
 		// ------------------------------
 		Date InsertDate = new Date();
 		OrderInfo order = new OrderInfo();
 		order.setId(1);
 		order.setDate(InsertDate);
 		
 		OrderInfoDetail detail1 = new OrderInfoDetail();
 		detail1.setId(1);
 		detail1.setOrderInfo(order);
 		detail1.setProductName("商品名1");
 		detail1.setProductPrice(1000);
 		detail1.setQuantity(1);
 		
 		OrderInfoDetail detail2 = new OrderInfoDetail();
 		detail2.setId(2);
 		detail2.setOrderInfo(order);
 		detail2.setProductName("商品名2");
 		detail2.setProductPrice(2000);
 		detail2.setQuantity(2);
 	
 		// Insert
 		// ライフサイクル:managed
 		// ------------------------------
 		entityManager.getTransaction().begin();
 		entityManager.persist(order);
 		entityManager.persist(detail1);
 		entityManager.persist(detail2);
 		entityManager.getTransaction().commit();
 		
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 	
 		
 		// Select
 		// ライフサイクル:managed
 		// ------------------------------
 		OrderInfo actual = entityManager.find(OrderInfo.class, 1);
 		
 		// 確認
 		// ************************************
 		assertThat(actual.getId(), is(1));
 		
 		List<OrderInfoDetail> orderDetailList = actual.getOrderDetailList();
 		assertThat(orderDetailList.size(), is(2));
 		
 		OrderInfoDetail actualDetail1 = orderDetailList.get(0);
 		assertThat(actualDetail1.getId(), is(detail1.getId()));
 		assertThat(actualDetail1.getProductName(), is(detail1.getProductName()));
 		assertThat(actualDetail1.getProductPrice(), is(detail1.getProductPrice()));
 		assertThat(actualDetail1.getQuantity(), is(detail1.getQuantity()));
 		
 		OrderInfoDetail actualDetail2 = orderDetailList.get(1);
 		assertThat(actualDetail2.getId(), is(detail2.getId()));
 		assertThat(actualDetail2.getProductName(), is(detail2.getProductName()));
 		assertThat(actualDetail2.getProductPrice(), is(detail2.getProductPrice()));
 		assertThat(actualDetail2.getQuantity(), is(detail2.getQuantity()));
 	}
 	
 	
 	@Test
 	public void ManyToOne() {
 		// 永続化
 		// ------------------------------
 		EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
 		EntityManager entityManager = factory.createEntityManager();
 		
 		// データの追加
 		// ************************************
 		
 		// EntityBeanをnew 
 		// ライフサイクル:new
 		// ------------------------------
 		Date InsertDate = new Date();
 		OrderInfo order = new OrderInfo();
 		order.setId(1);
 		order.setDate(InsertDate);
 		
 		OrderInfoDetail detail1 = new OrderInfoDetail();
 		detail1.setId(1);
 		detail1.setOrderInfo(order);
 		detail1.setProductName("商品名1");
 		detail1.setProductPrice(1000);
 		detail1.setQuantity(1);
 		
 		OrderInfoDetail detail2 = new OrderInfoDetail();
 		detail2.setId(2);
 		detail2.setOrderInfo(order);
 		detail2.setProductName("商品名2");
 		detail2.setProductPrice(2000);
 		detail2.setQuantity(2);
 	
 		// Insert
 		// ライフサイクル:managed
 		// ------------------------------
 		entityManager.getTransaction().begin();
 		entityManager.persist(order);
 		entityManager.persist(detail1);
 		entityManager.persist(detail2);
 		entityManager.getTransaction().commit();
 		
 		// 管理していたEntityBeanをクリア
 		// ライフサイクル:detached
 		// ------------------------------		
 		entityManager.clear();
 	
 		
 		// Select
 		// ライフサイクル:managed
 		// ------------------------------
 		OrderInfoDetail actual = entityManager.find(OrderInfoDetail.class, 1);
 		
 		// 確認
 		// ************************************
 		assertThat(actual.getId(), is(detail1.getId()));
 		assertThat(actual.getProductName(), is(detail1.getProductName()));
 		assertThat(actual.getProductPrice(), is(detail1.getProductPrice()));
 		assertThat(actual.getQuantity(), is(detail1.getQuantity()));
 		
 		OrderInfo actualOrder = actual.getOrderInfo();
 		assertThat(actualOrder.getId(), is(order.getId()));
 	}
 }

- ''データ''
OrderInfo
|~id|~date|
|1|2007-09-26 10:23:33|

OrderInfoDetail
|~id|~productName|~productPrice|~quantity|~orderInfo_id|
|1|商品名1|1000|1|1|
|2|商品名2|2000|2|1|


- ''解説''
-- &color(blue){''1対多''};
+++ OrderInfoを取得する
 OrderInfo actual = entityManager.find(OrderInfo.class, 1);
取得したOrderInfoのインスタンス変数「orderDetailList」には、リレーションで紐付けられているOrderInfoDetailオブジェクトが格納されている.
紐付けられているOrderInfoDetailは、「orderInfo_id」の値が「1」のOrderInfoDetail.
--- 発行されるSQL
    select
        orderinfo0_.id as id0_0_,
        orderinfo0_.date as date0_0_ 
    from
        OrderInfo orderinfo0_ 
    where
        orderinfo0_.id=?
&BR;
    select
        orderdetai0_.orderInfo_id as orderInfo5_1_,
        orderdetai0_.id as id1_,
        orderdetai0_.id as id1_0_,
        orderdetai0_.orderInfo_id as orderInfo5_1_0_,
        orderdetai0_.productName as productN2_1_0_,
        orderdetai0_.productPrice as productP3_1_0_,
        orderdetai0_.quantity as quantity1_0_ 
    from
        OrderInfoDetail orderdetai0_ 
    where
        orderdetai0_.orderInfo_id=?
--- 結果
 OrderInfo
 :id->1
 :date->2007-09-26 10:23:33
 :orderDetailList->
	OrderInfoDetail
	:id->1
	:productName->商品名1
	:productPrice->1000
	:quantity->1
	:orderInfo_id->OrderInfo
	OrderInfoDetail
	:id->2
	:productName->商品名2
	:productPrice->2000
	:quantity->2
	:orderInfo_id->OrderInfo

-- &color(blue){''多対1''};
+++ OrderInfoDetailを取得する
 OrderInfoDetail actual = entityManager.find(OrderInfoDetail.class, 1);
取得したOrderInfoDetailのインスタンス変数「orderInfo」には、リレーションで紐付けられているOrderInfoオブジェクトが格納されている.
紐付けられているOrderInfoは、「id」の値が「1」のOrderInfo.
--- 発行されるSQL
    select
        orderinfod0_.id as id1_1_,
        orderinfod0_.orderInfo_id as orderInfo5_1_1_,
        orderinfod0_.productName as productN2_1_1_,
        orderinfod0_.productPrice as productP3_1_1_,
        orderinfod0_.quantity as quantity1_1_,
        orderinfo1_.id as id0_0_,
        orderinfo1_.date as date0_0_ 
    from
        OrderInfoDetail orderinfod0_ 
    left outer join
        OrderInfo orderinfo1_ 
            on orderinfod0_.orderInfo_id=orderinfo1_.id 
    where
        orderinfod0_.id=?

--- 結果
 OrderInfoDetail
 :id->1
 :productName->商品名1
 :productPrice->1000
 :quantity->1
 :orderInfo_id->
	OrderInfo
	:id->1
	:date->2007-09-26 10:23:33
	:orderDetailList->OrderInfoDetail


*** サンプルダウンロード [#x493789f]
- [[jpa_hibernate-sample2.zip[6.4MB]>http://www.trance.co.jp/wiki/index.php?down=jpa_hibernate-sample2.zip]]



//** アノテーション一覧 [#jd01ea3f]
//|アノテーション|説明|記述場所|要素|要素説明|
//|@Entity|Entity Beanであることを定義|クラス|||
//|@Tabel||
//|@Id||
//|@Column||
//|||


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS