|
Spring Frameworkのとっつきです。
ここから、spring-framework-2.0-M3.zipをダウンロードして展開します。
dist/spring.jarをコピーして、CLASSPATHの通っている場所に配置します。
また、Springはロギング機構としてApache Log4Jを使っているので、
log4j-*.jarとcommons-logging-*.jarが必要です。
また、データベース接続の際のデータソースのファクトリーとして、
一般にJakarta Commons DBCPを使うので、
Jakarta Commons DBCP、Pool、BeanUtilsの各jarファイルも用意するとよいでしょう。
(Jakarta Commons Collectionsは最近不要になったようです)
また、「aopalliance.zip」というjarファイルもAOP APIを利用する際は必要と各所に書かれていますが、
Spring 2.0のJARには同梱されていませんでした。??
Springでは、DIに関与するBeanの定義をXML文書で定義します。
サンプルに、以下のような文書を "beans1.xml" という名前で作ります。
Springでは一般に、XML文書のファイル名は自由に決められます。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="queryFindAll" class="test.jdbc.config.QueryConfig" singleton="true">
<property name="description"><value>支店コード表検索(全件)</value></property>
<property name="connectionType"><value>JNDI</value></property>
<property name="database"><value>jdbc/sadb</value></property>
<property name="query">
<value>
SELECT SHITEN_CODE, SHITEN_NAME, AREA_CODE, ADDRESS, EMPLOYEE_NUM
FROM SHITEN
ORDER BY SHITEN_CODE
</value>
</property>
</bean>
<bean id="queryWithAreaCode" class="test.jdbc.config.QueryConfig" singleton="true">
<property name="description"><value>支店コード表検索(地域コードで検索)</value></property>
<property name="connectionType"><value>JNDI</value></property>
<property name="database"><value>jdbc/sadb</value></property>
<property name="query">
<value>
SELECT SHITEN_CODE, SHITEN_NAME, AREA_CODE, ADDRESS, EMPLOYEE_NUM
FROM SHITEN WHERE AREA_CODE = ?
ORDER BY SHITEN_CODE
</value>
</property>
</bean>
</beans>
|
この定義はQueryConfigというBeanクラスの初期値を設定しているものです。
QueryConfigクラスのソースコードは省略しますが、
description, connectionType, database, queryの4つのプロパティを持つBeanクラスです。
singleton=というのは、そのインスタンスをシングルとんとして使いまわすか(true)、
参照のたびに新しいインスタンスを作るのか(false)を指示するもので、
デフォルトはtrue(つまりシングルとん)です。要注意。。
上記の設定ファイルを読んで、2つあるBean定義のうち片方を参照して、
その設定内容を標準出力に表示するサンプルです。
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import test.jdbc.config.QueryConfig;
public class Example1 {
public static void main(String[] args) {
ClassPathResource res = new ClassPathResource("beans1.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
QueryConfig c = (QueryConfig) factory.getBean("queryFindAll");
System.out.println(c.getDescription());
System.out.println(c.getConnectionType());
System.out.println(c.getQuery());
}
}
|
JdbcTemplateを利用したDAOによるデータベース・アクセス |
前の例はDIコンテナとしてのSpringのごくごく簡単な使い方のサンプルでしたが、
今度はデータベースアクセスのフレームワークとしてのSpringの紹介ということで、
DAO(Data Access Object)クラスを作ってデータベースに接続してみます。
先のbeans1.xmlとは別に、beans2.xmlを次のように作ります。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="myDataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>org.hsqldb.jdbcDriver</value></property>
<property name="url"><value>jdbc:hsqldb:hsql://localhost/</value></property>
<property name="username"><value>sa</value></property>
<property name="password"><value></value></property>
</bean>
<bean id="Example2DAO" class="test.beans.Example2DAO">
<property name="dataSource"><ref bean="myDataSource"/></property>
<property name="queryConfig"><ref bean="queryFindAll"/></property>
</bean>
<bean id="Example3DAO" class="test.beans.Example3DAO">
<property name="dataSource"><ref bean="myDataSource"/></property>
<property name="queryConfig"><ref bean="queryWithAreaCode"/></property>
</bean>
</beans>
|
ここで、DataSourceの実装として、Jakarta Commons DBCPの
org.apache.commons.dbcp.BasicDataSource を使っているので、
Jakarta Commons DBCP、Pool、BeanUtilsのJARファイルがCLASSPATHに必要です。
また、そのdriverClassNameとurlから分かるように、
このサンプルはhsqldbのデータベースに接続します。
localhostにサーバープロセスとしてhsqldbを起動しておく必要があります。
また、Example2DAOとExample3DAOの定義には、
プロパティの設定に"ref bean="という新しい書き方が出てきています。
これはその名前をもつBeanインスタンスの参照をプロパティに設定するという指示です。
package test.beans;
import java.util.*;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import ushi.jdbc.config.QueryConfig;
public class Example2DAO {
private DataSource dataSource;
private QueryConfig queryConfig;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setQueryConfig(QueryConfig queryConfig) {
this.queryConfig = queryConfig;
}
public List retrieve() {
final String sql = queryConfig.getQuery();
JdbcTemplate jt = new JdbcTemplate(this.dataSource);
List list = jt.queryForList(sql);
List beanList = new ArrayList();
for (Iterator it = list.iterator(); it.hasNext();) {
Map map = (Map) it.next();
ShitenBean s = createRecordBean(map);
beanList.add(s);
}
return beanList;
}
private ShitenBean createRecordBean(Map map) {
ShitenBean s = new ShitenBean();
s.setShitenCode((String) map.get("SHITEN_CODE"));
s.setShitenName((String) map.get("SHITEN_NAME"));
s.setAreaCode(map.get("AREA_CODE").toString());
s.setAddress((String) map.get("ADDRESS"));
s.setEmployeeNum(map.get("EMPLOYEE_NUM").toString());
return s;
}
}
|
これは低レベルの実装であるJdbcTemplateをそのまま使ったDAOクラスです。
先のbean定義の通り、Example2DAOはdataSourceとqueryConfigという2つのプロパティを持ちます。
データベース接続情報であるdataSourceと、
queryConfigが持っているSQL文を渡すと、
(ここからJdbcTemplateはいろいろな方法でデータベースアクセスができるのですが)
上記の例では queryForList という、各行のデータが列名をキーとするMapであるリストを返すAPIを使っています。
それで1行ずつMapをShitenBean(ソースは省略。サンプルの通りの5つのプロパティを持つ単純なBean)
にマッピングして、そのリストに変換しています。
package test.beans;
import java.util.Iterator;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Example2 {
public static void main(String[] args) {
String[] files = {"beans1.xml", "beans2.xml"};
ApplicationContext context = new ClassPathXmlApplicationContext(files);
Example2DAO d = (Example2DAO) context.getBean("Example2DAO");
List beanList = d.retrieve();
for (Iterator iter = beanList.iterator(); iter.hasNext();) {
ShitenBean s = (ShitenBean) iter.next();
System.out.println(s.getShitenCode() + "\t" + s.getShitenName());
}
}
}
|
そのDAOクラスを利用したアプリケーションmainのサンプルです。
今度はXmlBeanFactoryの代わりにClassPathXmlApplicationContextというクラスを使っています。
ApplicationContextはBeanFactoryのより強まった拡張クラスだそーなので、
以後こちらを使うことにします。
それで例のように、XML定義ファイルは配列にして複数読むことができます。
package test.beans;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.object.MappingSqlQuery;
import ushi.jdbc.config.QueryConfig;
public class Example2DAO extends JdbcDaoSupport {
private QueryConfig queryConfig;
private class Finder extends MappingSqlQuery {
public Finder(){
super(getDataSource(), queryConfig.getQuery());
}
protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
ShitenBean s = new ShitenBean();
s.setShitenCode(rs.getString("SHITEN_CODE"));
s.setShitenName(rs.getString("SHITEN_NAME"));
s.setAreaCode(rs.getString("AREA_CODE"));
s.setAddress(rs.getString("ADDRESS"));
s.setEmployeeNum(rs.getString("EMPLOYEE_NUM"));
return s;
}
}
private Finder finder;
public void setQueryConfig(QueryConfig queryConfig) {
this.queryConfig = queryConfig;
}
protected void initDao() throws Exception {
System.out.println("initDAO is called.");
this.finder = new Finder();
}
public List retrieve() {
return this.finder.execute();
}
}
|
再びDAOクラスに戻って、今度はJdbcTemplateではなく、
MappingSqlQueryという、
少し上位レベルの実装を拡張して利用しています。
これは、SELECT文の発行に特化したクラスで、結果集合の各行を、
自分でIteratorで回す必要がありません。mapRow()メソッドを自分で実装するのですが、
その定義は1行をResultSetからBeanオブジェクトにマッピングする方法を書いているだけです。
後はMappingSqlQueryのexecute()を実行すれば、
既に実装済みの部分がSQL発行〜結果集合のループを自分で行って、Beanのリストを返してきます。
(first uploaded 2006/04/29 last updated 2006/04/29, URANO398)
|