2015年3月7日土曜日

domaを試してみる


■domaの特徴など

doma公式サイト

SQLファイルからSQLを読み込んで使える
SQLに必要なパラメータはコメントとして書くので
実行可能なSQLを書いておくことができる

マッピングファイルを書かなくてもいい
DBの接続情報などは設定クラスに書く
ファイルに書くことができるのかは調べてない

Daoの実装クラスなどaptを使ってコンパイル時に自動生成
実行時に動的生成するよりもレスポンスがいいとの事
そんなに変更のないクラスを実行時に毎回動的生成することに疑問を感じていたので
これはいいかも
aptについては別途調べる予定

日本語の説明が豊富
実にありがたい


■環境等

doma 1.38
sqlite 3.8.7
java   1.7

サンプル
本家のクイックスタートを元にして
sqlite用に作ります。

●aptの設定など

aptを使ってビルド時にソースコードの生成をするので
eclipseの設定をします

1.プロジェクトのプロパティ > Javaコンパイラー > 注釈処理
   注釈処理を使用可能にするにチェックを入れる













2.ファクトリーパスにdomaのjarを指定する













3.ビルドパスの設定も忘れずに














●作成するファイル

設定クラス
エンティティ
Dao
SQLファイル

●設定クラス

利用するDBの情報と接続文字列を指定します。
この例では sqlite を使うので
DialectにSqliteDialect
DataSourceのurlに jdbc:sqlite:sample.db
を指定しています

Dialectには以下が使えます
データベース 方言クラスの名前
DB2 org.seasar.doma.jdbc.dialect.Db2Dialect
H2 Database Engine 1.2.126 org.seasar.doma.jdbc.dialect.H212126Dialect
H2 Database Engine org.seasar.doma.jdbc.dialect.H2Dialect
HSQLDB org.seasar.doma.jdbc.dialect.HsqldbDialect
Microsoft SQL Server 2008 org.seasar.doma.jdbc.dialect.Mssql2008Dialect
Microsoft SQL Server org.seasar.doma.jdbc.dialect.MssqlDialect
MySQL org.seasar.doma.jdbc.dialect.MySqlDialect
Oracle Database org.seasar.doma.jdbc.dialect.OracleDialect
PostgreSQL org.seasar.doma.jdbc.dialect.PostgresDialect
SQLite org.seasar.doma.jdbc.dialect.SqliteDialect


AppConfig.java
package sample.doma;

import javax.sql.DataSource;

import org.seasar.doma.jdbc.DomaAbstractConfig;
import org.seasar.doma.jdbc.SimpleDataSource;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.SqliteDialect;
import org.seasar.doma.jdbc.tx.LocalTransaction;
import org.seasar.doma.jdbc.tx.LocalTransactionalDataSource;

public class AppConfig extends DomaAbstractConfig {
    
    protected static final LocalTransactionalDataSource
                               dataSource = createDataSource();
    
    protected static final Dialect dialect = new SqliteDialect();
    
    @Override
    public DataSource getDataSource() {
        
        return dataSource;
    }
    
    @Override
    public Dialect getDialect() {
        
        return dialect;
    }
    
    protected static LocalTransactionalDataSource createDataSource() {
        
        SimpleDataSource dataSource = new SimpleDataSource();
        dataSource.setUrl("jdbc:sqlite:sample.db");
        
        return new LocalTransactionalDataSource(dataSource);
    }
    
    public static LocalTransaction getLocalTransaction() {
        
        return dataSource.getLocalTransaction(defaultJdbcLogger);
    }
    
}

●エンティティクラス

SQLの結果に対応するクラスを作ります。
サンプルでは単一テーブルを検索するので
テーブルと一致するクラスを作ります
本家のサンプルはhiredateがDate型ですが
sqliteにはDateは無いのでStringにしてあります
コンパイル時に
.apt_generated\sample\doma\_Employee.java
が自動生成されます
package sample.doma;

import org.seasar.doma.Entity;
import org.seasar.doma.Id;
import org.seasar.doma.Version;
import org.seasar.doma.jdbc.entity.NamingType;

@Entity(naming = NamingType.SNAKE_UPPER_CASE)
public class Employee {
 
    @Id
    public Integer employeeId;
 
    public String employeeName;
 
    // public Date hiredate;
    public String hiredate;
 
    public Integer salary;
 
    @Version
    public Integer versionNo;
}


●Dao

一覧の取得や更新、削除などは、このクラスを使います
selectをするSQLを使うメソッドには@Selectアノテーションを付けます
更新をするメソッドは@Update
@Scriptというのがあって、これはパラメータを渡せない代わりに
create table してデータを insert するようなSQLファイルを書いておいて
これを実行できます。
各メソッド名と同じ名前のSQLファイルを用意します。
パラメーターがある場合はSQLファイルにパラメーターを書かないとエラーになります。
コンパイル時に
.apt_generated\sample\doma\EmployeeDaoImpl.java
が自動生成されます

EmployeeDao.java
package sample.doma;

import java.util.List;

import org.seasar.doma.Dao;
import org.seasar.doma.Script;
import org.seasar.doma.Select;
import org.seasar.doma.Update;

@Dao(config = AppConfig.class)
public interface EmployeeDao {
 
    @Select
    int countTable(String tableName);
 
    @Script
    void createTable();
 
    @Select
    Employee selectById(Integer employeeId);
 
    @Update
    int update(Employee employee);
 
    @Select
    List selectAll();
}




●SQLファイル

・拡張子sqlのファイルにSQLを書きます。
 パラメータはコメントとして書きます。
 
 例えばこんな風に書きます。
 select * from EMPLOYEE where EMPLOYEE_ID = /* employeeId */99
 この場合/* employeeId */99 の部分がemployeeIdというパラメータで書き換えられます
 Daoの説明を見るともう少し分かるかも


・SQLファイルの配置
 META-INF以下に対象Daoのパッケージと同じフォルダ構成でファイル名はメソッド名同じにする

 srcにあるsample.doma.EmployeeDaoのselectAll()の場合
 src\META-INF\sample\doma\EmployeeDao\selectAll.sql

実際のファイルはDaoに書いたメソッドの分だけ作成します。

countTable.sql
select count(*) from sqlite_master where type = 'table' and tbl_name = /* tableName */'hoge'

createTable.script
/*
 * テーブル定義(SQLステートメント)
 */
create table EMPLOYEE (
    EMPLOYEE_ID integer,
    EMPLOYEE_NAME text,
    HIREDATE text,
    SALARY integer,
    VERSION_NO integer
);

/*
 * データの追加(SQLステートメント)
 */
insert into EMPLOYEE values(1, 'SMITH', '1980-12-17', 800, 1);
insert into EMPLOYEE values(2, 'ALLEN', '1981-02-20', 1600, 1);
insert into EMPLOYEE values(3, 'WARD', '1981-02-22', 1250, 1);

selectById.sql
select * from EMPLOYEE where EMPLOYEE_ID = /* employeeId */99

updateは書かなくてもOKみたい

selectAll.sql
select * from EMPLOYEE

最後にこれらを確認するクラスを作成します。

Main.java
import java.util.List;

import org.seasar.doma.jdbc.tx.LocalTransaction;

import sample.doma.AppConfig;
import sample.doma.Employee;
import sample.doma.EmployeeDao;
import sample.doma.EmployeeDaoImpl;

public class Main {
    
    public static void main(String[] args) {
        
        LocalTransaction tx = AppConfig.getLocalTransaction();
        
        try {
            
            tx.begin();
            
            EmployeeDao dao = new EmployeeDaoImpl();
            
            // テーブル情報を検索して存在しなければ作成します
            int tableCount = dao.countTable("EMPLOYEE");
            if (tableCount == 0) {
                dao.createTable();
            }
            
            // Employeeから1レコード分取得します
            Employee employee = dao.selectById(1);
            System.out.println(employee.employeeName);
            
            Integer salary = employee.salary;
            System.out.println(salary);
            
            // 値を変えて
            employee.salary = salary + 50;
            // 更新します
            dao.update(employee);
            
            // 一覧取得
            List list = dao.selectAll();
            for (Employee emp : list) {
                
                System.out.print(emp.employeeId);
                System.out.print(" : ");
                System.out.print(emp.employeeName);
                System.out.print(" : ");
                System.out.print(emp.hiredate);
                System.out.print(" : ");
                System.out.println(emp.salary);
            }
            
        } catch (Exception e) {
            
            tx.rollback();
            
        } finally {
            
            tx.commit();
            
        }
    }
}


ソース一式ダウンロード



0 件のコメント:

コメントを投稿