mini_S2.4andS2ejb3unit

S2.4 & S2EJB3Unit
中村(taedium)
Seasar 2.4 の特徴 1
• Sesar 2.4 は
しています。
EJB 3.0 を実装
• EJB 3.0 の仕様は5月12日にFinal
Releaseされたばかりの新しい技術
です。
Seasar 2.4 の特徴 2
• Sesar2.4 ではEJB 3.0に加えO/Rマッピング
機能の標準である
Java Persistence API
(JPA)を使うこともできます。
• Sesar2.4 でJPAを使うにはHibernateと連携
するためのS2Hibernate-JPAを利用
します。
EJB 3.0 や JPAは使える技術?
• 以前のEJBに比べるとずいぶん使いやすく
なっている。アノテーションを使った設定がわ
かりやすい。
– EJB 3.0 : DIコンテナに慣れている人には問題な
く受け入れられるはず。
– JPA : Hibernateに慣れている人には問題なく受
け入れられるはず。
• ただ…
問題点
1. EJBはサーバにデプロイしないと動かせな
い。
2. EJBは単体テストがしにくい。JPAのエン
ティティのデータを比較するテストが面倒。
3. EJB 3.0はインターセプタの機能が貧弱。
JPAはSQLを使いにくい。
Seasarの対応 1
• EJBはサーバにデプロイしないと動かせない。
• Seasar 2.4はサーバにデプロイし
なくてもEJB 3.0のコンポーネントを動か
すことを可能にする。
Seasarの対応 2
• EJBは単体テストがしにくい。JPAのエンティ
ティのデータを比較するテストが面倒。
• Seasar 2.4はJUnitを拡張した
S2EJB3Unitを提供し、EJB 3.0や
JPAを使ったプログラムの単体テストを簡単
する。
Seasarの対応 3
• EJB 3.0はインターセプタの機能が貧弱。JPA
はSQLが使いにくい。
• Seasar 2.4 は EJB 3.0の足りない機能を補
い拡張できる。
ここで簡単にまとめ
ここで簡単にまとめ
Sesar2.4 ではJavaの標準技術である
EJB 3.0 と
Java Persistence API
が
使える。
さらに
これらをより使いやすくする。
Sesar2.4 は
Sesar 2.4でEJB 3.0を動かす
•
•
•
•
•
•
•
•
•
•
@Stateless
@EJB
@Stateful
@Local
@TransactionManagement
@TransactionAttribute
@Interceptors
@ExcludeClassInterceptors
@PostConstruct
@AroundInvoke
Sesar 2.4でEJB 3.0を動かす
GreetingMain
GreetingClient
<<realize>>
GreetingClientImpl
EJB 3.0を使った開発の基
本はDIコンテナを使うときと
同じ。
インタフェースに対してプロ
グラミングする。
+
execute() : void
Greeting
<<realize>>
GreetingImpl
+
greet() : String
Sesar 2.4でEJB 3.0を動かす
public interface GreetingClient {
void execute();
}
public interface Greeting {
String greet();
}
1.まず、インタフェースを作成。
@Stateless
public class GreetingClientImpl implements GreetingClient {
@EJB
private Greeting greeting;
フィールドインジェクション
public void execute() {
System.out.println(greeting.greet());
}
}
@Stateless
public class GreetingImpl implements Greeting {
2.実装クラスにEJB 3.0
のアノテーションをつけ
る。
3.DIするためにアノ
テーションを付ける。
public String greet() {
return "Hello World!";
}
}
4.JNDIでlookupして実
行。
Context ctx = new InitialContext();
GreetingClient greetingClient = (GreetingClient) ctx.lookup("greetingClient");
greetingClient.execute();
S2EJB3Unitとは
• JUnitの拡張版。
• EJBに対するテストを行う。
• JPAを使ったDAOのテストを行う。
• JPAのエンティティのテストを行う。
S2EJB3Unitの特徴 1
DIの指定
@EJBでDIする。
public class HogeTest extends S2EJB3TestCase {
@EJB
private GreetingClient greetingClient;
@EJB(beanName=“xxx”)
private GreetingClient greetingClient2;
}
S2EJB3Unitの特徴 2
DIされるコンポートの指定
public class HogeTest extends S2EJB3TestCase {
@EJB
private GreetingClient greetingClient;
DIされるコンポーネントは
設定ファイルを使ってまと
めて、もしくはクラスごとに
登録できる。
@Override
public void setUp() throws Exception {
super.setUp();
include("examples/ejb3/dicon/GreetingMain.dicon");
register(GreetingImpl.class);
}
}
S2EJB3Unitの特徴 3
ロールバックをアノテーションで指定
@Rollbackでtestメソッド開始前にトランザクショ
ンを開始しメソッド終了後にトランザクションをロー
ルバックする。→DBを汚さずにすむ。
public class HogeTest extends S2EJB3TestCase {
@Rollback
public void testFindEmployee() {
//…DBアクセス処理
}
}
S2EJB3Unitの特徴 4
EntityManagerの取得
Java Persistence APIの
EntityManagerがgetterで取得
するだけで使える。
public class HogeTest extends S2EJB3TestCase {
@Rollback
public void testFindEmployee() {
getEntityManager().find(Employee.class, new Long(1));
}
}
S2EJB3Unitの特徴 5
準備値(Excelデータ) 、期待値(Excelデータ)、実際値(エンティティ)
テストデータはExcelで用意
してDBに書き込む。
テストの期待値はExcelで用
意する。
public class GreetingClientImplTest extends S2EJB3TestCase {
@Rollback
public void testFindEmployee() {
readXlsWriteDb("Prepare.xls");
DataSet expected = readXls("findEmployeeResult.xls");
Employee actual =
getEntityManager().find(Employee.class, new Long(1));
assertEntityEquals("0", expected, actual);
}
}
期待値とEntityのデータを比
較するアサートメソッド。
S2EJB3Unitの特徴 6
更新の検証
EmployeeEntityを更新。
public class GreetingClientImplTest extends S2EJB3TestCase {
@Rollback
public void testUpdateEmployee() {
readXlsWriteDb("Prepare.xls");
DataSet expected = readXls("updateEmployeeResult.xls");
Employee employee = getEntityManager().find(Employee.class, new Long(2));
employee.setSalary(9999);
assertEquals("0", expected, reload(expected));
}
}
DataSet同士を比較する。
DBを更新し期待値のデータを
読み直す。
S2EJB3Unitを動かしてみる
• 実際にS2EJB3Unitを動かして見ます。
テーブルとエンティティのマッピング
Department
PK
ID
Employee
1
0..*
PK
ID
FK1
FK2
EMPLOYEENAME
SALALY
DEPT_ID
ADDRESS_ID
DEPARATMENTNAME
Department
エンティティ
Employee
エンティティ
0..1
1
Address
PK
ID
CITY
Address
エンティティ
テーブルとエンティティの比較 1
• エンティティ単体(もしく
リスト)をDBデータと比
較する
ターゲットとなるエンティティ
の値のみを比較する。
Employee
Department
PK
ID
PK
ID
FK1
FK2
EMPLOYEENAME
SALALY
DEPT_ID
ADDRESS_ID
DEPARATMENTNAME
Address
PK
ID
CITY
テーブルとエンティティの比較 2
• エンティティ単体(もしく
はリスト)のリレーション
シップを含めてDBデー
タと比較する
ターゲットとなるエン
ティティから辿れるリ
レーションも比較対象
とする。
Employee
Department
PK
ID
PK
ID
FK1
FK2
EMPLOYEENAME
SALALY
DEPT_ID
ADDRESS_ID
DEPARATMENTNAME
Address
PK
ID
CITY
テーブルとエンティティの比較 3
• Java上で参照があれ
ば逆向きにも辿ること
ができる。遅延ローディ
ングにも対応。
クエリでDepartmentを取得
した場合、Employeeは遅
延ローディングされるが
Employeeも比較可能。
Employee
Department
PK
ID
PK
ID
FK1
FK2
EMPLOYEENAME
SALALY
DEPT_ID
ADDRESS_ID
DEPARATMENTNAME
Address
PK
ID
CITY
複雑なマッピングにも対応
Department
PK
Employee
1
0..*
ID
PK
ID
FK1
FK2
EMPLOYEENAME
SALALY
DEPT_ID
ADDRESS_ID
DEPARATMENTNAME
ポリモーフィズム
を使ったマッピン
グに対しても
データの比較が
可能。
1
PK
0..1
FulltimeEmployee
ID
BONUS
ID
CITY
1
0..1
PK,FK1
Address
1
0..1
ParttimeEmployee
PK,FK1
ID
WORKHOUR
エンティティの更新
• エンティティ単体(もしく
リスト)をDBデータと比
較する
ターゲットとなるエンティティ
の値のみを比較する。
Employee
Department
PK
ID
PK
ID
FK1
FK2
EMPLOYEENAME
SALALY
DEPT_ID
ADDRESS_ID
DEPARATMENTNAME
Address
PK
ID
CITY