isami100のSwingin' Seasar日記

2004-06-21

データベースを使うDAOの作成

S2DAOがリリースされるまで、とりあえずS2JDBCを使ったDAOを作成します。

JdbcUserDao.java
package s2study.app.login.dao;
import org.seasar.extension.jdbc.SelectHandler;
import s2study.app.entity.User;
import s2study.app.login.service.UserDao;

public class JdbcUserDao implements UserDao {
    private SelectHandler _selectHandlar;

    public JdbcUserDao(SelectHandler selectHandler) {
        setSelectHandler(selectHandler);
    }
    public User getUser(String userId) {
        return (User) _selectHandlar.execute(new Object[] { userId });
    }
    public void setSelectHandler(final SelectHandler selectHandlar) {
        _selectHandlar = selectHandlar;
    }
}

以前作ったDummyUserDaoもs2study.app.login.daoパッケージに移動し、LoginService.dicon から Dao 記述部分を切り取って LoginDao.dicon に移動します。

LoginDao.dicon


"http://www.seasar.org/dtd/components.dtd">
<components namespace="LoginDao">
    <!-- Handler -->
    <component name="userSelectHandler" class="org.seasar.extension.jdbc.impl.BasicSelectHandler">
        <property name="sql">
            "SELECT USERID, PASSWD, USERNAME FROM USER WHERE USERID = ?"
        </property>
        <property name="resultSetHandler">
            <component class="org.seasar.extension.jdbc.impl.BeanResultSetHandler">
                <arg>@s2study.app.entity.User@class</arg>
            </component>
        </property>
    </component>
    

    <!-- Dao -->
    <!-- Dummy
    <component name="userDao" class="s2study.app.login.dao.DummyUserDao"/>
     -->
    <!-- S2JDBC     -->
    <component name="userDao" class="s2study.app.login.dao.JdbcUserDao">
        <arg>userSelectHandler</arg>
    </component>

</components>

app.diconにはLoginDao.diconとj2ee.diconを追加でincludeします。

HSQLDBの設定

seasar2プロジェクトのdataディレクトリにあるserver.propertiesで次のように設定し、bin/runHsqldb.bat を起動。

server.properties
server.database=s2study

次にbin/runHsqldbManager.batを起動してHSQLDBのDatabaseManagerを使ってテーブルの作成とデータの作成を行います。*1

SHUTDOWNすると次のようなscriptファイルが生成されました。(自動的に作られます)

s2study.script
CREATE TABLE USER(USERID CHAR(5) NOT NULL PRIMARY KEY,PASSWD BINARY(40),USERNAME CHAR(40))
GRANT ALL ON CLASS "org.hsqldb.Library" TO PUBLIC
GRANT ALL ON CLASS "java.lang.Math" TO PUBLIC
CREATE USER SA PASSWORD "" ADMIN
CREATE ALIAS DAYNAME FOR "org.hsqldb.Library.dayname"
       :(省略)
CREATE ALIAS REPLACE FOR "org.hsqldb.Library.replace"
INSERT INTO USER VALUES('00001','3030303031','Okita')
INSERT INTO USER VALUES('00002','3030303032','Nagakura')
INSERT INTO USER VALUES('00003','3030303033','Saito')
INSERT INTO USER VALUES('00004','3030303034','Matsubara')
INSERT INTO USER VALUES('00005','3030303035','Takeda')
INSERT INTO USER VALUES('00006','3030303036','Inoue')
INSERT INTO USER VALUES('00007','3030303037','Tani')
INSERT INTO USER VALUES('00008','3030303038','Todo')
INSERT INTO USER VALUES('00009','3030303039','Suzuki')
INSERT INTO USER VALUES('00010','3030303130','Harada')

テストの作成

http://homepage3.nifty.com/seasar/S2Unit.html のDb2Excelの例にならい、Db2Excel.diconを次のように設定してExcelファイルを生成。

Db2Excel.dicon


"http://www.seasar.org/dtd/components.dtd">
<components>
    <include path="j2ee.dicon"/>
    <component class="org.seasar.extension.dataset.impl.SqlReader">
    <initMethod>#self.addSql("SELECT * FROM USER", "user")</initMethod>
    </component>
    <component class="org.seasar.extension.dataset.impl.XlsWriter" instance="prototype">
    <arg>"../../s2study/src/test/s2study/app/login/dao/getUserPrepare.xls"</arg>
    </component>
</components>

Eclipseで最新表示し、生成されたgetUserPrepare.xlsをシステムエディタで開くと、ちゃんとテストデータがExcelに展開されていました。感動。

次に、ユーザID='00001'のレコード以外を削除して、getUserResult.xlsに別名保存。テストデータが揃ったので、今度はテストを作成。

JdbcUserDaoTest.java
package test.s2study.app.login.dao;
import java.util.Arrays;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.seasar.extension.dataset.DataSet;
import org.seasar.extension.dataset.DataTable;
import org.seasar.extension.dataset.impl.DataTableImpl;
import org.seasar.extension.dataset.types.ColumnTypes;
import org.seasar.extension.unit.S2TestCase;
import s2study.app.entity.User;
import s2study.app.login.service.UserDao;

public class JdbcUserDaoTest extends S2TestCase {
    private UserDao dao_;

    public JdbcUserDaoTest(String name) {
        super(name);
    }
    protected void setUp() throws Exception {
        include("j2ee.dicon");
        include("JdbcUserDaoTest.dicon");
    }
    protected void tearDown() throws Exception {
    }
    public static Test suite() {
        return new TestSuite(JdbcUserDaoTest.class);
    }
    public static void main(String[] args) {
        junit.textui.TestRunner.run(suite());
    }
    public void testGetUserTx() throws Exception {
        readXlsReplaceDb("getUserPrepare.xls");
        User user = dao_.getUser("00001");
        DataTable result = new DataTableImpl("user");
        result.setupColumns(User.class);
        result.copyFrom(user);
        DataSet dataSet = readXls("getUserResult.xls");
        DataTable expect = dataSet.getTable("user");
        //assertEquals("1", dataSet.getTable("user"), table);

        assertEquals("1", expect.getRowSize(), result.getRowSize());
        for (int i = 0; i < result.getRowSize(); i++) {
            for (int j = 0; j < result.getColumnSize(); j++) {
                Object expectValue = expect.getRow(i).getValue(j);
                Object resultValue = result.getRow(i).getValue(j);

                if (result.getColumnType(j).equals(ColumnTypes.BINARY)) {
                    assertTrue(
                        i + ":" + result.getColumnName(j) + ":",
                        Arrays.equals(
                            (byte[]) expectValue,
                            (byte[]) resultValue));
                }
                else {
                    assertEquals(
                        i + ":" + result.getColumnName(j) + ":",
                        expectValue,
                        resultValue);
                }
            }
        }
    }
}

DataTable同士の比較だと、配列の場合にインスタンス比較で判定が行われるようなので、配列要素の比較を行うようにしてます。今回の例のようにbyte[]などを使っていなければ、DataTable同士の比較でOKだと思います。

JdbcUserDaoTest.dicon


"http://www.seasar.org/dtd/components.dtd">
<components namespace="JdbcUserDaoTest">
    <!-- Handler -->
    <component name="userSelectHandler" class="org.seasar.extension.jdbc.impl.BasicSelectHandler">
        <property name="sql">
            "SELECT USERID, PASSWD, USERNAME FROM USER WHERE USERID = ?"
        </property>
        <property name="resultSetHandler">
            <component class="org.seasar.extension.jdbc.impl.BeanResultSetHandler">
                <arg>@s2study.app.entity.User@class</arg>
            </component>
        </property>
    </component>

    <!-- Dao -->
    <!-- S2JDBC     -->
    <component name="userDao" class="s2study.app.login.dao.JdbcUserDao">
        <arg>userSelectHandler</arg>
    </component>
</components>

と、テスト用にdiconファイルを分けてみたけど、クエリが埋まっているので、本当はLoginDao.diconを使ったほうがよかったかも。

JdbcUserDaoTest 実行結果
.DEBUG 2004-06-21 18:08:00,529 [main] トランザクションを開始しました
DEBUG 2004-06-21 18:08:00,998 [main] 物理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,060 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,107 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,107 [main] DELETE FROM user WHERE USERID = '00001'
DEBUG 2004-06-21 18:08:01,107 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,295 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,295 [main] DELETE FROM user WHERE USERID = '00002'
DEBUG 2004-06-21 18:08:01,295 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,295 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,295 [main] DELETE FROM user WHERE USERID = '00003'
DEBUG 2004-06-21 18:08:01,295 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] DELETE FROM user WHERE USERID = '00004'
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] DELETE FROM user WHERE USERID = '00005'
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] DELETE FROM user WHERE USERID = '00006'
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] DELETE FROM user WHERE USERID = '00007'
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] DELETE FROM user WHERE USERID = '00008'
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] DELETE FROM user WHERE USERID = '00009'
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] DELETE FROM user WHERE USERID = '00010'
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00001', '[B@589e56', 'Okita')
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00002', '[B@3411a', 'Nagakura')
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00003', '[B@a7508a', 'Saito')
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00004', '[B@98cb3d', 'Matsubara')
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00005', '[B@472d48', 'Takeda')
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00006', '[B@edf3f6', 'Inoue')
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,310 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00007', '[B@2bc3f5', 'Tani')
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,310 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,326 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00008', '[B@4e3f41', 'Todo')
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,326 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00009', '[B@1acd47', 'Suzuki')
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,326 [main] INSERT INTO user(USERID, PASSWD, USERNAME) VALUES('00010', '[B@9b04e2', 'Harada')
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,326 [main] SELECT USERID, PASSWD, USERNAME FROM USER WHERE USERID = '00001'
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを取得しました
DEBUG 2004-06-21 18:08:01,326 [main] 論理的なコネクションを閉じました
DEBUG 2004-06-21 18:08:01,341 [main] トランザクションをロールバックしました
DEBUG 2004-06-21 18:08:01,388 [main] 物理的なコネクションを閉じました

Time: 1.578

OK (1 test)

Launcherから起動してログイン画面を動かしてみてもちゃんと動きました^^

*1:PASSWDフィールドはBINARY型なのでASCIIコードの16進表現で指定

higayasuohigayasuo2004/06/25 18:42byte[]の比較は次のバージョンに組み込みます。

isami100isami1002004/06/25 19:34見て頂けてるとは光栄です。応援してます。頑張ってください!

isami100isami1002004/06/25 19:42実は私ひがさんと同じ会社です。昨年某案件でサポート頂いたこともあったりして。^^;

higayasuohigayasuo2004/06/25 19:58まじっすか。ということは、おいらも知ってる方ですね。気軽に飲みにでも誘ってください。(^^;

isami100isami1002004/06/28 13:02実際お会いしたのは2、3回ですが、MLでは何度かお世話になってます(外食案件です)。今後ともよろしくお願いします。m(__)m