81.Daoの作り方サンプル
(通常の方法:SpringJDBC)
概要
Spring トランザクションはかなり強力で便利な機能です。
しかし、使用に関してはSpringトランザクションが働くようにDaoを作る必要があります。
でも、それはとても簡単です。
ここではHibernateやIBatisなどのO/Rマッピングを使用しないような、簡単なやり方を見て行きます。
しかしO/Rマッピングを使用する場合でもやり方はほぼ同じで、extendsするクラスが変わるぐらいです。
【注意事項 (2012.05.20追記)】
SimpleJdbcTemplateというクラスが存在していますが、Spring3.1以降ではdeprecatedされています。
JdbcTemplateを使うようにしましょう。
この記事ではSimpleJdbcTemplate で記事を書いてしまいましたが、以下のように読み替えてください。
?のプレースフォルダを使いたい場合 ⇒ JdbcTemplate
:name の名前プレースフォルダを使いたい場合 ⇒ NamedParameterJdbcTemplate
目標
まずは、ゴールを示しておきます。
会員の検索、更新などをするDaoを作ります。
ここではSpringJDBCを使用します。
厳密に言えばSpringJDBCはO/Rマッピングということになるかとは思いますが、普通のJDBCとしても使えるため
O/Rマッピングを使用しない場合というタイトルにしています。
サンプル
【Daoのサンプル】
public class MemberDaoTest extends JdbcDaoSupport {
//JDBCテンプレート
protected SimpleJdbcTemplate simpleTemplate;
//会員情報マッピング(selectのためのマッピングです)
protected class MemberRowMapper implements ParameterizedRowMapper<Member> {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member mem = new Member();
mem.setId(rs.getString("id"));
mem.setName(rs.getString("name"));
mem.setAge(rs.getInt("age"));
return mem;
}
}
//初期化
protected void initDao()
{
this.simpleTemplate = new SimpleJdbcTemplate(getDataSource());
}
//selectサンプル
public List<Member> findMember(MemberSearchKey searchKey) {
//
String sql = "select * from t_member ";
String where = "";
if(searchKey.getId() != null){
where += " and id = :id";
}
if(searchKey.getName() != null){
where += " and name = :name";
}
if(searchKey.getAgeFrom() != -1){
where += " and age >= :ageFrom";
}
if(searchKey.getAgeTo() != -1){
where += " and age >= :ageTo";
}
if(!where.isEmpty()){
sql += " where " + where.substring(4);
}
//会員リスト
List<Member> memberList = this.simpleTemplate.query(
sql, new MemberRowMapper(), new BeanPropertySqlParameterSource(searchKey)
);
return memberList;
}
//更新サンプル(insertも同じ)
public void updateMember(Member member){
Assert.hasText(member.getId());
//SQL
String sql = "update member set name = :name, age = :age where id = :id";
this.simpleTemplate.update(sql, new BeanPropertySqlParameterSource(member));
}
}
メインのDaoサンプルクラスです。
ポイントは、JdbcDaoSupportを継承することです。
これによりSpringトランザクションを使用できるようになります。
DaoSupportは自作することもできますが、用意されたものを使用するのが良いでしょう。
<JdbcTemplate>
プレースフォルダを使用できるSpringJDBCのクラスです。
プレースフォルダは2種類が使用可能です。
・"?" を利用したJDBCでよく使用するプレースフォルダ(JdbcTemplate)
・":name"のように名前を使用するプレースフォルダ(NamedParameterJdbcTemplate )
このサンプルではせっかくなので名前を使用するプレースフォルダを使いました。
<BeanPropertySqlParameterSource>
以下、再掲:
List<Member> memberList = this.simpleTemplate.query(
sql, new MemberRowMapper(), new BeanPropertySqlParameterSource(searchKey)
);
query()の3つ目の引数は、Mapか、SqlParameterSourceのいずれかです。
ここでは、POJOをSqlParameterSourceに変換するクラスBeanPropertySqlParameterSourceを使用しました。
もし、"?"のプレースフォルダを使用したい場合は、可変長引数に値を順番に設定していきます。
<MemberRowMapper>
MemberRowMapperは、select結果のResultSetをMemberに変換するクラスで、上記で自作しています。
もし、Mapperを作りたくない場合はMapとして受け取ることもできます。以下に例を示します。
List<Map<String, Object>> memberList = this.simpleTemplate.queryForList(
sql, new BeanPropertySqlParameterSource(searchKey)
);
【Memberクラス】
public class Member {
private String id;
private String name;
private int age;
//getter / setterを以下に書く(ここでは省略)
:
}
【MemberSearchKeyクラス (検索のキーワードクラス)】
public class MemberSearchKey {
private String id;
private String name;
private int ageFrom=-1;
private int ageTo=-1;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAgeFrom() {
return ageFrom;
}
public void setAgeFrom(int ageFrom) {
this.ageFrom = ageFrom;
}
public int getAgeTo() {
return ageTo;
}
public void setAgeTo(int ageTo) {
this.ageTo = ageTo;
}
}
【Spring Context ファイル (宣言的トランザクションの記事を参照)】
<!-- Data Source (例えばPostgres)-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost/XXXX" />
<property name="username" value="XXX" />
<property name="password" value="XXX" />
</bean>
<!-- DAO -->
<bean id="memberDaoTest" class="dao.MemberDaoTest">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- トランザクション管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 宣言的トランザクションの織り込み -->
<aop:config proxy-target-class="false">
<aop:advisor pointcut="execution(* business.service.*(..))" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" >
<tx:attributes>
<tx:method name="find*" read-only="true" />
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
宣言的トランザクションの記事と同じです。ほぼ再掲です。
ここでは説明は省略します。
これで、トランザクション制御をするときのDaoの作り方がわかったでしょうか?
注目すべきは、Daoのメソッド内に、SQL例外の try~catchがなくなっていることです。
地味ですが、いざとなると以外に楽です。
さらに詳細な内容については、以下の記事をご覧ください。
Created Date: 2010/01/12