Springとっつき

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には同梱されていませんでした。??


Bean定義ファイルを作る

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(つまりシングルとん)です。要注意。。


Javaアプリケーションを作る

上記の設定ファイルを読んで、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のリストを返してきます。

Java kowaza Top

(first uploaded 2006/04/29 last updated 2006/04/29, URANO398)

楽天モバイル[UNLIMITが今なら1円] ECナビでポインと Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!


無料ホームページ 無料のクレジットカード 海外格安航空券 解約手数料0円【あしたでんき】 海外旅行保険が無料! 海外ホテル