LoginSignup
9
11

More than 5 years have passed since last update.

Dropwizard with jdbiでのトランザクション

Last updated at Posted at 2014-10-14

Dropwizardでjdbiを使う場合、以下を気にする必要があります。

  • トランザクション境界をどうするか
  • dao一つ一つが別のトランザクション

Resourceにトランザクション境界を作る

まずは、トランザクション境界をResourceクラスにします。

daoで org.skife.jdbi.v2.sqlobject.mixins.Transactional  を継承します。

PersonJdbiRepository.java
public interface PersonJdbiRepository extends Transactional<PersonJdbiRepository> {

    @SqlBatch("insert into people (fullName, jobTitle) values (:fullName, :jobTitle)")
    void createMany(@BindBean Iterator<Person> iterator);
・・・

次にResourceクラスで、inTransaction メソッドを利用します。@org.skife.jdbi.v2.sqlobject.Transactionを利用しても駄目です。
引数の Transaction 実装内で例外が起きるとrollbackされるようになります。

PeopleJdbiResource.java

    private final PersonJdbiRepository repository;

    @POST
    public List<Person> createBatch() {
        repository.inTransaction(new Transaction<Void, PersonJdbiRepository>() {
            @Override
            public Void inTransaction(PersonJdbiRepository transactional, TransactionStatus status) throws Exception {
                List<Person> people = new ArrayList<Person>();
                people.add(new Person("ko2ic", "batch1"));
                people.add(new Person("ko2ic", "batch2"));
                repository.createMany(people.iterator());
                return null;
            }
        });
        return listPeople();
    }

複数Dao対応

次は、二つのDao間で一つのトランザクションにしたい場合の対処です。

これは特殊な(微妙な)処理をしなければなりません。
一方のDaoにもう一つのDaoを取得するメソッドを追加し、そのメソッドに @CreateSqlObject アノテーションを付けます。
そして、両方を呼び出すメソッドを作ります。
文章にしてもよくわからないと思うのでコードを見て下さい。

PersonJdbiRepository.java
public abstract class PersonJdbiRepository implements Transactional<PersonJdbiRepository> {

    @SqlBatch("insert into people (fullName, jobTitle) values (:fullName, :jobTitle)")
    public abstract void createMany(@BindBean Iterator<Person> iterator);

    @CreateSqlObject
    public abstract TempJdbiRepository createTempJdbiRepository();

    public int createWithTemp(Iterator<Person> iterator) {
        createMany(iterator);
        TempJdbiRepository repository = createTempJdbiRepository();
        repository.create();
        // throw new IllegalArgumentException();
        return repository.count();
    }
}

createWithTemp() メソッドの実装が必要なので、abstract classにしています。java8のdefault実装ではできませんでした。
createWithTemp() メソッドに @org.skife.jdbi.v2.sqlobject.Transaction を書くとこのメソッドがトランザクション境界になります。
Resourceクラスをトランザクション境界にしたい場合は、上記「Resourceにトランザクション境界を作る」と同様です。

下の実装は、上記内で呼ばれているもう一方のDaoです。

TempJdbiRepository.java
public interface TempJdbiRepository {

    @SqlQuery("select count(id) from temp")
    int count();

    @SqlUpdate("insert into temp (fullName) values ('fullName')")
    void create();
}
9
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
11