<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
@Entity @NoArgsConstructor @Data public class ProductLoadRecord implements Serializable { private static final long serialVersionUID = 7676163793637224150L; @Id private Long id; private Long batchId; private String code; private String name; private String content; private String status; @Column(name = "datatime", columnDefinition = "DATETIME") private Date datatime; }
以上的@Entity、@Table、@Column注解的用法可以查閱網址:
https://www.cnblogs.com/softidea/p/6216722.html
public interface OrderRepository extends JpaRepository<OrderInfo,String> { @Query(value="SELECT * from order_info where lock_user_id=?1 AND status=1",nativeQuery=true) List<OrderInfo> selectMyOrders(String lockUserId); @Modifying @Transactional @Query(value="UPDATE order_info SET lock_user_id = NULL AND status = 0 WHERE order_id = ?1",nativeQuery = true) void unlockOrderByOrderId(String orderId); }
public Map select(Integer pageNum,Integer pageSize,Province province){ Page<Province> provinces = provinceRepository.findAll(Example.of(province), PageRequest.of(pageNum - 1, pageSize)); }
@Data @Entity @NoArgsConstructor public class OrderInfo implements Serializable { private static final long serialVersionUID = 1063821955023696541L; @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinColumn(name = "orderId") private List<GoodsInfo> goodsInfos; }
復雜的多條件查詢需要實現JpaSpecificationExecutor。
public interface OrderRepository extends JpaRepository<OrderInfo,String>, JpaSpecificationExecutor<OrderInfo> { }
service層
重寫specification。下面的代碼實現了多條件的兩表聯查分頁查詢。
通過條件構造中把各種條件拼接在一起,合並成總條件specification。
public Page<OrderInfo> getOrders(OrderPageQuery orderPageQuery){ Specification<OrderInfo> specification = new Specification<OrderInfo>() { @Override public Predicate toPredicate(Root<OrderInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) { // 建立子查詢 Subquery<GoodsInfo> goodsSubquery = query.subquery(GoodsInfo.class); Root<GoodsInfo> goodsInfoRoot = goodsSubquery.from(GoodsInfo.class); goodsSubquery.select(goodsInfoRoot.get("goodsSku")); List<Predicate> orderInfo = new ArrayList<Predicate>(); List<Predicate> goodsInfo = new ArrayList<Predicate>(); Date createStartDate = orderPageQuery.getCreateStartDate(); Date createEndDate = orderPageQuery.getCreateEndDate(); String custName = orderPageQuery.getCustName(); String goodsName = orderPageQuery.getGoodsName(); String custType = orderPageQuery.getCustType(); Integer status = orderPageQuery.getStatus(); if (createStartDate != null && createEndDate != null) { orderInfo.add(cb.between(root.get("createDt"),createStartDate,createEndDate)); } if(custName != null){ orderInfo.add(cb.like(root.get("custName"),"%"+custName+"%")); } if(goodsName != null){ goodsInfo.add(cb.like(goodsInfoRoot.get("goodsName"),"%"+goodsName+"%")); } if(custType != null){ orderInfo.add(cb.equal(root.get("custType").as(String.class),custType)); } if(status != null){ orderInfo.add(cb.equal(root.get("status").as(Integer.class),status)); } if(goodsInfo.size() > 0){ // 子查詢與父查詢相關聯 goodsInfo.add(cb.equal(goodsInfoRoot.get("orderId"),root.get("orderId"))); // 拼接過濾條件 goodsSubquery.where(goodsInfo.toArray(new Predicate[goodsInfo.size()])); // 和總條件拼接(exists的使用) orderInfo.add(cb.exists(goodsSubquery)); } return query.where(orderInfo.toArray(new Predicate[orderInfo.size()])).getRestriction(); } }; Page<OrderInfo> orders = orderRepository.findAll(specification, PageRequest.of(orderPageQuery.getPage() - 1, orderPageQuery.getPageSize())); return orders; }
可以參考下面的網址,一個復雜的查詢例子(包含常用的所有查詢方法):
https://www.cnblogs.com/g-smile/p/9177841.html
注意:但是這種實現JpaSpecificationExecutor,重寫specification的方法,不能單獨對表字段查詢,例如:
select id,code from order.......,只能相當於select *這樣。
實現方式
EntityManager:EntityManager是JPA中用於增刪改查的接口,它的作用相當於一座橋梁,連接內存中的java對象和數據庫的數據存儲。可以用getCriteriaBuilder()的方式獲取CriteriaBuilder對象。
CriteriaBuilder接口:用於構造標准查詢、復合條件、表達式、排序等。可以通過createQuery的方式獲取CriteriaQuery實例。
CriteriaQuery接口:代表一個specific的頂層查詢對象,它包含着查詢的各個部分,比如:select 、from、where、group by、order by。
Root接口:代表Criteria查詢的根對象,定義了實體類型,能為將來導航獲得想要的結果,它與SQL查詢中的FROM子句類似 。
實現代碼
//通過注解@PersistenceContext注入的方式來獲得EntityManager對象 @PersistenceContext private EntityManager entityManager; public void multiQueryStudent (StudentParam studentParam) { //studentParam:自定義的查詢參數體 List<String> schoolList = studentParam.getSchoolList(); //查詢條件:學校List String startDate = studentParam.getStartDate(); //查詢條件:出生日期-起 String endDate = studentParam.getEndDate(); //查詢條件:出生日期-止 CriteriaBuilder cb = entityManager.getCriteriaBuilder(); //StudentScoreSum指定了查詢結果返回至自定義對象 CriteriaQuery<StudentScoreSum> query = cb.createQuery(StudentScoreSum.class); Root<StudentEntity> root = query.from(StudentEntity.class); Path<String> schoolPath = root.get("school"); Path<Integer> scorePath = root.get("score"); Path<String> namePath = root.get("name"); Path<String> birthdayPath = root.get("birthday"); //拼接where條件 List<Predicate> predicateList = new ArrayList<Predicate>(); if (schoolList != null && schoolList.size() > 0) { CriteriaBuilder.In<String> in = cb.in(schoolPath); for (String school : schoolList) { in.value(school); } predicateList.add(in); } if (startDate != null && !"".equals(startDate)) { predicateList.add(cb.greaterThan(birthdayPath, startDate)); } if (endDate != null && !"".equals(endDate)) { predicateList.add(cb.lessThan(birthdayPath, endDate)); } Predicate[] predicates = new Predicate[predicateList.size()]; predicates = predicateList.toArray(predicates); //加上where條件 query.where(predicates); //指定查詢項,select后面的東西 query.multiselect(schoolPath, cb.count(root).as(Integer.class), cb.sum(scorePath), namePath, cb.max(scorePath)); //按學校分組 query.groupBy(schoolPath); //排序 query.orderBy(cb.desc(cb.max(scorePath))); //篩選第一名成績大於80分的 query.having(cb.greaterThan(cb.max(scorePath), 80)); TypedQuery<StudentScoreSum> q = entityManager.createQuery(query); List<StudentScoreSum> result = q.getResultList(); for (StudentScoreSum studentScoreSum : result) { //打印查詢結果 System.out.println(studentScoreSum.toString()); } }
具體可以參考下面的網址:
https://blog.csdn.net/liuyunyihao/article/details/81255731
注意:這種實現方式不能返回分頁Page給前端,會把所有的數據查詢出來,效率慢。
