我有一个使用 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);
}
如何利用Hibernate在Spring Boot应用程序中为此类情况提供的 Criteria Query
答案 0 :(得分:18)
来自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
答案 1 :(得分:4)
使用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
课程。
答案 2 :(得分:3)
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
答案 3 :(得分:2)
根据Spring doc HibernateTemplate:
注意:Hibernate访问代码也可以在普通的Hibernate中编码 样式。因此,对于新开工项目,请考虑采用 标准的Hibernate风格的编码数据访问对象取而代之 在SessionFactory.getCurrentSession()上。这个HibernateTemplate 主要作为基于Hibernate 3的数据的迁移帮助程序存在 访问代码,从Hibernate 4.x中的错误修复中受益。
虽然根据Hibernate doc:
新的发展应该集中在JPA上 javax.persistence.criteria.CriteriaQuery API。最终, 特定于Hibernate的标准功能将作为扩展名移植到 JPA javax.persistence.criteria.CriteriaQuery。
因此,最好使用JPQL Criteria:JPA Criteria API Queries
示例:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Country> q = cb.createQuery(Country.class);
Root<Country> c = q.from(Country.class);
q.select(c);
其中entityManager应该是@Autowired。有关详细信息,请参阅上面的链接
答案 4 :(得分:0)
您可以将Query creation引用到spring数据JPA文档中并查看该表,JPA从方法名称创建多个Query创建,您可以避免使用String查询
答案 5 :(得分:0)
使用JPA Criteria创建规范非常复杂,因为API非常详细且非常具有侵略性。
使用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);
}
您可以隔离条件并在其他查询中重复使用,即规范。