doma2をやってみる (5) - OriginalStates -

2015-04-20T00:00:00+09:00 Java doma

参考: http://doma.readthedocs.org/ja/stable/entity/#id16

取得時の状態とは、エンティティがDaoから取得されときの全プロパティの値です。取得時の状態を保持しておくことで、更新処理を実行する際、UPDATE文のSET句に変更したフィールドのみを含められます

との事。やってみた

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.OriginalStates;
import org.seasar.doma.Version;
import org.seasar.doma.jdbc.entity.NamingType;

import sample.domain.Name;

@Entity(naming = NamingType.LOWER_CASE)
public class Sample {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private Name name;

    private int age;

    @Column(name = "created_at")
    private Date createdAt;

    @OriginalStates
    private Sample originalStates;

    @Version
    private int version;

    public int getId() {
        return id;
    }

    public Name getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Date getCreatedAt() {
        return createdAt;
    }
}

みたいに@OriginalStatesアノテーションを持つエンティティクラスを定義する。これを定義するかしないかでUPDATE実行SQLがどう変わるのか確認する

SampleDaoTest.java

package sample.dao;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.beans.factory.annotation.Autowired;

import sample.domain.Name;
import sample.entity.Sample;
import sample.repository.SampleRepository;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SampleDaoTest {

    @Autowired
    SampleRepository dao;

    @Test
    public void test_update() throws Exception {
        Sample sample = dao.find(1);
        sample.setAge(sample.getAge() + 1);

        // updateメソッドは@Updateアノテーションを付与しただけ
        dao.update(sample);
    }
}

実行SQL結果 (@OriginalStatesが無い場合)

update sample
set
    name = 'hoge fuga foobar',
    age = 21,
    created_at = '2015-04-20 15:30:40',
    version = 0 + 1
where
    id = 1
and
    version = 0

実行SQL結果 (@OriginalStatesがある場合)

update sample
set
    age = 22,
    version = 1 + 1
where
    id = 1
and
    version = 1

っていうように取得時状態をチェックして変化がないような所に関してはSET区において指定されずに処理される。又、DAO等の@Updateがついてるメソッドから返ってくるint値は@OriginalStatesがある場合とかだと変化が無くアップデートされてない場合は0が帰って来る。それ以外の場合は1(もしくは変化があったレコード数?)が返ってくる。@OriginalStatesが無い場合とかだと変化が無くても処理されるため1が返ってくる模様

っていう感じでUPDATE区を使って処理するような場合に取得時状態をチェックして変化合った場合にのみ処理を行うような所な機能な模様

gradleのExecタスクタイプ