1.在新建Repository时继承 JpaSpecificationExecutor 接口:
1 2 3
| public interface SiteinfoRepo extends JpaRepository<SiteInfo,Long>, JpaSpecificationExecutor { List<SiteInfo> findAll(); }
|
2.在Service层时实现自定义的find函数,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service;
import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import java.util.ArrayList; import java.util.List;
@Service public class SiteinfoService { @Autowired private SiteinfoRepo siteinfoRepo; @PersistenceContext private EntityManager entityManager;
public List<SiteInfo> findSiteInfo(String minDate,String maxDate,Sting nickname){ List<SiteInfo> resultList = null; Specification querySpecifi = new Specification<SiteInfo>() { @Override public Predicate toPredicate(Root<SiteInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>(); if(null != minDate){ predicates.add(criteriaBuilder.greaterThan(root.get("subscribeTime"), minDate));
} if(null != maxDate){ predicates.add(criteriaBuilder.lessThan(root.get("subscribeTime"), maxDate)); } if(null != nickname){ predicates.add(criteriaBuilder.like(root.get("nickname"), "%"+nickname+"%")); } return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])); } }; resultList = this.siteinfoRepo.findAll(querySpecifi); } }
|
3.Specification排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public List<Client> findClient(List<Integer> siteListNo, String orderName, String orderContent){ List<Client> resultList = null; Specification querySpecifi = new Specification<Client>() { @Override public Predicate toPredicate(Root<Client> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>(); if(null != siteListNo&&siteListNo.size()>0){ Expression<Integer> expression=root.get("SiteNo"); Predicate predicate=expression.in(siteListNo); predicates.add(predicate); } Predicate p=criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])); criteriaQuery.where(p); if(orderName!=null&&orderContent!=null){ if(orderContent.toLowerCase().equals("asc")){ criteriaQuery.orderBy(criteriaBuilder.asc(root.get(orderName))); }else { criteriaQuery.orderBy(criteriaBuilder.desc(root.get(orderName))); } }else { criteriaQuery.orderBy(criteriaBuilder.desc(root.get("SiteNo"))); } return criteriaQuery.getRestriction(); } }; resultList = this.clientRepo.findAll(querySpecifi); return resultList; }
|
3.Specification自定义选择sql语句
使用Specification自定义选择,即又要创建sql语句,又要进行条件查询。
(1) 创建原生查询的方式
使用正确的entityManage,就可以使用entityManager创建原生的查询,并和实体类进行关联。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Service public class SecHisService { @Autowired private SecHisRepository secHisRepository;
@PersistenceContext private EntityManager entityManager;
public List<SecHis> findAlarmRecrder(Integer sectionId, Date start_date,Date end_date, Double velocity_min,Double velocity_max,Double heat_min, Double heat_max,Double hLoss_min,Double hLoss_max) { List<SecHis> resultList=null; entityManager.getProperties(); Query query= entityManager.createNativeQuery("select row_number() over (order by RecordTime ) as id, * from secHis",SecHis.class); resultList=query.getResultList(); return resultList; } }
|
(2) CriteriaQuery API
使用安全查询工厂API,但是没有找到如何创建原生查询的方法,就像上面的第一和第二种问题,以及下面的多篇参考文章,都是介绍了如何使用Criteria API进行查询。其中CriteriaQuery 安全查询主语句;Root 定义查询的From子句中能出现的类型;Predicate 过滤条件;而CriteriaBuilder就是将上面的三者进行组合,最后组成了一个完整的查询。
Specification自定义选择sql语句,最终的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import com.proheng.gis.sqlserverEntity.SecHis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service;
import javax.persistence.EntityManager; import javax.persistence.Query; import java.util.Date; import java.util.List;
@Service public class SecHisService { @Autowired private SecHisRepository secHisRepository;
@Autowired @Qualifier("secondEntityManager") private EntityManager entityManager;
public List<SecHis> findAlarmRecrder(Integer sectionId, Date start_date,Date end_date, Double velocity_min,Double velocity_max,Double heat_min, Double heat_max,Double hLoss_min,Double hLoss_max) { List<SecHis> resultList=null; String sql=""; if(null != sectionId){ sql+=" sectionId ="+sectionId; } if(null != start_date&&end_date!=null){ sql+=" recordTime between "+start_date+" and "+end_date; } if(velocity_min==null&&velocity_max==null&&heat_min==null&&heat_max==null&&hLoss_max==null&&hLoss_min==null) { return null; } Query query= entityManager.createNativeQuery(sql,SecHis.class); resultList=query.getResultList();
return resultList; }
}
|
问题
(1) Unknown entity: com.proheng.gis.sqlserverEntity.SecHis
这个问题和下一个问题一起解决了,参考文章都没有用。
(2) 错误: 关系 “sechis” 不存在
在执行sql查询的时候,我明明定义了表名,但是最后执行的结果却和我的表名不相同,于是就报关系不存在,因为我数据库中的表的表名是secHis,而不是sechis。
我也同时定义了hibernate的命名策略。
1 2 3 4 5
| jpa: hibernate: naming: implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
|
于是我查了EntityManager相关资料
我突然想到了,我使用了多数据的配置,所以我这里的entityManager,应该使用我自定义的那个Bean,而不是系统自带的Bean
1 2 3 4
| @Bean(name = "secondEntityManager") public EntityManager entityManager() { return entityManagerFactoryBean().getObject().createEntityManager(); }
|
使用@Qualifier进行命名Bean的调用。
1 2 3
| @Autowired @Qualifier("secondEntityManager") private EntityManager entityManager;
|