かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

お次はs2dao

使い方を思い出してきたので次はs2dao
これは、本当に久しく触ってないなぁ。
順調に出来るだろうか??


とりあえず、データベースが無いとはじまらない!!
マシンの中に入ってるDBは…

う〜ん
H2にするか。

データの用意

jdbc:h2:tcp://localhost:9092/sample/dataにありがちなテーブルを切ってみた

create table Employee (
  id int primary key,
  name varchar(50),
  dept_id int not null);

create table Department (
  id int primary key,
  name varchar(50));

alter table Employee add
constraint FK_Employee_Department
foreign key (dept_id) references Department(id);

ここにありがちなデータを突っ込む!

insert into Department ( id , name )
values
  (1, '総務'),
  (2, '人事');

insert into Employee (id, name , dept_id )
values
  (1, '太郎', 1),
  (2, '二郎', 1),
  (3, '三郎', 2);

j2ee.diconの用意

s2daoをダウンロードして解凍したものの中にj2ee.diconがあるのでそれをコピーしていらない部分を消す!
結果こんな感じに

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components namespace="j2ee">
	<component name="transactionManager"
		class="org.seasar.extension.jta.TransactionManagerImpl"/>
	<component name="requiredTx"
		class="org.seasar.extension.tx.RequiredInterceptor"/>
	<component name="requiresNewTx"
		class="org.seasar.extension.tx.RequiresNewInterceptor"/>
	<component name="mandatoryTx"
		class="org.seasar.extension.tx.MandatoryInterceptor"/>
	<component name="notSupportedTx"
		class="org.seasar.extension.tx.NotSupportedInterceptor"/>
		
	<component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
	<component class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>

	<component name="xaDataSource"
		class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
		<property name="driverClassName">
			"org.h2.Driver"
		</property>
		<property name="URL">
			"jdbc:h2:tcp://localhost:9092/sample/data"
		</property>
		<property name="user">"sa"</property>
		<property name="password">""</property>
	</component>
	
	<component name="connectionPool"
		class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
		<property name="timeout">600</property>
		<property name="maxPoolSize">10</property>
		<property name="allowLocalTx">true</property>
		<destroyMethod name="close"/>
	</component>
	<component name="dataSource"
		class="org.seasar.extension.dbcp.impl.DataSourceImpl"/>

</components>

xaDataSourceの所をH2用に書き換えてあります。

Beanを用意

データベースのデータを入れるためのbeanを作ります。
ここらへんDBのスキーマから自動生成したいところですね。


Employee.java

package org.sample.s2.bean;

import org.seasar.dao.annotation.tiger.Bean;
import org.seasar.dao.annotation.tiger.Relation;

@Bean
public class Employee {
	private int id;

	private String name;

	private Department department;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Relation(relationNo=0, relationKey="dept_id:id")
	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}

}

クラスの定義のところのBeanアノテーションと、getDepartmentの所のRelationアノテーションくらいがポイント。
後は、DBのカラム名とかとあわせてあるので特に何もしなくてOK

続いて、Department。これはBeanアノテーションつけるだけ。


Department.java

package org.sample.s2.bean;

import org.seasar.dao.annotation.tiger.Bean;

@Bean
public class Department {
	private int id;

	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}


よっしゃ次!!
DAOを用意しないと始まらない。
めんどくさいので、EmployeeDaoだけを用意する。必要最低限のメソッドのみ定義。


EmployeeDao.java

package org.sample.s2.dao;

import java.util.List;

import org.sample.s2.bean.Employee;
import org.seasar.dao.annotation.tiger.S2Dao;

@S2Dao(bean=Employee.class)
public interface EmployeeDao {
	Employee get(int id);
	List<Employee> selectAll();
	void update(Employee emp);
	void delete(Employee emp);
	void insert(Employee emp);
}

S2Daoアノテーションで、先ほど作ったbeanと関連付けをしてあげる。
これでOK


最後に、設定ファイルを書けば準備完了!!
これも自動登録機能を使ってやります。
app.diconに以下の2つのcomponentの定義を足す。


app.dicon

<!-- dao.interceptor -->
<include path="dao.dicon" />

<!-- Daoの自動登録 -->
<component class="org.seasar.framework.container.autoregister.ComponentAutoRegister">
	<initMethod name="addReferenceClass">
		<arg>@org.sample.s2.Main@class</arg>
	</initMethod>
	<initMethod name="addClassPattern">
		<arg>"org.sample.s2.dao"</arg>
		<arg>".*Dao"</arg>
	</initMethod>
</component>

<!-- dao.interceptorをDaoに適用 -->
<component class="org.seasar.framework.container.autoregister.AspectAutoRegister" >
	<property name="interceptor">
		dao.interceptor
	</property>
	<initMethod name="addClassPattern" >
		<arg>"org.sample.s2.dao"</arg>
		<arg>".*Dao"</arg>
	</initMethod>
</component>


ふぅ。長かった。
後はmainメソッドでお試しだ!!

package org.sample.s2;

import org.sample.s2.bean.Employee;
import org.sample.s2.component.Greeter;
import org.sample.s2.dao.EmployeeDao;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

public class Main {
	private static final String CONFIG_PATH = "app.dicon";

	public static void main(String[] args) {
		SingletonS2ContainerFactory.setConfigPath(CONFIG_PATH);
		SingletonS2ContainerFactory.init();
		try {
			new Main().execute();
		} finally {
			SingletonS2ContainerFactory.destroy();
		}
	}

	private void execute() {
		S2Container con = SingletonS2ContainerFactory.getContainer();

		// Dao
		EmployeeDao dao = (EmployeeDao) con.getComponent(EmployeeDao.class);
		Employee emp = dao.get(1);
		System.out.printf("id = %d, name = %s, department.name = %s\n", emp
				.getId(), emp.getName(), emp.getDepartment().getName());
	}
}


これを実行すると

2006-11-12 20:48:05,843 DEBUG ConnectionPoolImpl - 物理的なコネクションを取得しました
2006-11-12 20:48:05,843 DEBUG DataSourceImpl - 論理的なコネクションを取得しました
2006-11-12 20:48:06,109 DEBUG ConnectionWrapperImpl - 論理的なコネクションを閉じました
2006-11-12 20:48:06,140 DEBUG BasicSelectHandler - SELECT Employee.id, Employee.name, department.id AS id_0, department.name AS name_0 FROM Employee LEFT OUTER JOIN Department department ON Employee.dept_id = department.id
2006-11-12 20:48:06,140 DEBUG DataSourceImpl - 論理的なコネクションを取得しました
2006-11-12 20:48:06,156 DEBUG ConnectionWrapperImpl - 論理的なコネクションを閉じました
id = 1, name = 太郎, department.name = 総務
2006-11-12 20:48:06,171 DEBUG ConnectionWrapperImpl - 物理的なコネクションを閉じました


お〜っちゃんと取れてる!
ラクチンだけどやっぱ自動生成したいね。
CodeGenっていうのがあったけど使えるのかな?後で見てみよう