J'ai une application qui utilise Spring Boot Data jpa . Jusqu'à présent, j'utilise un référentiel comme celui-ci.
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);
}
Comment puis-je utiliser Interrogation sur les critères qu'Hibernate fournit pour de tels cas dans une application Spring Boot
De la docs
Pour enrichir un référentiel avec des fonctionnalités personnalisées, vous devez d'abord définir une interface et une implémentation pour les fonctionnalités personnalisées. Utilisez l'interface de référentiel que vous avez fournie pour étendre l'interface personnalisée.
Définir une interface comme ça
public interface StudentRepositoryCustom {
List<String> nameByCourse(String coursename);
}
Puis définissez une implémentation personnalisée de cette interface comme
@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.
}
}
Vous pouvez maintenant étendre cette implémentaion de référentiel personnalisé dans votre référentiel JPA comme suit.
public interface StudentRepository extends CrudRepository<StudentEntity, Integer>, StudentRepositoryCustom {
}
En savoir plus sur la requête de critères et le générateur de critères here
Avec Spring-boot-jpa
, vous pouvez utiliser entityManager
presque partout. La méthode la plus courante consiste à créer une propre variable interface
pour les méthodes personnalisées.
public interface StudentCustomRepository {
void anyCustomMethod();
Student getStudentByName(String name);
}
Puis implémentez cette interface dans une classe de service sur laquelle vous êtes en mesure de connecter automatiquement et utilisez la variable 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);
}
}
Vous pouvez également décider d'implémenter votre StudentRepository
dans votre nouvelle classe StudentCustomRepositoryServiceImpl
.
JPA 2 introduit une API de critères qui peut être utilisée pour créer des requêtes par programme.
Vous pouvez étendre une nouvelle interface de JpaSpecificationExecutor
public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor {
default List<Customer> findCustomers() {
return findAll(CustomerSpecs.findCustomers());
}
Puis créez une spécification client
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);
}
};
}
Pour plus de détails, référez-vous à la doc de ce printemps ici
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications
Selon Spring, le document HibernateTemplate :
REMARQUE: Le code d'accès Hibernate peut également être codé en clair. Hibernate style. Par conséquent, pour les projets récemment lancés, envisagez d’adopter le Le style standard d’Hibernate de codage des objets d’accès aux données, basé sur sur SessionFactory.getCurrentSession (). Ce modèle Hibernate existe principalement comme assistant de migration pour les données basées sur Hibernate 3./ code d'accès, pour bénéficier des corrections de bugs dans Hibernate 4.x.
Selon la documentation d'Hibernate:
Les nouveaux développements devraient se concentrer sur l’APP API javax.persistence.criteria.CriteriaQuery. Finalement, Les critères spécifiques à Hibernate seront portés en tant qu'extensions vers JPA javax.persistence.criteria.CriteriaQuery.
Il est donc préférable d’utiliser les critères JPQL: Requêtes API JPA Criteria
Exemple:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Country> q = cb.createQuery(Country.class);
Root<Country> c = q.from(Country.class);
q.select(c);
où entityManager devrait être @Autowired. Pour plus d'informations, voir le lien ci-dessus
Il est très compliqué de créer des spécifications à l'aide de critères JPA, car l'API est très détaillée et instructive.
Avec le JDK Lambda 8, vous pouvez créer des requêtes très typées en utilisant des prédicats simples.
@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);
}
Vous pouvez isoler les conditions et les réutiliser dans d'autres requêtes, par exemple des spécifications.
vous pouvez vous référer à Création de requête dans la documentation JPA de Spring Data et consulter le tableau. JPA permet de créer plusieurs requêtes à partir de noms de méthodes, ce qui vous évite d'utiliser une requête String