您的位置:首页 > 编程语言 > Java开发

Spring Boot Jpa之构建动态SQL查询语句

2018-04-20 17:58 751 查看

Spring Boot Jpa之构建动态SQL查询语句

概念 

创建使用Java Persistence API的存储库是一个繁琐的过程,需要大量时间并需要大量样板代码。一种推荐的方式是使用元

1.JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。,而Hibernate是它的一种实现。除了Hibernate,还有EclipseLink(曾经的toplink),OpenJPA等可供选择,所以使用Jpa的一个好处是,可以更换实现而不必改动太多代码。2.Hibernate作为JPA的一种实现,jpa的注解已经是hibernate的核心,hibernate只提供了一些补充,而不是两套注解。hibernate对jpa的支持够足量,在使用hibernate注解建议使用jpa。

使用criteria 查询简单Demo

1.实体类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
import java.util.Date;

/**
* 学生 实体类
* @jason.zhong
*/
@Entity
@DynamicUpdate(true)
@DynamicInsert(true)
@Table(name="student")
@JsonIgnoreProperties(value={"hibernateLazyInitializer", "handler"})
public class StudentVo {

/**
* 主键
*/
@Id
@GenericGenerator(name = "uuidGenerator", strategy = "org.hibernate.id.UUIDGenerator") // 唯一性不受进程重启,机器重启等影响UUID生成方式
@GeneratedValue(generator = "uuidGenerator") // 使用上面定义的uuidGenerator作为主键生成器
@Column(name = "id", columnDefinition="CHAR(36)", unique = true, nullable = false, insertable = false, updatable = false)
private String id;

/**
* 创建时间
*/
@Column(name = "created_at", columnDefinition="DATETIME", nullable = false, updatable = false)
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date createdAt;

/**
* 修改时间
*/
@Column(name = "updated_at", columnDefinition="DATETIME")
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date updatedAt;

/**
* 学号
*/
@Column(name = "student_no", columnDefinition="INTEGER(10) UNSIGNED")
private Integer studentNo;

/**
* 姓名
*/
@Column(name="name", columnDefinition="VARCHAR(50)")
private String name;

/**
* 性别
*/
@Column(name="sex", columnDefinition="TINYINT(1) UNSIGNED")
private Short sex;

/**
* 年龄
*/
@Column(name = "age", columnDefinition="INTEGER(3) UNSIGNED")
private Integer age;

@Override
public String toString() {
return JSON.toJSONString(this);
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public Date getCreatedAt() {
return createdAt;
}

public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}

public Date getUpdatedAt() {
return updatedAt;
}

public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}

public Integer getStudentNo() {
return studentNo;
}

public void setStudentNo(Integer studentNo) {
this.studentNo = studentNo;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Short getSex() {
return sex;
}

public void setSex(Short sex) {
this.sex = sex;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}
}

2.服务

import java.util.List;

/**
* 学生 服务
* @jason.zhong
*/
public interface StudentService {

/**
* 获取学生信息
* @param student
* @return
*/
List<StudentVo> getAllStudent(StudentVo student);
}

3.实现类

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
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;

/**
* 学生 实现类
* @jason.zhong
*/
@Service
public class StudentServiceImpl implements StudentService {

/**
* entityManager
*/
@Autowired
private EntityManager entityManager;

/**
* 安全查询创建工厂
*/
private CriteriaBuilder cb = null;

/**
* 安全查询主语句
*/
private CriteriaQuery<StudentVo> criteriaQuery = null;

/**
* Root 定义查询的From子句中能出现的类型
*/
private Root<StudentVo> register = null;

public StudentServiceImpl(EntityManager entityManager) {
this.entityManager = entityManager;
this.cb = this.entityManager.getCriteriaBuilder();
this.criteriaQuery = this.cb.createQuery(StudentVo.class);
this.register = this.criteriaQuery.from(StudentVo.class);
}

@Override
public List<StudentVo> getAllStudent(StudentVo student) {
this.criteriaQuery.where(this.getPredicates(student));

TypedQuery<StudentVo> typedQuery = this.entityManager.createQuery(this.criteriaQuery);

List<StudentVo> result = typedQuery.getResultList();

return result;
}

/**
* 设置过滤条件
* @param student
* @return
*/
private Predicate[] getPredicates(StudentVo student) {
List<Predicate> predicate=new ArrayList<Predicate>();

//学号
if (student.getStudentNo() != null) {
predicate.add(this.cb.equal(this.register.<Integer> get("studentNo"), student.getStudentNo()));
}

//姓名
if (StringUtils.isNotBlank(student.getName())) {
predicate.add(this.cb.like(this.register.<String> get("name"), '%' + student.getName()+ '%'));
}

//性别
if (student.getSex() != null) {
predicate.add(this.cb.equal(this.register.<Integer> get("sex"), student.getSex()));
}

//年龄
if (student.getAge() != null) {
predicate.add(this.cb.le(this.register.<Integer> get("age"), student.getAge()));
}

return predicate.toArray(new Predicate[0]);
}
}

构建CriteriaQuery 实例API说明

1.CriteriaBuilder 安全查询创建工厂,创建CriteriaQuery,创建查询具体具体条件Predicate 等.

CriteriaBuilder是一个工厂对象,安全查询的开始.用于构建JPA安全查询.可以从EntityManager 或 EntityManagerFactory类中获得CriteriaBuilder. 

例如:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();

2.CriteriaQuery 安全查询主语句

[p]CriteriaQuery对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。 
它通过调用 CriteriaBuilder, createQuery 或CriteriaBuilder.createTupleQuery 获得。 
CriteriaBuilder就像CriteriaQuery 的工厂一样。 
CriteriaBuilder工厂类是调用EntityManager.getCriteriaBuilder 或 EntityManagerFactory.getCriteriaBuilder而得。 
StudentVo实体的 CriteriaQuery 对象以下面的方式创建:

例如:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<StudentVo> criteriaQuery = cb.createQuery(StudentVo.class);

3.Root 定义查询的From子句中能出现的类型

AbstractQuery是CriteriaQuery 接口的父类。它提供得到查询根的方法。 
Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似。 
Root实例也是类型化的,且定义了查询的FROM子句中能够出现的类型。 
查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。 
Criteria查询,可以有多个查询根。 
StudentVo实体的查询根对象可以用以下的语法获得 :

例如:

Root<StudentVo> register = criteriaQuery.from(StudentVo.class);

4.Predicate 过滤条件

过滤条件应用到SQL语句的FROM子句中。 
在criteria 查询中,查询条件通过Predicate 或Expression 实例应用到CriteriaQuery 对象上。 
这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上。 
CriteriaBuilder 也是作为Predicate 实例的工厂,Predicate 对象通过调用CriteriaBuilder 的条件方法( equal,notEqual, gt, ge,lt, le,between,like等)创建。 
Predicate 实例也可以用Expression 实例的 isNull, isNotNull 和 in方法获得,复合的Predicate 语句可以使用CriteriaBuilder的and, or andnot 方法构建。 
下面的代码片段展示了Predicate 实例查询学号为10010303的学生实例:[/p]例如:
Predicate predicate = cb.equal(register.<Integer> get("studentNo"), 10010303);
criteriaQuery.where(predicate);
5.排序结果
Criteria查询的结果能调用CriteriaQuery.orderBy方法排序,该方法接收一个Order对象做为参数。通过调用 CriteriaBuilder.asc 或 CriteriaBuilder.Desc,Order对象能被创建。以下代码片段中,StudentVo实例是基于name的升序排列。
criteriaQuery.orderBy(cb.asc(register.<String> get("name")));
6.分页
Criteria查询的结果能调用typedQuery.setFirstResult(int).setMaxResults(int)方法来进行分页,setFirstResult设置开始位置(下标从0开始),setMaxResults设置每页显示条数。
TypedQuery<StudentVo> typedQuery = entityManager.createQuery(criteriaQuery);
typedQuery.setFirstResult(0).setMaxResults(10);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: