前提
- 1、需要实体类与数据库中的指定表绑定,并绑定指定列,如下
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name = "tb_label") //绑定数据库中的那张表,如果有多个主键,就在对应上面加上该注解
@Entity //将改实体类注入容器中
public class Label implements Serializable {
@Id // 主键必须要有的,与数据库中的主键绑定
private String id;
@Column(name = "labelName") //如果改字段与数据库中的列名不一样,自己可以指定
private String labelname;
- 2、写一个接口继承JpaRepository<Label,String>
public interface LabelDao extends JpaRepository<Label,String>, JpaSpecificationExecutor<Label> {
}
参数 | 说明 |
---|---|
第一个参数 | 绑定的实体类 |
第二个参数 | ,该实体类主键的类型 |
该接口可以实现基本的增删该查,但是如果还需要条件查询,则还需要继承另一个接口
JpaSpecificationExecutor<Label;>
1、简单的增删改查
使用刚刚的接口即可
labelDao.save(Label label) //增,改
label.deleteById(String id) //删
label.findById(String id) //查
2、条件查询
如果只是一个条件,完成后就可以直接返回,如果是多个则需要使用组合,下面是3个条件
/**
* 构建查询条件
* @param label 查询的条件label对象
* @return
*/
public Specification<Label> createSpecification(Label label){
return new Specification<Label>() {
/**
*
* @param root 获取匹配的对象条件
* @param cq order by , group by 等。一般用不到,一般我们直接写sql语句
* @param cb 链接参数对象
* @return
*/
@Override
public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
List<Predicate> predicateList = new ArrayList<>();
if(!StringUtils.isEmpty(label.getLabelname())){
Predicate predicate = cb.like(root.get("labelname").as(String.class), "%" + label.getLabelname() + "%");
predicateList.add(predicate);
}
if(!StringUtils.isEmpty(label.getState())){
Predicate predicate = cb.equal(root.get("state").as(String.class), label.getState());
predicateList.add(predicate);
}
if(!StringUtils.isEmpty(label.getRecommend())){
Predicate predicate = cb.equal(root.get("recommend").as(String.class),label.getRecommend() );
predicateList.add(predicate);
}
// Predicate[] array = (Predicate[]) predicateList.toArray();
// 直接使用会出现如下错误
// [Ljava.lang.Object; cannot be cast to [Ljavax.persistence.criteria.Predicate;
Predicate[] array = new Predicate[predicateList.size()];
predicateList.toArray(array);
return cb.and(array);
}
};
}
/**
* 根据条件查询所有的标签
* @param label 条件,即label实体类
* @return
*/
public List<Label> findSearch(Label label){
Specification<Label> specification = createSpecification(label);
//select * from tb_label where labelname like "%条件%" and state=条件 and recommed = 条件
return labelDao.findAll(specification);
}
3、分页条件查询
分页查询只是在find方法参数里面加了一个另一个参数,如下即可(页码内部是从0开始的,如果从前端发过来是1,则需要 -1 来完成操作)
/**
* 根据条件查询标签信息,并分页
* @param label 查询的条件
* @param page 查询多少页,从第1页开始
* @param size 每页查询多少条
* @return page<Label>
*/
public Page<Label> findSearchPage(Label label,int page,int size){
//因为代码内部是从0开始的页数
PageRequest pageRequest = PageRequest.of(page - 1, size);
Specification<Label> specification = createSpecification(label);
//返回的是 Page<T>
return labelDao.findAll(specification, pageRequest);
}
后面可以通过
Page<Label> pageList = labelService.findSearchPage(label, page, size);
pageList.getTotalElements() //总的数据量
pageList.getContent() //获取该次分页查询的数据
4、通过命名规则来完成查询
在之前的空的接口中,根据命名规则写一个方法
#查询状态为2并以创建日期降序排序,查询前4条记录
List<Label> findTop4ByStateOrderByCreatetimeDesc(String state);
-----------------------------------------------------
其内部就会根据你的命名规则去查询
接下来service层就可以去调用了
5、通过写sql语句来完成查询
前面的方法都只能单表查询,如果多表的话,只能自己写sql语句去执行了!
如果只是查询用一个query即可,但是如果需要修改数据就再加一个注解modifying
以及在service层加上(@transactional
(import org.springframework.transaction.annotation.Transactional;))或者直接加在sql语句这里也行!!
/**
* 根据标签id 查询该标签下的 最新问答列表,并分页
* @param labelId 标签id
* @param pageable 分页数据
* @return
*/
// @Modifying
@Query(value = "SELECT * FROM tb_pl pl ,tb_problem pro WHERE pl.problemid = pro.id AND pl.labelid = ? ORDER BY pro.createtime DESC",
nativeQuery = true)
Page<Problem> findNewProblemList(String labelId, Pageable pageable);