doma2を使ってみた
http://doma.readthedocs.org/ja/latest/getting-started を見ながらやってみた
※ターゲットバージョンは2.x
構造
. ├── build.gradle └── src ├── main │ ├── java │ │ └── sample │ │ ├── AppConfig.java │ │ ├── dao │ │ │ └── SampleDao.java │ │ └── entity │ │ └── Sample.java │ └── resources │ └── META-INF │ └── sample │ └── dao │ └── SampleDao │ ├── find.sql │ └── findAll.sql └── test └── java └── sample └── dao └── SampleDaoTest.java
build.gradle
apply plugin: "java"
processResources.destinationDir = compileJava.destinationDir
compileJava.dependsOn processResources
repositories {
mavenCentral()
}
dependencies {
runtime "mysql:mysql-connector-java:+"
compile "org.seasar.doma:doma:2.1.0"
testCompile "junit:junit:+"
testCompile "org.hamcrest:hamcrest-all:+"
}
公式ドキュメントにはEclipseを使う際の設定なりが記述されてるけど、使わないのですこは全面的にスキップで(詳しくは https://github.com/domaframework/simple-boilerplate を読めばいい)
でdomaの方式としてはDAO(インターフェース)とSQLを書いてそのソースから実装をアノテーションプロセッサー周りを使ってクラスを生成する仕組みになっている模様
で実行環境はこんなもんで、DAO(とエンティティクラスを含む)とSQLとデータソースなり回りなAppConfigクラスを作成する
AppConfig.java
package sample;
import javax.sql.DataSource;
import org.seasar.doma.SingletonConfig;
import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.MysqlDialect;
import org.seasar.doma.jdbc.tx.LocalTransactionDataSource;
import org.seasar.doma.jdbc.tx.LocalTransactionManager;
import org.seasar.doma.jdbc.tx.TransactionManager;
@SingletonConfig
public class AppConfig implements Config {
private static final AppConfig INSTANCE = new AppConfig();
private final Dialect dialect;
private final LocalTransactionDataSource dataSource;
private final TransactionManager transactionManager;
private AppConfig() {
dialect = new MysqlDialect();
dataSource = new LocalTransactionDataSource("jdbc:mysql://localhost:3306/sample", "kinjouj", "1234");
transactionManager = new LocalTransactionManager(dataSource.getLocalTransaction(getJdbcLogger()));
}
@Override
public Dialect getDialect() {
return dialect;
}
@Override
public DataSource getDataSource() {
return dataSource;
}
@Override
public TransactionManager getTransactionManager() {
return transactionManager;
}
public static AppConfig singleton() {
return INSTANCE;
}
}
大体な所を http://doma.readthedocs.org/ja/latest/config/#id20 を参考にして作成。DIコンテナ依存するような場合のケースは今後検証するので今回はパス
Sample.java
package sample.entity;
import java.util.Date;
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.Version;
import org.seasar.doma.jdbc.entity.NamingType;
@Entity(naming = NamingType.LOWER_CASE)
public class Sample {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@Column(name = "created_at")
private Date createdAt;
@Version
private int version;
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreatedAt() {
return createdAt;
}
}
変数名がそのままカラム名になるのでマッピングする際にあたって名称によって問題なる場合には@Columnアノテーションで紐付けするカラム名をマッピングするようにすれば良い。あとテーブル名もデフォルトではクラス名同等の名前になる模様。そういう問題が出るような場合(insert等のSQLを自動生成して実行するような場合)にはnamingパラメーターでクラス内で実行するSQLを生成する際に参照するテーブル名などの方式を設定すれば良い。上記だとクラス名をlowercaseした値でSQLを実行する
※@Tableアノテーションで指定した名前で利用することも可能っぽい
SampleDao.java
package sample.dao;
import java.util.List;
import org.seasar.doma.Dao;
import org.seasar.doma.Insert;
import org.seasar.doma.Select;
import sample.AppConfig;
import sample.entity.Sample;
@Dao(config = AppConfig.class)
public interface SampleDao {
@Select
List<Sample> findAll();
@Select
Sample find(int id);
@Insert
// へたに引数の変数名にパッケージ名等に存在するような名称使うとコンパイルエラーになる
int save(Sample s);
}
で@Selectアノテーションで使うSQLファイルを定義する必要がある。resources/META-INF/DAOパッケージ名/メソッド名.sqlで定義すれば良い模様
resources/META-INF/sample/dao/SampleDao/findAll.sql
select
/*%expand*/*
from
sample
order by id
/%expand/っていう形として、オブジェクトが持つカラムを展開してくれる
resources/META-INF/sample/dao/SampleDao/find.sql
SELECT
/*%expand*/*
FROM
sample
WHERE
id = /* id */0
/* id */の箇所にメソッドの引数で指定した値が展開される
っていう感じでこれで実装終わりなので、テスト書いて実際にデータベースの問い合わせをテストしてみる
SampleDaoTest.java
package sample.dao;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.seasar.doma.jdbc.tx.TransactionManager;
import sample.AppConfig;
import sample.entity.Sample;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
public class SampleDaoTest {
private final SampleDao dao = new SampleDaoImpl();
private TransactionManager tm;
@Before
public void setUp() {
tm = AppConfig.singleton().getTransactionManager();
}
@Test
public void test_findAll() {
tm.required(() -> {
List<Sample> samples = dao.findAll();
assertThat(samples.size(), greaterThan(0));
Sample sample = samples.get(0);
assertThat(sample, notNullValue());
assertThat(sample.getId(), is(1));
assertThat(sample.getName(), is("hoge"));
});
}
@Test
public void test_find() {
tm.required(() -> {
Sample sample = dao.find(1);
assertThat(sample, notNullValue());
assertThat(sample.getName(), is("hoge"));
});
}
@Test
public void test_save() {
tm.required(() -> {
Sample sample = new Sample();
sample.setName("hoge fuga foobar");
dao.save(sample);
});
}
}
終わり。とりあえずGetting Startedをやってみただけなので今後もドキュメント読みを遂行しつつやってく予定っていうことで