Spring Data JPA中封装了很多条件查询的方法,我们可以使用封装的方法和@Query注解进行条件查询。这些都是比较简单的,直接调用接口就行。但是要想实现动态查询,就比较复杂了。下面我将结合Specification和自定义Repository实现来定制一个动态条件查询,实现当对应的条件参数为空时,不加入查询的条件中。
1.定义Specification:
package edu.dgut.supervision.customRepository;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
//定义Specification(自定义Repository实现)
public class CustomerSpecs {
//根据任务编号,督查项目,督查点动态查询
public static Specification byAuto(String renwuNo,String projectName,String name){
return new Specification(){
@Override
public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder criteriaBuilder) {
List predicates = new ArrayList<>();
if(null != renwuNo && !"".equals(renwuNo)){
predicates.add(criteriaBuilder.equal(root.get("renwuNo"), renwuNo));
}
if(null != projectName && !"".equals(projectName)){
predicates.add(criteriaBuilder.equal(root.get("projectName"), projectName));
}
if(null != name && !"".equals(name)){
predicates.add(criteriaBuilder.equal(root.get("name"), name));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
}
}
2.定义Repository接口
package edu.dgut.supervision.customRepository;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.Param;
import edu.dgut.supervision.domain.VDuchataizhang;
/**
* 自定义接口:根据任务编号,督查项目,督查点查询督查任务
* @author Mike
*
* @param
* @param
*/
@NoRepositoryBean
public interface CustomRepository extends JpaRepository,JpaSpecificationExecutor{
List findByCondition(@Param("renwuNo")String renwuNo,@Param("projectName")String projectName,@Param("name")String name);
}
3.自定义接口的实现
package edu.dgut.supervision.customRepository;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import edu.dgut.supervision.domain.VDuchataizhang;
import static edu.dgut.supervision.customRepository.CustomerSpecs.*;
//自定义数据库接口实现
public class CustomRepositoryImpl extends SimpleJpaRepository implements
CustomRepository{
public CustomRepositoryImpl(Class domainClass,EntityManager entityManager){
super(domainClass,entityManager);
}
@SuppressWarnings("unchecked")
@Override
public List findByCondition(String renwuNo,String projectName,String name) {
return (List) findAll(byAuto(renwuNo,projectName,name));
}
}
4.定义repositoryFactoryBean:
package edu.dgut.supervision.customRepository;
import java.io.Serializable;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
public class CustomRepositoryFactoryBean,S,ID extends Serializable>
extends JpaRepositoryFactoryBean{
public CustomRepositoryFactoryBean(Class extends T> repositoryInterface) {
super(repositoryInterface);
}
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager){
return new CustomRepositoryFactory(entityManager);
}
private static class CustomRepositoryFactory extends JpaRepositoryFactory{
public CustomRepositoryFactory(EntityManager entityManager) {
super(entityManager);
}
@Override
@SuppressWarnings({"unchecked"})
protected SimpleJpaRepository,?> getTargetRepository(
RepositoryInformation information,EntityManager entityManager){
return new CustomRepositoryImpl((Class)information.getDomainType(),entityManager);
}
@Override
protected Class> getRepositoryBaseClass(RepositoryMetadata metadata){
return CustomRepositoryImpl.class;
}
}
}
5.开启自定义支持
package edu.dgut.supervision;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import edu.dgut.supervision.customRepository.CustomRepositoryFactoryBean;
@SpringBootApplication
//开启自定义Repository的配置
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class SupervisionApplication{
public static void main(String[] args) {
SpringApplication.run(SupervisionApplication.class, args);
}
}
这一步非常重要,我之前就是忘记开启,所以自定义的repository不起作用。
6.继承自定义接口
package edu.dgut.supervision.repository;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.transaction.annotation.Transactional;
import edu.dgut.supervision.customRepository.CustomRepository;
import edu.dgut.supervision.domain.VDuchataizhang;
/**
* @author Jackie
*
*/
@RepositoryRestResource(collectionResourceRel = "VDuchataizhang", path = "duchataizhang")
public interface DuchataizhangRepository extends PagingAndSortingRepository,CustomRepository{
@Transactional(readOnly=true)
@Query("select u from VDuchataizhang u where u.renwuNo = ?1")
Page findByRenwuNo(@Param("renwuNo")String renwuNo,Pageable pageable);
@Query("select u from VDuchataizhang u")
List findAll();
//根据任务编号和督查点获取对应的督查台账记录
@Query("select u from VDuchataizhang u where u.renwuNo = ?1 and u.name = ?2")
VDuchataizhang getProject(@Param("renwuNo")String renwuNo,@Param("name")String name);
//根据任务编号和项目编号获取对应的督查台账记录
@Query("select u from VDuchataizhang u where u.renwuNo = ?1 and u.projectNo = ?2")
Page getByTaskNoAndProjectNo(@Param("renwuNo")String renwuNo,@Param("projectNo")String projectNo,Pageable pageable);
// //根据任务编号获取督查任务
@Query("select u from VDuchataizhang u where u.renwuNo = ?1")
List findListByRenwuNo(@Param("renwuNo")String renwuNo);
}
只需让实体类Repository继承我们自定义的Repository接口,即可使用我们在自定义Repository中实现的功能。
7.调用自定义的Repository接口
/**
* 根据任务编号,督查项目,督查点查询督查任务
* @param renwuNo
* @param projectName
* @param name
* @return
*/
@RequestMapping("/findDuchataizhang")
@ResponseBody
public Map findDuchataizhang(String renwuNo,String projectName,String name){
Map resultMap = new HashMap();
//获取返回的数据
resultMap.put("data", duchataizhangRepository.findByCondition(renwuNo,projectName,name));
return resultMap;
}