s2jdbcを使う
s2jdbcの使い方についてはSeasarのホームページ(Seasar2 - S2JDBC)に詳しく書いてあるので、ここでは私なりにs2jdbcを探検した結果について書いてみる。
s2jdbc-tutorialプロジェクトを探検
前回のs2jdbc-tutorialのセットアップとMySQLでセットアップをおこなったs2jdbc-tutorialプロジェクトの/s2jdbc-tutorial/src/test/java/examplesパッケージに有益なs2jdbcのサンプルコードが多くのっているのでまずはこれを動かしてみる。
サンプルコードはS2Unitを使ったテストクラスとなっている。
これらのサンプルクラを実行するには、パッケージエクスプロラーよりソースコードを選択し、マウスの右クリックにて表示されるメニューより「実行」→「JUnitテスト」を選択すればよい。
試しに「/s2jdbc-tutorial/src/test/java/examples/GetResultListTest.java」を実行した結果を以下に示す。
「GetResultListTest.java」の主要なコードであるtestGetResultListメソッドの内容 は Seasar2 - S2JDBC - チュートリアルの複数件検索で説明されているコードそのものであるので説明の必要もないが、 たったこれだけのコードでEmployeeテーブルのname列の値の一覧をコンソールに出力する事ができる。
他のサンプルも同様に 「Seasar2 - S2JDBC - S2JDBCとは」と 「Seasar2 - S2JDBC - チュートリアル」を参考にプログラムを実行しながらソースをみていけば理解できると思う。
Javaアプリケーションてs2jdbc(プロジェクトの作成)
s2jdbc-tutorialプロジェクトのサンプルはすべてS2Unitを使ったテストクラスとなっている。
このコードは通常のJavaアプリケーションで動作させるためにはどうしたらよいだろう。
s2jdbcを使ってデータベースにアクセスするためにはJdbcManagerのインスタンスを取得する必要がある。
s2jdbcが動作するJavaアプリケーション環境をつくるにはDoletngを使って新しいプロジェクトを作成するのが簡単である。
eclipseより「ファイル」→「新規」→「プロジェクト」→「Dolteng」→「Doltengプロジェクト」を選択して表示されるダイヤログボックスにて、アプリケーション・タイプとしてスタンドアロン・アプリケーション,永続化にS2JDBCを選択して,ルートパッケージ名として適当な名前を入力して完了ボタンを押す。
ここではプロジェクト名として「S2jdbcApp」をルートパッケージ名として「examples」を指定している。
使用したいデータベースに合わせてs2jdbc-tutorialのセットアップとMySQLを参考にjdbc.diconとs2jdbc.diconの設定を修正する.
libフォルダにJDBCドライバーをコピーしてクラスパスに追加する。
必要に応じてS2JDBC-Genによるテーブルのエンティティの自動生成とソースコードの修正を参考にエンティティクラスを作成、s2jdbc-tutorial/と同じコードを実行するのであればs2jdbc-tutorialプロジェクトよりsrc/main/java/examples/entity/JobType.javaをコピーする。
Doletngで作成したプロジェクトではS2Containerの機能が使用できます。
このS2Containerの機能を利用していろいろな方法でJdbcManagerのインスタンスを取得する事ができる。
話を単純にするためのアプリケーション・タイプをスタンドアロン・アプリケーションに指定したが通常は「Webアプリケーション」を指定する事になると思う。
Javaアプリケーションでs2jdbc(JdbcManagerのインスタンスを取得)
JdbcManagerのインスタンスを取得するにはS2Containerの機能を利用して以下のようなコードを記述します。
// S2Containerの初期化 SingletonS2ContainerFactory.init(); // JdbcManagerのインスタンスを取得 JdbcManager jdbcManager=SingletonS2Container.getComponent("jdbcManager");
BeanUtil クラスを利用する
以下は例はS2jdbcAppプロジェクトに新規クラス「S2jdbcApp」を作成してそのmainメソッドにてJdbcManagerのインスタンスを取得してEmployeeテーブルの全データをコンソールに表示するコードの例です。
SeasarにはCommons BeanUtilsの流れるようなインターフェース版のクラスが用意されていて、エンティティクラスよりMapにコピーして表示するようなコードを簡潔に記述する事ができる。
Seasar - S2BeanUtils -
BeanMap (S2 Tiger 2.4.38 API)
package examples; import java.util.List; import org.seasar.extension.jdbc.JdbcManager; import org.seasar.framework.beans.util.BeanMap; import org.seasar.framework.beans.util.Beans; import org.seasar.framework.container.SingletonS2Container; import org.seasar.framework.container.factory.SingletonS2ContainerFactory; import examples.entity.Employee; public class S2jdbcApp { public static void main(String[] args) { // S2Containerの初期化 SingletonS2ContainerFactory.init(); // JdbcManagerのインスタンスを取得 JdbcManager jdbcManager=SingletonS2Container.getComponent("jdbcManager"); System.out.println("executeJdbcManager"); List<Employee> empItems = jdbcManager.from(Employee.class).getResultList(); for ( Employee e : empItems) { BeanMap beanMap=Beans.createAndCopy(BeanMap.class, e).execute(); System.out.println(beanMap); for (String str : beanMap.keySet()) { System.out.print("\t" + str + ": " + beanMap.get(str)); } System.out.println(); } } }
以下に実行結果を示す。
Employeeテーブルの全行,全列のデータが出力されているのがわかる。
S2ContainerのクリエータとResourceアノテーションの機能を利用する
/プロジェクト/src/main/resourcesのcreator.diconにはあらかじめクリエータが定義されているので、クリエータのルールに従って規定のパッケージにクラスを定義する事により、diconファイルにDI対象のクラスを設定しなくてもS2Containerによりクラスのインスタンスを自動取得する事ができます。
例えばLogicCreatorを使ってビジネスロジックのクラスを定義するには「ルートパッケージ.logic」パッケージにクラス名がLogicで終わるクラスを作成します。
S2Containerにより自動生成されたクラスではResourceアノテーションを指定してクラスのインスタンス変数としてJdbcManagerを定義することによりクラスの生成時にインスタンス変数に自動的にJdbcManagerのインスタンスがセットされます。
以下に例を示します。
パッケージexamples.logicに新規クラスDITest1Logicを作成して、このクラスにビジネスロジックの処理を記述します。
package examples.logic; import java.util.List; import javax.annotation.Resource; import org.seasar.extension.jdbc.JdbcManager; import org.seasar.framework.beans.util.BeanMap; import org.seasar.framework.beans.util.Beans; import examples.entity.Employee; public class DITest1Logic { @Resource private JdbcManager jdbcManager; public void executeJdbcManager() { System.out.println("executeJdbcManager"); List<Employee> empItems = jdbcManager.from(Employee.class).getResultList(); for ( Employee e : empItems) { BeanMap beanMap=Beans.createAndCopy(BeanMap.class, e).execute(); System.out.println(beanMap); for (String str : beanMap.keySet()) { System.out.print("\t" + str + ": " + beanMap.get(str)); } System.out.println(); } } }
パッケージexamplesにjavaアプリケーションとして動作させる新規クラスDITest1Mainを作成して、 S2Containerによりロジッククラスのインスタンスを取得し、このクラスにビジネスロジックの処理をゆだねます。
package examples; import org.seasar.framework.container.SingletonS2Container; import org.seasar.framework.container.factory.SingletonS2ContainerFactory; import examples.logic.DITest1Logic; public class DITest1Main { public static void main(String[] args) { SingletonS2ContainerFactory.init(); DITest1Logic dITest1Logic=SingletonS2Container.getComponent(DITest1Logic.class); dITest1Logic.executeJdbcManager(); } }
Service クラスを利用する
JdbcManagerクラスの替わりに Serviceクラスを利用してデータベースにアクセスする事ができます。
Service クラスはS2JDBC-Gen の Gen-Service タスクによって自動生成できます。
S2JDBC-Genによるテーブルのエンティティの自動生成をしていれば、以下のようにサービスクラスが存在しているはずです。
サービスクラスについては以下のリンクを参照して下さい。
- Seasar2 - S2JDBC - サービスの作り方
- 流れるようにSQLっぽくO-RマッピングできるS2JDBC (2-3) - @IT
- S2AbstractService (S2 Tiger 2.4.41 API)
以下にJdbcManagerクラスの代わりにServiceクラスを使った例を示します。
examples.logicパッケージにロジッククラスDITest2Logicを作成して、以下のようにコードを記述します。
package examples.logic; import java.util.List; import javax.annotation.Resource; import org.seasar.framework.beans.util.BeanMap; import org.seasar.framework.beans.util.Beans; import examples.entity.Employee; import examples.service.EmployeeService; public class DITest2Logic { @Resource public EmployeeService employeeService; public void executeService() { System.out.println("executeService"); ListempItems = employeeService.findAll(); for ( Employee e : empItems) { BeanMap beanMap=Beans.createAndCopy(BeanMap.class, e).execute(); for (String str : beanMap.keySet()) { System.out.print("\t" + str + ": " + beanMap.get(str)); } System.out.println(); } } }
パッケージexamplesにjavaアプリケーションとして動作させる新規クラスDITest2Mainを作成して、 以下のようにDITest2Logicに処理をゆだねるコードを記述します。
package examples; import org.seasar.framework.container.SingletonS2Container; import org.seasar.framework.container.factory.SingletonS2ContainerFactory; import examples.logic.DITest2Logic; public class DITest2Main { public static void main(String[] args) { SingletonS2ContainerFactory.init(); DITest2Logic dITest2Logic=SingletonS2Container.getComponent(DITest2Logic.class); dITest2Logic.executeService(); } }
SAStrutsでS2JDBC
SAStrutsの場合はActionを含むほとんどのクラスが、Resourceアノテーションを指定する事によりインスタンスを生成できるのでJdbcManagerやService クラスを定義することによりデータベースにアクセスする事ができます。
また、 S2Containerの説明にあるようにSingletonS2ContainerFactory.init()が自動的に呼び出されるため、明示的に呼び出す必要はありません。
以下にActionよりService クラスを使用した例としてS2JDBC-はじめのいっぽのScaffoldアプリケーションの作成で自動生成したDeptAction.javaのコードの抜粋を示す。
public class DeptAction { public List<Dept> deptItems; @ActionForm @Resource protected DeptForm deptForm; @Resource protected DeptService deptService; @Execute(validator = false) public String index() { deptItems = deptService.findAll(); return "list.jsp"; }
また、以下のコードでJdbcManagerやService クラスのインスタンスを取得する事もできる。
JdbcManager jdbcManager=SingletonS2Container.getComponent("jdbcManager"); DeptService deptService=SingletonS2Container.getComponent("deptService");
Enum クラスを利用する
s2jdbc-tutorialのセットアップとMySQLでjobTypeプロパティの型をJobTypeに変更した事を思い出して下さい。
/s2jdbc-tutorial/src/main/java/examples/entity/JobType.javaと/s2jdbc-tutorial/src/test/java/examples/InsertTest.javaの42行目のコートを参照して下さい。
emp.jobType = JobType.ANALYST;
jobTypeプロパティの型をJobTypeに変更する事でjavaのenum型の機能を利用して可読性の高いコードで記述できるようになっています。
Enum クラスの利用例については以下のリンクを参照して下さい。