Spring Boot Data jpaを使用するアプリケーションがあります。これまでのところ、私はこのようなリポジトリを使用しています
public interface StudentRepository extends CrudRepository<StudentEntity, Integer>{
@Query(value = ""
+ "SELECT s.studentname "
+ "FROM studententity s, "
+ " courseentity c "
+ "WHERE s.courseid = c.courseid "
+ " AND s.courseid IN (SELECT c.courseid "
+ " FROM courseentity c "
+ " WHERE c.coursename = ?1)")
List<String> nameByCourse(String coursename);
}
Criteria Queryを使用して、HibernateがSpring Bootアプリケーションでそのような場合に提供する方法
docs
から
リポジトリをカスタム機能で強化するには、最初にカスタム機能のインターフェイスと実装を定義します。指定したリポジトリインターフェイスを使用して、カスタムインターフェイスを拡張します。
そのようにインターフェースを定義する
public interface StudentRepositoryCustom {
List<String> nameByCourse(String coursename);
}
次に、このインターフェースのカスタム実装を次のように定義します
@Service
class StudentRepositoryImpl implements StudentRepositoryCustom {
@PersistenceContext
private EntityManager em;
public List<String> nameByCourse(String coursename) {
CriteriaBuilder cb = em.getCriteriaBuilder();
//Using criteria builder you can build your criteria queries.
}
}
これで、JPAリポジトリでこのカスタムリポジトリ実装を拡張できます。
public interface StudentRepository extends CrudRepository<StudentEntity, Integer>, StudentRepositoryCustom {
}
条件クエリと条件ビルダーの詳細 here
Spring-boot-jpa
ほぼすべての場所でentityManager
を使用できます。最も一般的な方法は、カスタムメソッド用に独自のinterface
を作成することです。
public interface StudentCustomRepository {
void anyCustomMethod();
Student getStudentByName(String name);
}
次に、entityManager
を自動配線して使用できるサービスクラスにこのインターフェイスを実装します。
@Service
public class StudentCustomRepositoryServiceImpl implements StudentCustomRepository {
@PersistenceContext
private EntityManager em;
@Override
public void anyCustomMethod(){
//here use the entityManager
}
@Override
StudentEntity getStudentByName(String name){
Criteria crit = em.unwrap(Session.class).createCriteria(StudentEntity.class);
crit.add(Restrictions.eq("name", name));
List<StudentEntity> students = crit.list();
return students.get(0);
}
}
StudentRepository
を新しいStudentCustomRepositoryServiceImpl
クラスに実装することもできます。
JPA 2は、クエリをプログラムで作成するために使用できる基準APIを導入しています。
JpaSpecificationExecutor
から新しいインターフェースを拡張できます
public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor {
default List<Customer> findCustomers() {
return findAll(CustomerSpecs.findCustomers());
}
次に、顧客仕様を作成します
public final class CustomerSpecs {
public static Specification<Customer> findCustomers() {
return new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
LocalDate date = new LocalDate().minusYears(2);
return builder.lessThan(root.get("birthday"), date);
}
};
}
詳細については、この春のドキュメントを参照してください
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications
Spring docによると HibernateTemplate :
注:Hibernateアクセスコードは、プレーンなHibernateスタイルでコーディングすることもできます。したがって、新しく開始されたプロジェクトの場合は、SessionFactory.getCurrentSession()に基づいて、データアクセスオブジェクトをコーディングする標準のHibernateスタイルを採用することを検討してください。このHibernateTemplateは、主にHibernate 4.xのバグ修正の恩恵を受けるために、Hibernate 3ベースのデータアクセスコードの移行ヘルパーとして存在します。
Hibernateのドキュメントによると:
新規開発では、JPA javax.persistence.criteria.CriteriaQuery APIに焦点を当てる必要があります。最終的に、Hibernate固有の基準機能は、JPA javax.persistence.criteria.CriteriaQueryの拡張機能として移植されます。
したがって、JPQL基準を使用する方が適切です: JPA基準APIクエリ
例:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Country> q = cb.createQuery(Country.class);
Root<Country> c = q.from(Country.class);
q.select(c);
entityManagerは@Autowiredである必要があります。詳細情報については、上記のリンクを参照してください
APIは非常に冗長で邪魔にならないため、JPA基準を使用して仕様を作成することは非常に複雑です。
Lambda JDK 8では、単純な述語を使用して、非常に型付けされたクエリを作成できます。
@Test
public void testSimpleSpec() {
String expected =
"select e0.id, e0.name "
+ "from Customer e0 "
+ "where (e0.regionCode = :p0)";
Consumer<Query<Customer>> regionCode1 =
q -> q.where(i -> i.getRegionCode()).eq(1L);
NativeSQLResult result = new QueryBuilder()
.from(Customer.class)
.whereSpec(regionCode1)
.select(i -> i.getId())
.select(i -> i.getName())
.to(new NativeSQL())
;
String actual = result.sql();
Assert.assertEquals(expected, actual);
Assert.assertEquals(result.params().get("p0"), 1L);
}
条件を分離し、他のクエリ、つまり仕様で再利用できます。
クエリ作成 を参照してスプリングデータJPAドキュメントを参照し、表を見ると、JPAは文字列クエリの使用を避けることができるメソッド名から複数のクエリを作成できます。