创建使用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。
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;
}
}
import java.util.List;
/**
* 学生 服务
* @jason.zhong
*/
public interface StudentService {
/**
* 获取学生信息
* @param student
* @return
*/
List getAllStudent(StudentVo student);
}
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 criteriaQuery = null;
/**
* Root 定义查询的From子句中能出现的类型
*/
private Root 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 getAllStudent(StudentVo student) {
this.criteriaQuery.where(this.getPredicates(student));
TypedQuery typedQuery = this.entityManager.createQuery(this.criteriaQuery);
List result = typedQuery.getResultList();
return result;
}
/**
* 设置过滤条件
* @param student
* @return
*/
private Predicate[] getPredicates(StudentVo student) {
List predicate=new ArrayList();
//学号
if (student.getStudentNo() != null) {
predicate.add(this.cb.equal(this.register. get("studentNo"), student.getStudentNo()));
}
//姓名
if (StringUtils.isNotBlank(student.getName())) {
predicate.add(this.cb.like(this.register. get("name"), '%' + student.getName()+ '%'));
}
//性别
if (student.getSex() != null) {
predicate.add(this.cb.equal(this.register. get("sex"), student.getSex()));
}
//年龄
if (student.getAge() != null) {
predicate.add(this.cb.le(this.register. get("age"), student.getAge()));
}
return predicate.toArray(new Predicate[0]);
}
}
CriteriaBuilder是一个工厂对象,安全查询的开始.用于构建JPA安全查询.可以从EntityManager 或 EntityManagerFactory类中获得CriteriaBuilder.
例如:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。
它通过调用 CriteriaBuilder, createQuery 或CriteriaBuilder.createTupleQuery 获得。
CriteriaBuilder就像CriteriaQuery 的工厂一样。
CriteriaBuilder工厂类是调用EntityManager.getCriteriaBuilder 或 EntityManagerFactory.getCriteriaBuilder而得。
StudentVo实体的 CriteriaQuery 对象以下面的方式创建:
例如:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = cb.createQuery(StudentVo.class);
AbstractQuery是CriteriaQuery 接口的父类。它提供得到查询根的方法。
Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似。
Root实例也是类型化的,且定义了查询的FROM子句中能够出现的类型。
查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。
Criteria查询,可以有多个查询根。
StudentVo实体的查询根对象可以用以下的语法获得 :
例如:
Root register = criteriaQuery.from(StudentVo.class);
过滤条件应用到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的学生实例:
例如:
Predicate predicate = cb.equal(register. get("studentNo"), 10010303);
criteriaQuery.where(predicate);
Criteria查询的结果能调用CriteriaQuery.orderBy方法排序,该方法接收一个Order对象做为参数。通过调用 CriteriaBuilder.asc 或 CriteriaBuilder.Desc,Order对象能被创建。以下代码片段中,StudentVo实例是基于name的升序排列。
criteriaQuery.orderBy(cb.asc(register. get("name")));
TypedQuery typedQuery = entityManager.createQuery(criteriaQuery);
typedQuery.setFirstResult(0).setMaxResults(10);