OpenJPAは、
これが組み込まれているプロダクトには、
また、
Kodoは、
オープンソースのプロダクトは、
Java Persistence API(JPA)とは
Java Persistence API(JPA)とは、
仕様の策定は、
特徴は、
OpenJPAによるO/Rマッピング
では、
O/
ここから、
persistence.xmlによるデータベース設定
JPAにおいてO/
リスト1にpersistence.
ルートタグ<persistence>の中には複数の<persistence-unit>タグを記述できます。Javaプログラムから設定を利用されるのは<persistence-unit>のほうです。この中の<property>タグにJDBC接続などで必要な設定を記述します。これらは実行時にシステムプロパティとして設定することもできます。ここでは、
<?xml version="1.0" encoding="Windows-31J"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<persistence-unit name="miniblog" transaction-type="RESOURCE_LOCAL">
<!-- データベースのテーブルに対応するJavaクラス -->
<class>Miniblog</class>
<!-- データベースに関する設定(JDBC関連など) -->
<properties>
<!-- ドライバクラス名 -->
<property name="openjpa.ConnectionDriverName"
value="org.apache.derby.jdbc.EmbeddedDriver"/>
<!-- 接続URL -->
<property name="openjpa.ConnectionURL"
value="jdbc:derby:openjpa-example;create=true" />
<!-- データベース接続用のユーザ名 -->
<property name="openjpa.ConnectionUserName" value="" />
<!-- データベース接続用のパスワード -->
<property name="openjpa.ConnectionPassword" value="" />
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema" />
<!-- ログ出力の設定(実行したSQLも出力) -->
<property name="openjpa.Log" value="DefaultLevel=WARN,SQL=TRACE" />
</properties>
</persistence-unit>
</persistence>
エンティティクラスの作成
データベースのテーブルに対応するエンティティクラスは、
- 1.クエリ設定
-
クエリとは、
データベースに対するデータの問い合わせのことです。JPAでは@NamedQueryに記述します。設定を複数記述する場合は@NamedQueries内に@NamedQueryの配列を記述します。通常クエリはSQLで記述されますが、 ここではEJB QLという言語で記述されています。といっても両者はよく似ており、 リスト2に記述した程度の短かさだと、 パラメータを表す:name以外はほとんど区別がつかないほどです。 - 2.プロパティ
-
Miniblogクラスは、
個別のデータを表すID(id)、 ユーザ名(name)、 という4つのプロパティを持っています。これらはそのままテーブルが持つカラムとなります。ユーザが投稿したメッセージ(message)、 データが生成された日時(createdDate) -
idプロパティの値は、
@Idと@GeneratedValueによってデータごとに自動的に番号がつけられるようになっています。それ以外は@Basicによってプロパティの名称やデータ型に対応するカラムがマッピングされます。 - 3.コンストラクタ
-
エンティティクラスには、
引数を持たないコンストラクタが必要です。それ以外は、 Javaプログラムとして必要なものを宣言します。リスト2では、 ユーザ名とメッセージから1つのインスタンスを生成できるようにしています。 - 4.getter/
setterメソッド -
データベースにデータを保存したり、
逆にデータベースからデータを取得したりする際に用いられるメソッドです。記述は単調ですが、 エンティティクラスにとってはデータのやり取りをする要(かなめ)となる大事なメソッドです。
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
// エンティティクラスであることを示す
@Entity
// あらかじめ定型的なクエリに名前をつけておく
@NamedQueries( {
@NamedQuery(
name="findAllMessages",
query="select mb from Miniblog mb"
),
@NamedQuery(
name="findAllMessagesByName",
query="select mb from Miniblog mb where mb.name = :name"
),
@NamedQuery(
name="findAllNames",
query="select distinct mb.name from Miniblog mb order by mb.name"
)
} )
// エンティティクラス
public class Miniblog implements java.io.Serializable {
@Id
@GeneratedValue
private long id; // ID番号
@Basic
private String name; // ユーザ名
@Basic
private String message; // メッセージ
@Basic
private Date createdDate = new Date(); // データが生成された日時
public Miniblog() {} // 引数が空のコンストラクタが必要
public Miniblog( String nm, String msg ) { // 引数はユーザ名、メッセージ
setName( nm );
setMessage( msg );
}
// getterメソッド(データ取得)
public long getId() { return id; }
public String getName() { return name; }
public String getMessage() { return message; }
public Date getCreatedDate() { return createdDate; }
// setterメソッド(データ設定)
public void setId( long value ) { id = value; }
public void setName( String nm ) { name = nm; }
public void setMessage( String msg ) { message = msg; }
public void setCreatedDate( Date d ) { createdDate = d; }
}
EntityManagerの生成
persistence.
実際の手順は、
このとき、
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
....................
EntityManagerFactory factory =
Persistence.createEntityManagerFactory(
"miniblog", System.getProperties() );
EntityManager em = factory.createEntityManager();
// ..... (省略) .....
em.close();
factory.close();
データの書き込み(保存)
データの書き込みは、
リスト4によってデータベース(Apache Derby)に対して実行されるSQLをリスト5に示します。先頭のCREATE TABLEは、
その後のINSERT文中に記述されている ? はパラメータマーカーで、
// 書き込むミニブログのデータ(ユーザ名、投稿する文字列)
import java.util.Date;
....................
Miniblog[] minblog = {
new Miniblog( "masanori", "ようやく過ごしやすい天気になってきたね" ),
new Miniblog( "okibayashi", "でもこれからまた暑くなるらしいよ" ),
new Miniblog( "masanori", "えぇ~、またぁ 早く涼しくならないかなぁ" ),
new Miniblog( "okibayashi", "まだしばらくは我慢しなきゃならないみたいだ" )
};
for( Miniblog mb : minblog ) {
mb.setCreatedDate( new Date() ); // 日時を修整
em.getTransaction().begin(); // トランザクション開始
em.persist( mb ); // データベースに書き込み(保存)
em.getTransaction().commit(); // トランザクション終了(コミット)
Thread.sleep( 990 ); // 投稿に時間差をつける(約1秒間)
}
CREATE TABLE Miniblog (id BIGINT NOT NULL, createdDate TIMESTAMP, message VARCHAR(255), name VARCHAR(255), PRIMARY KEY (id))
INSERT INTO Miniblog (id, createdDate, message, name) VALUES (?, ?, ?, ?) [params=(long) 1, (Timestamp) 2007-08-31 16:33:57.448, (String) ようやく過ごしやすい天気になってきたね, (String) masanori]
INSERT INTO Miniblog (id, createdDate, message, name) VALUES (?, ?, ?, ?) [params=(long) 2, (Timestamp) 2007-08-31 16:33:59.24, (String) でもこれからまた暑くなるらしいよ, (String) okibayashi]
INSERT INTO Miniblog (id, createdDate, message, name) VALUES (?, ?, ?, ?) [params=(long) 3, (Timestamp) 2007-08-31 16:34:00.251, (String) えぇ~、またぁ 早く涼しくならないかなぁ, (String) masanori]
INSERT INTO Miniblog (id, createdDate, message, name) VALUES (?, ?, ?, ?) [params=(long) 4, (Timestamp) 2007-08-31 16:34:01.252, (String) まだしばらくは我慢しなきゃならないみたいだ, (String) okibayashi]
データの読み込み(クエリ発行)
JPAでは、
リスト6はシンプルなSELECTを実行した例です。この結果を取得するにはQuery.
リスト7は、
リスト8は、
import java.text.SimpleDateFormat;
import java.util.List;
import javax.persistence.Query;
....................
SimpleDateFormat sdf = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" );
// Query q1 = em.createQuery( "select mb from Miniblog mb" );
Query q1 = em.createNamedQuery( "findAllMessages" );
for ( Miniblog mb : (List<Miniblog>) q1.getResultList() ) {
System.out.printf( "%03d %-19s %-10s - %-30s\n",
mb.getId(), sdf.format( mb.getCreatedDate() ), mb.getName(), mb.getMessage() );
}
001 2007/08/31 16:33:57 masanori - ようやく過ごしやすい天気になってきたね 002 2007/08/31 16:33:59 okibayashi - でもこれからまた暑くなるらしいよ 003 2007/08/31 16:34:00 masanori - えぇ~、またぁ 早く涼しくならないかなぁ 004 2007/08/31 16:34:01 okibayashi - まだしばらくは我慢しなきゃならないみたいだ
// EntityManagerによるQuery生成
Query q2 = em.createNamedQuery( "findAllMessagesByName" )
.setParameter( "name", "masanori" );
SELECT t0.id, t0.createdDate, t0.message,t0.name FROM Miniblog t0 WHERE (t0.name = ?) [params=(String) masanori]
001 2007/08/31 16:33:57 masanori - ようやく過ごしやすい天気になってきたね 003 2007/08/31 16:34:00 masanori - えぇ~、またぁ 早く涼しくならないかなぁ
// EntityManagerによるNamedQuery生成
Query q3 = em.createNamedQuery( "findAllNames" );
SELECT DISTINCT t0.name FROM Miniblog t0 ORDER BY t0.name ASC
masanori okibayashi
JPAを用いると、
ここでは紹介できなかった複雑なリレーションを設定する方法も、