かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

お次は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っていうのがあったけど使えるのかな?後で見てみよう