About

ドキュメント

プロジェクト文書

Built by Maven

概要

チュートリアルプロジェクトの構成、データベース、主要クラスを説明します。

プロジェクトの構成

チュートリアルのプロジェクトは以下のフォルダで構成されています。

フォルダ 説明
src 設定クラス、Daoインタフェース、エンティティクラス、SQLファイル等のソースフォルダです。 SQLファイルは、Domaの規約に則ってMETA-INFフォルダ以下に配置されます。
test Daoを利用するコードのためのソースフォルダです。 Daoを利用するコードはすべてJUnitのテストクラスとして記述されています。
.apt_generated apt(Annotation Processing Tool)によって生成されたコードを格納するソースフォルダです。 Pckage Explorerビューでは、フィルタリングされるため表示されません(フィルタリングは解除可能です)。 Nivigatorビューで確認できます。
lib このチュートリアルで利用するjarファイルを格納するフォルダです。 JUnit、HSQLDB、Domaのjarが格納されます。 これらのjarはすべてビルドパスに通っていなければいけません。
libsrc このチュートリアルで利用するjarファイルのソースコードを格納するフォルダです。

データベース

このチュートリアルでは、データベースにHSQLDBを利用します。

使用するスキーマの定義は次のとおりです。 1つのシーケンスと1つのテーブルを使用します。

create sequence employee_seq as integer start with 100 increment by 1;
create table employee (
  id integer not null primary key,
  name varchar(255) not null,
  age integer not null,
  salary integer,
  job_type varchar(20),
  hiredate timestamp, 
  department_id integer, 
  version integer not null, 
  insertTimestamp timestamp, 
  updateTimestamp timestamp
);

HSQLDBはMemory-Onlyモードで起動し、テスト用のスキーマとデータは各テストの実行前に作成し、テスト終了後に破棄します。 スキーマとデータの作成と破棄は、共通のテストクラスで行っています。 Javaのコードは、test/tutorial/TutorialTestCase.javaになります。

主要なクラス

チュートリアル中の主要なクラスについて説明します。

設定クラス

設定クラスとは、Domaに関する各種設定を持つクラスです。 このチュートリアルで使用する設定クラスのソースコードは、src/tutorial/AppConfig.javaになります。

このクラスでは、HSQLDBのデータソースの作成とHSQLDBの方言の設定を行っています。 それ以外の設定については親クラスのDomaAbstractConfigのものを利用しています。 設定クラスはDaoインタフェースから利用されます。

package tutorial;

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.HsqldbDialect;

public class AppConfig extends DomaAbstractConfig {

    protected static final DataSource dataSource = createDataSource();

    protected static final Dialect dialect = new HsqldbDialect();

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public Dialect getDialect() {
        return dialect;
    }

    protected static DataSource createDataSource() {
        SimpleDataSource dataSource = new SimpleDataSource();
        dataSource.setUrl("jdbc:hsqldb:mem:tutorial");
        dataSource.setUser("sa");
        return dataSource;
    }

}

エンティティクラス

エンティティクラスとは、テーブルやSQLの結果セットにマッピングされたクラスです。 エンティティクラスは、@Entityを注釈して示します。 このチュートリアルで使用するエンティティクラスのソースコードは、src/tutorial/entity/Employee.javaになります。

Employeeクラスは、EMPLOYEEテーブルに対応します。

識別子(テーブルの主キー)には@Idを注釈します。 識別子を自動生成する場合は、さらに@GeneratedValueを注釈し、自動生成の方法を示します。 ここではEMPLOYEE_SEQシーケンスを使って採番することを示しています。

プロパティ名がマッピングするカラム名と異なる場合は@Columnのname要素を使って示します。

更新や削除時の楽観的排他制御に使用するカラムとマッピングされたプロパティには@Versionを注釈します。

@Entityのlistener要素にはEmployeeListenerクラスを指定しています。

package tutorial.entity;

import java.io.Serializable;
import java.sql.Date;
import java.sql.Timestamp;

import org.seasar.doma.Column;
import org.seasar.doma.Entity;
import org.seasar.doma.GeneratedValue;
import org.seasar.doma.GenerationType;
import org.seasar.doma.Id;
import org.seasar.doma.OriginalStates;
import org.seasar.doma.SequenceGenerator;
import org.seasar.doma.Version;

import tutorial.domain.Salary;

@Entity(listener = EmployeeListener.class)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(sequence = "EMPLOYEE_SEQ")
    Integer id;

    String name;

    int age;

    Salary salary;

    @Column(name = "JOB_TYPE")
    JobType jobType;

    Date hiredate;

    @Column(name = "DEPARTMENT_ID")
    Integer departmentId;

    @Version
    @Column(name = "VERSION")
    Integer version;

    Timestamp insertTimestamp;

    Timestamp updateTimestamp;

    @OriginalStates
    Serializable originalStates;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Salary getSalary() {
        return salary;
    }

    public void setSalary(Salary salary) {
        this.salary = salary;
    }

    public JobType getJobType() {
        return jobType;
    }

    public void setJobType(JobType jobType) {
        this.jobType = jobType;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    @Override
    public String toString() {
        return "Employee [departmentId=" + departmentId + ", hiredate="
                + hiredate + ", id=" + id + ", jobType=" + jobType + ", name="
                + name + ", originalStates=" + originalStates + ", salary="
                + salary + ", version=" + version + ", insertTimestamp="
                + insertTimestamp + ", updateTimestamp=" + updateTimestamp
                + "]";
    }

}

エンティティリスナー

エンティティリスナークラスのインスタンスは、エンティティがデータベースに挿入、更新、削除されるまえに呼び出されます。 このチュートリアルで使用するエンティティリスナークラスはEmployeeListenerです。 ソースコードは、src/tutorial/entity/EmployeeListener.javaになります。

package tutorial.entity;

import java.sql.Timestamp;

import org.seasar.doma.jdbc.entity.EntityListener;

public class EmployeeListener implements EntityListener<Employee> {

    @Override
    public void preDelete(Employee employee) {
    }

    @Override
    public void preInsert(Employee employee) {
        employee.insertTimestamp = new Timestamp(System.currentTimeMillis());
    }

    @Override
    public void preUpdate(Employee employee) {
        employee.updateTimestamp = new Timestamp(System.currentTimeMillis());
    }

}

ドメインクラス

ドメインクラスは、データベースのカラムにマッピング可能なアプリケーション固有の値型です。 ドメインクラスは@Domainを注釈して示します。 このチュートリアルで使用するドメインクラスは、給料を表すSalaryクラスです。 ソースコードは、src/tutorial/domain/Salary.javaになります。

package tutorial.domain;

import org.seasar.doma.Domain;

@Domain(valueType = Integer.class)
public class Salary {

    private final Integer value;

    public Salary(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }

    public Salary add(Salary salary) {
        if (salary == null) {
            throw new NullPointerException("The salary parameter is null.");
        }
        if (this.value == null || salary.value == null) {
            return new Salary(null);
        }
        return new Salary(this.value + salary.value);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value == null) ? 0 : value.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Salary other = (Salary) obj;
        if (value == null) {
            if (other.value != null) {
                return false;
            }
        } else if (!value.equals(other.value)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return value != null ? String.valueOf(value) : null;
    }

}

Daoインタフェース

Daoインタフェースとは、データベースアクセスの境界となるインタフェースです。 Daoインタフェースは@Daoを注釈して示します。 @Daoのconfig要素には設定クラスであるAppConfigクラスを指定します。 このチュートリアルで使用するDaoインタフェースのソースコードは、src/tutorial/dao/EmployeeDao.javaになります。

Daoインタフェースの実装クラスはDomaにより自動生成されます。

すべてのメソッドは、@Selectや@Updateなど問い合わせの種別を示すアノテーションが注釈されなければいけません。

package tutorial.dao;

import java.sql.Timestamp;
import java.util.List;

import org.seasar.doma.BatchDelete;
import org.seasar.doma.BatchInsert;
import org.seasar.doma.BatchUpdate;
import org.seasar.doma.Dao;
import org.seasar.doma.Delegate;
import org.seasar.doma.Delete;
import org.seasar.doma.Insert;
import org.seasar.doma.Select;
import org.seasar.doma.Update;
import org.seasar.doma.jdbc.IterationCallback;
import org.seasar.doma.jdbc.SelectOptions;

import tutorial.AppConfig;
import tutorial.domain.Salary;
import tutorial.entity.Employee;

@Dao(config = AppConfig.class)
public interface EmployeeDao {

    @Select
    Employee selectById(Integer id);

    @Select
    List<Employee> selectByAgeRange(Integer min, Integer max);

    @Select
    List<Employee> selectByAges(List<Integer> ages);

    @Select
    List<Employee> selectByNames(List<String> names);

    @Select
    List<Employee> selectByNameWithPrefixMatching(String prefix);

    @Select
    List<Employee> selectByNameWithSuffixMatching(String suffix);

    @Select
    List<Employee> selectByNameWithInsideMatching(String inside);

    @Select
    List<Employee> selectByHiredateRange(Timestamp from, Timestamp to);

    @Select
    List<Employee> selectBySalary(Salary salary);

    @Select
    Salary selectSummedSalary();

    @Select
    List<Employee> selectByExample(Employee e);

    @Select
    List<Employee> selectAll();

    @Select
    List<Employee> selectAll(SelectOptions options);

    @Select(iterate = true)
    <R> R selectByAge(int age, IterationCallback<R, Employee> callback);

    @Delegate(to = EmployeeDaoDelegate.class)
    int count();

    @Insert
    int insert(Employee employee);

    @Update
    int update(Employee employee);

    @Delete
    int delete(Employee employee);

    @BatchInsert
    int[] batchInsert(List<Employee> employees);

    @BatchUpdate
    int[] batchUpdate(List<Employee> employees);

    @BatchDelete
    int[] batchDelete(List<Employee> employees);

}

SQLファイル

SQLファイルは、src/META-INF/tutorial/EmployeeDaoフォルダ以下に配置されています。