seasar2のお勉強7(SAStrutsとS2JDBCやS2Daoとの連携とか）

とりあえず今回のでSeasar2周りはひとまずおしまいの予定です。
タイトル通りSAStrutsとS2JDBCやS2Daoとの連携とかをやります。


#SAStrutsとS2JDBCの連携
といっても超簡単。
まずはサービスクラスを用意。こいつがJdbcManagerを持っていて実際のDBアクセスを行います。

```
package org.s2strutsandjdbc.service;

import java.util.List;

import javax.annotation.Resource;

import org.s2strutsandjdbc.entity.Person;
import org.seasar.extension.jdbc.JdbcManager;

public class PersonService {

	@Resource
	protected JdbcManager jdbcManager;

	public List<Person> getPersonList(Person condition) {
		List<Person> results = jdbcManager.selectBySqlFile(Person.class,
				"org/s2strutsandjdbc/service/Person_Search.sql", condition)
				.getResultList();

		return results;
	}
}
```

でAction側で上記のサービスを@ResourceつけてDIすればすぐ使える。
以下サンプルで一部無関係なimportとかあるけどご容赦ください。
ただしサービス名はxxxxService（今回はpersonService）じゃないと自動でインスタンス登録はされないのでエラーになっちゃいます。
自爆だけど誤字ってpresonServiceとか書いてたら全然反応しなくて苦労しました。serviceとか適当につけても勿論ダメ。


```
package org.s2strutsandjdbc.action;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;


import org.s2strutsandjdbc.dto.PersonListDto;
import org.s2strutsandjdbc.entity.Person;
import org.s2strutsandjdbc.form.PersonForm;
import org.s2strutsandjdbc.service.PersonService;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;
public class PersonAction {

	@Resource
	@ActionForm
	protected PersonForm personForm;

	@Resource
	protected HttpSession session;

	@Resource
	protected PersonService personService;

	@Execute(validator=false, input="input.jsp")
	/** 検索処理 */
	public String getPersonList() {
		List<Person> personList = personService.getPersonList(new Person());
		for (Iterator<Person> iterator = personList.iterator(); iterator.hasNext();) {
			Person person = (Person) iterator.next();
			System.out.print(person.getName());
			System.out.print(person.getBelonging());
			System.out.println(person.getFeature());
		}
		session.setAttribute("personListBean", personList);
		return "list.jsp";
	}
}
```

あと、この例ではgetPersonListメソッドでpersonListBeanという名前でセッションに結果をセットしているんだけど
セッションにセットする際の名前をpersonListにしていたら全然JSP側で検索結果が取れないという事象が発生した。
personListという名前でセッションに入っている値をJSP参照したらlist.jspという値がセットされていたので何か謎の命名規約縛りが生じているのだと思われる。

あとSQLファイルはresources/org/s2strutsandjdbc/service/Person_Search.sqlに以下のような物を置きました。

```
SELECT name, belonging, feature FROM person
/*BEGIN*/
WHERE
    /*IF name != null*/
    name = /*name*/
    /*END*/
    /*IF belonging != null*/
    AND belonging = /*belonging*/
    /*END*/
    /*IF feature != null*/
    AND feature = /*feature*/
    /*END*/
/*END*/
```

これでサービスのgetPersonListメソッドに渡した引数の値ででWHERE句の値をセットするしないを条件分岐してくれる。
（今回の例は空のBean渡してるから面白みないけど）

また全部の変数がNULL（IFを一個も満たさなかった場合）はBEGINからENDのテキストはSQLとして送られないらしい。
なので、WHEREだけついてSQL構文エラーってこともない。
あともしnameとfeature がなくてbelongingだけあったばあいには先頭のANDを取り除いて（ORも取り除くらしい）WHERE belonging = "hoge"みたいにしてくれるらしいから中々便利だと思う。（まあmybatisとかでもあるけど）

あとlist.jspはこんな感じにしました。

```
<%@ page pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
	以下の内容が登録済みです。<br/>
	<c:forEach items="${personListBean}" var="person">
		<c:out value="${person.name}" default="取れなかった"/>
		<c:out value="${person.belonging}" default="取れなかった"/>
		<c:out value="${person.feature}" default="取れなかった"/><br/>
	</c:forEach>
</body>
</html>
```

設定ファイル系はS2JDBCを単独で動かしたときと同様にjdbc.diconで接続先DB情報の設定と、s2jdbc.diconを編集してDB方言の設定をするだけで行ける。

#SAStrutsとS2DAOの連携
こちらも基本的にやることは変わらない。連携したければ@ResourceでDIするだけだ。

まずはDAO

```
package org.s2strutsanddao.dao;

import java.util.List;

import org.s2strutsanddao.entity.Person;

public interface PersonDao {

    public static final Class BEAN = Person.class;

    public String selectPerson_ARGS = "feature";

    // 全件検索用メソッド
    public List<Person> selectPerson(Person condition);

}
```

で、SQL定義ファイル(resources/org/s2strutsanddao/dao/PersonDao_selectPerson_postgre.sqlに置いた）

```
SELECT name, belonging, feature FROM person
/*BEGIN*/
WHERE
    /*IF condition.name != null*/
    name = /*condition.name*/
    /*END*/
    /*IF condition.belonging != null*/
    AND belonging = /*condition.belonging*/
    /*END*/
    /*IF condition.feature != null*/
    AND feature = /*condition.feature*/
    /*END*/
/*END*/
```

やりたいことはS2JDBCでのSQL定義ファイルと同じだけど
condition.nameみたいに引数のオブジェクト名つけなくちゃなのが気持ち面倒。

で、Action。サービスの代わりにpersonDaoをDIしただけ。list.jspの中身はS2JDBCのときと同じ。

```
package org.s2strutsanddao.action;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;


import org.s2strutsanddao.dto.PersonListDto;
import org.s2strutsanddao.entity.Person;
import org.s2strutsanddao.form.PersonForm;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;
import org.s2strutsanddao.dao.PersonDao;
public class PersonAction {

	@Resource
	@ActionForm
	protected PersonForm personForm;

	@Resource
	protected HttpSession session;

	@Resource
	protected PersonDao personDao;

	@Execute(validator=false, input="input.jsp")
	/** 検索処理 */
	public String getPersonList() {

		Person condition = new Person();
		condition.setFeature("長身");
        List<Person> personList = personDao.selectPerson(condition);
		for (Iterator<Person> iterator = personList.iterator(); iterator.hasNext();) {
			Person person = (Person) iterator.next();
			System.out.print(person.getName());
			System.out.print(person.getBelonging());
			System.out.println(person.getFeature());
		}
		session.setAttribute("personListBean", personList);
		return "list.jsp";
	}

}
```

S2JDBCにしてもS2Daoにしても連携はかなり簡単なので中々使いやすいのではと思いました。