DeltaSpike Data Module(使いそうなところだけ)まとめ4
Transactions
・・・DeltaSpike JPAも使うつもりだけど、完全に理解できていない。。。
特に指定せずに1トランザクション内で異なるRepositoryの更新ができるなら問題ないけど。。。
とりあえず
「the repository will figure out if a transaction is needed or not」
(リポジトリはトランザクションが必要かどうか理解します)
とあるからよろしくやってくれる、、、はず。。。
トランザクションを完全に理解しないのはかなり怖いけど、必要になったらログを見ながら調査予定。
Extensions
リポジトリに独自インターフェースを足して拡張できる。その際、独自インターフェースを実装するimplクラスにDelegateQueryHandlerを付けてね。
という理解。
サンプルではQueryDslライブラリを使えるように拡張している。
・・・QueryDslって何?
QuerydslでJPAが思ったよりも捗る - 水まんじゅう
なるほど、S2JDBCは経験済みだからすぐに理解。でもDeltaSpike Dataが同じような機能を実装してくれている。(後述)
というわけで詳細はスキップ。
Mapping
戻り値をEntityではなくDTOなんかで返せるようにできる。
よくお世話になってくるはず。
public class PersonMapper implements QueryInOutMapper<Person> { @Override public Object mapResult(Person result) { return (変換後オブジェクト); } @Override public Object mapResultList(List<Simple> result) { return (変換後オブジェクトのリスト); } @Override public boolean mapsParameter(Object parameter) { // ? } @Override public Object mapParameter(Object parameter) { // ? } }
QueryInOutMapper
・・・いやまて。mapResultList()はListを受けてListを返す?
List件数が膨大になるとOutOfMemoryになるけど、、、iterator的な機能は?
・・・そもそもJPA自体にそういう仕組みが無いのか。ページングをちゃんとしろ、ということなのだろう。
全件CSV出力とかする場合は、1000件づつ取ってくるとか工夫しないといけない。
それはさておき、クラスを作ったらRepositoryで@MappingConfigを使って指定する。
@Repository(forEntity = Person.class) @MappingConfig(PersonDtoMapper.class) public interface PersonRepository extends EntityRepository<PersonDto, Long> {}
簡易マッピング(Simple Mappings)
正直、mapsParameter()とmapParameter()は何をするのかよく分からない。
それに実際にやるのはEntity←→DTOの相互変換ぐらいなので、その場合は簡易マッピングを使う。たぶんこちらを使うことになる。
public class PersonMapper extends SimpleQueryInOutMapperBase<Person, PersonDto> { @Override protected Object getPrimaryKey(PersonDto dto) { return dto.getId(); } @Override protected PersonDto toDto(Person entity) { return parsonDto; } @Override protected Person toEntity(Person entity, PersonDto dto) { return entity; } }
SimpleQueryInOutMapperBaseはQueryInOutMapperを実装した抽象クラスで、QueryInOutMapperのよく分からないメソッド達を隠蔽してくれている。
getPrimaryKey()はDTO側でプライマリキーとなるプロパティの値を返すようにする。
toDto()とtoEntity()は読んで字のごとく。
toEntity()の第一引数がEntityになっているが、ソースを見るとEntityManager.find()したEntityを、find()結果が無ければnewのオブジェクトを渡している様子。
必ず引数のEntityを操作して返すこと。(自前でnewとかしない)
JPA Criteria API Support
JPAにCriteriaというAPIがある。が、かなり複雑(みたい)。
(実際に触ったことがないが、色々調べる限り使いたくない。上述のQuerydslなんてものが作られるのが使いにくい証拠)
DeltaSpike DataでもQuerydslのような機能が提供されている。
@Repository(forEntity = Person.class) public abstract class PersonRepository implements CriteriaSupport<Person> { public List<Person> findAdultFamilyMembers(String name, Integer minAge) { return criteria() .like(Person_.name, "%" + name + "%") .gtOrEq(Person_.age, minAge) .eq(Person_.validated, Boolean.TRUE) .orderDesc(Person_.age) .getResultList(); } }
「流れるようなインターフェース」というやつでしょうか。多分見て想像がつくSQLが実行される。
これについてはSeasar2(S2JDBC)を使っていたので問題なし。DTOでも返せそう。なのでスキップ。
Auditing
・・・監査?
サンプルでは登録日(Date created)と更新日(Date updated)を更新するような例が載っている。
@PrePersistや@PreUpdate使うのとあまり違いは無い気がする。
(Auditingの方はオブジェクトの作成・更新のタイミングで差し込まれる? でもそこまで厳密なタイムスタンプいらない)
というわけでスキップ。
まとめ終わり。