私は3つのJPAエンティティクラスA
、B
およびC
を次の階層で持っています:
A
|
+---+---+
| |
C B
あれは:
@Entity
@Inheritance
public abstract class A { /* ... */ }
@Entity
public class B extends A { /* ... */ }
@Entity
public class C extends A { /* ... */ }
Spring Data JPAを使用して、リポジトリこのようなエンティティのクラスを記述する最良の方法は何ですか?
私はこれらを書くことができることを知っています:
public interface ARespository extends CrudRepository<A, Long> { }
public interface BRespository extends CrudRepository<B, Long> { }
public interface CRespository extends CrudRepository<C, Long> { }
クラスA
にフィールドname
があり、ARepository
にこのメソッドを追加する場合:
public A findByName(String name);
私は他の2つのリポジトリにもこのようなメソッドを記述しなければなりませんが、これは少し面倒です。そのような状況に対処するより良い方法はありますか?
もう1つのポイントは、ARespository
を読み取り専用リポジトリにする(つまり、Repository
クラスを拡張する)一方で、他の2つのリポジトリはすべてのCRUD操作を公開する必要があるということです。
可能な解決策を教えてください。
Netglooのブログの この投稿 でも説明されているソリューションを使用しました。
考え方は、次のようなgenericリポジトリクラスを作成することです。
@NoRepositoryBean
public interface ABaseRepository<T extends A>
extends CrudRepository<T, Long> {
// All methods in this repository will be available in the ARepository,
// in the BRepository and in the CRepository.
// ...
}
次に、この方法で3つのリポジトリを作成できます。
@Transactional
public interface ARepository extends ABaseRepository<A> { /* ... */ }
@Transactional
public interface BRepository extends ABaseRepository<B> { /* ... */ }
@Transactional
public interface CRepository extends ABaseRepository<C> { /* ... */ }
さらに、ARepository
の読み取り専用リポジトリを取得するには、ABaseRepository
を読み取り専用として定義できます。
@NoRepositoryBean
public interface ABaseRepository<T>
extends Repository<T, Long> {
T findOne(Long id);
Iterable<T> findAll();
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
また、BRepository
からSpring Data JPAのCrudRepository
も拡張して、読み取り/書き込みリポジトリを実現します。
@Transactional
public interface BRepository
extends ABaseRepository<B>, CrudRepository<B, Long>
{ /* ... */ }