Domaでエンティティが変更されたかどうかを検知するには

エンティティに@OriginalStatesを付与すると、エンティティのプロパティがDaoからの取得後に変更されたかどうかを検知できます。

@Entity(listener = EmpListener.class, naming = NamingType.SNAKE_UPPER_CASE)
public class Emp {
    ...
    @OriginalStates
    Emp originalStates;
}

Domaはこの機能で変更があったプロパティだけを対象とするUPDATE文のSET句を組み立てています。

実は、この変更検知の機能、Domaの内部だけで使用していてアプリから利用できるようなAPIを提供していません。ただし、次のようなクラスを自前で作ると変更があったかどうかを知ることができます。

import org.seasar.doma.jdbc.entity.EntityPropertyType;
import org.seasar.doma.jdbc.entity.EntityType;
import org.seasar.doma.jdbc.entity.EntityTypeFactory;
import org.seasar.doma.wrapper.Wrapper;

public class EntityUtil {

    public static <E> boolean isChanged(Class<E> entityClass, E entity) {
        EntityType<E> entityType = EntityTypeFactory.getEntityType(entityClass);
        E originalStates = entityType.getOriginalStates(entity);
        if (originalStates == null) {
            return true;
        }
        for (EntityPropertyType<E, ?> p : entityType.getEntityPropertyTypes()) {
            Wrapper<?> wrapper = p.getWrapper(entity);
            Wrapper<?> originalWrapper = p.getWrapper(originalStates);
            p.getWrapper(originalStates);
            if (!wrapper.hasEqualValue(originalWrapper.get())) {
                return true;
            }
        }
        return false;
    }
}

使い方はこうです。

boolean changed = EntityUtil.isChanged(Emp.class, entity);

利用できるバージョンは、1.10.2。たぶん、これより下位のバージョンでも大丈夫。

これと同等のAPI、もしくはEntityListenerで変更を検知するAPIは次のバージョンでサポートしたいと思います。