- 首先是建一个实体类,打上注解,运行后自动在指定数据库中创建数据表。
- 配置文件换用.yml,这种格式层次分明,不易冗余;连接上数据库。
- 写一个dao接口继承一下JpaRepository,自定义方法可以自己添加。即可操作数据库。
自定义@Query查询
在dao中写自定义查询方法
/* 自定义方法实现模糊查询 */ @Query("select b from Book b where b.name like %?1%") //使用hql(操作对象),Book表示类型,?1传入第一个参数,前后都有%表示前后都可以是其他文字 public List<Book> findByName(String name); /* 原生sql */ @Query(value = "select * from book b where b.name=?1", nativeQuery = true) List<Book> findByName(String name); /* 自定义任意查询几条数据出来 */ @Query(value="select * from t_book order by RAND() limit ?1",nativeQuery = true) //默认是false,这里使用本地sql应开启 public List<Book> randomList(Integer n); @Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2") List<Book> findByPriceRange(long price1, long price2); @Query(value = "select name,author,price from Book b where b.name like %:name%") List<Book> findByNameMatch(@Param("name") String name); @Query(value = "select * from book b where b.name=?1", nativeQuery = true) List<Book> findByName(String name); /* 使用@Param注解注入参数 */ @Query("select name,author,price from Book b where b.name=:name and b.author=:author and b.price=:price") List<Book> findByNamedParam(@Param("name")String name,@Param("author")String author,@Param("price")String price);
对于like语句,参数为null时查不到数据;而动态查询则能获取全部数据
- 建议使用sql语句
定义Predicate动态查询、条件拼接
以下是扩充findAll进行动态查询。主要是考虑搜索条件可能并不俱全,有时甚至是空搜,空搜的话会把所有记录都查出来
public ModelAndView list2(Book book){ //自动封装 ModelAndView mav=new ModelAndView(); List<Book> bookList=bookDao.findAll(new Specification<Book>(){ /* 拼接条件 */ @Override public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cd) { //cb是条件构造器;query是一种高级查询;root可以获取数据库字段 Predicate predicate=cd.conjunction(); //conjunction:结合 //条件全为null的话查询全部数据 if(book!=null){ if(book.getName()!=null&&!"".equals(book.getName())){ //如果用户输入了此查询条件 predicate.getExpressions().add(cd.like(root.get("name"),"%"+book.getName()+"%")); //cb.like(root.get("name"):获取对应字段,按like规则查询,类似的还有equal等;后面为具体查询规则 } if(book.getAuthor()!=null&&!"".equals(book.getAuthor())){ predicate.getExpressions().add(cd.like(root.get("author"),"%"+book.getAuthor()+"%")); } } return predicate; //返回拼接好的查询条件 } }); mav.addObject("bookList",bookList); mav.setViewName("bookList"); return mav;
}
除了like查询语句还有其他:
//大于等于,可用于时间 predicate.getExpressions().add(cd.greaterThanOrEqualTo(root.get("createDate"), document.getFirstDate())); //小于等于 predicate.getExpressions().add(cd.lessThanOrEqualTo(root.get("createDate"), document.getLastDate()));
拼接+分页
除了拼接条件,一般还会伴随着分页。我们可以定义一个方法同时实现条件拼接和分页
//dao层 public interface DocumentRepository extends JpaRepository<Document,Integer>{ Page<Document> findAll(Specification<Document> specification, Pageable pageable); } //service层定义接口 public interface DocumentService { public Page<Document> findAll(UsefulDocument document, int pageNum, int pageSize); } //service实现层 @Override public Page<Document> findAll(UsefulDocument document, int pageNum, int pageSize) { //传入页码和每页容量 List<Sort.Order> orders = new ArrayList<Sort.Order>(); //排序规则 //搜索条件包含时间则按时间排 if (document.getFirstDate() != null) { orders.add(new Sort.Order(Sort.Direction.DESC, "createDate")); } else if (document.getLastDate() != null) { orders.add(new Sort.Order(Sort.Direction.DESC, "createDate")); } else { //否则按id排 orders.add(new Sort.Order(Sort.Direction.ASC, "id")); } //封装排序规则 Sort sort = new Sort(orders); //创建分页对象,传入页码、容量和排序规则三个条件 Pageable pageable=new PageRequest(pageNum,pageSize,sort); //调用findAll方法开始动态拼接(重写拼接方法并传入分页对象) Page<Document> documentList = documentRepository.findAll(new Specification<Document>() { @Override …… }, pageable); //这样,根据传入的pageNum不同即可返回不同数据 return documentList; }
其中的Sort与Order是这么用的:Sort是排序方法,Order则是定义排序规则。如果只有一种排序规则那可以这样写
Sort sort=new Sort(Sort.Direction.ASC,"age"); //第二个参数是实体类的属性(记住不是数据库的字段) //底层是把字段全部转换为String进行比较
- 但如果我想要先按age降序,再按grade升序,再按dnum降序怎么办?
- 这个时候就要用到org.springframework.data.domain.Sort.Order这个包下面的Order类了
根据排序规则我们分别建立三个Order如下:
//设置规则 Sort.Order order1=new Sort.Order(Sort.Direction.DESC,"age"); Sort.Order order2=new Sort.Order(Sort.Direction.ASC,"grade"); Sort.Order order3=new Sort.Order(Sort.Direction.DESC,"dnum"); //放入集合 List<Sort.Order> list=new ArrayList<>(); list.add(order1); list.add(order2); list.add(order3); //放到Sort里 Sort sort=new Sort(list);
排序
Iterable<T> findAll(Sort sort);
- 分页获得的对象集合其实就跟普通集合一样,可以用任何遍历方法来遍历
- documentList.getTotalElements() //全部查询结果总行数,Long型,测试时应该这么判断:is(4L) //后面加个L
- documentList.getTotalPages() //查询总页数
- Document document = documentList.getContent() //获取结果对象
- documents.getNumberOfElements() //本页结果条数
- documents.getNumber() //同上
- documents.getSize() //每页容量
- documents.getSort() //排序方法:字段 升/降
代码实例
- D:/SpringBootJpa/BookDao、BookController、entity/Book(增删查改图书)
- D:/civalWeb/LLCWEB/DocumentRepository、DocumentService、DocumentServiceImpl、DocumentRepositoryTest
SringBoot学习之Jpa主要是自定义查询和条件拼接与分页
最后更新时间:
这里可以写作者留言,标签和 hexo 中所有变量及辅助函数等均可调用,示例:http://47.107.237.149/2019/04/30/SringBoot学习之Jpa主要是自定义查询和条件拼接与分页/