一、JPA简介
JPA全称为Java Persistence API。JPA提供了一种简单高效的方式来管理Java对象(POJO)到关系型数据库的映射,此类Java对象成为JPA实体或简称实体。JPA和Hibernate之间的关系,可以简单的理解为JPA是标准接口,Hibernate是实现。从功能上来说,JPA现在就是Hibernate功能的一个子集。Hibernate 从3.2开始,就开始兼容JPA。Hibernate3.2获得了Sun TCK的 JPA(Java Persistence API) 兼容认证。
那么Hibernate是如何实现与JPA的这种关系的呢?Hibernate主要是通过三个组件来实现的,及hibernate-annotation、hibernate-entitymanager和hibernate-core。
- hibernate-annotation是Hibernate支持annotation方式配置的基础,它包括了标准的JPA annotation以及Hibernate自身特殊功能的annotation。
- hibernate-core是Hibernate的核心实现,提供了Hibernate所有的核心功能。
- hibernate-entitymanager实现了标准的JPA,可以把它看成hibernate-core和JPA之间的适配器,它并不直接提供ORM的功能,而是对hibernate-core进行封装,使得Hibernate符合JPA的规范。
总的来说,JPA是规范,Hibernate是框架,JPA是持久化规范,而Hibernate实现了JPA。
二、JPA的实体状态
实体对象的状态,在Hibernate有瞬时、持久、离线三种,而JPA里有new,managed,detached,removed,两者的这些状态都是一一对应的。
三、JPA配置
我们看看基于Hibernate提供的一个比较完整的JPA2.1的配置文件。
pom.xml:
UTF-8
org.hibernate
hibernate-core
5.1.0.Final
compile
org.hibernate
hibernate-entitymanager
5.1.0.Final
compile
org.hibernate
hibernate-c3p0
5.1.0.Final
runtime
com.mchange
c3p0
com.mchange
c3p0
0.9.5.2
runtime
org.hibernate
hibernate-ehcache
5.1.0.Final
runtime
net.sf.ehcache
ehcache
2.10.1
compile
persistence.xml:
org.hibernate.jpa.HibernatePersistenceProvider
四、JPA的基本使用
public class JPABase(){
//实体管理器
protected ThreadLocal entityManager;
public JPABase(ThreadLocal tlemImpl) {
this.entityManager= tlemImpl;
}
//得到当下的entityManager
public EntityManager currentEM() {
return (EntityManager)this.entityManager.get();
}
//新建一个entityManager
public EntityManager newEM() {
return ((EntityManager)this.entityManager.get()).getEntityManagerFactory().createEntityManager();
}
//启动事务
public void begin() throws IllegalStateException {
((EntityManager)this.entityManager.get()).getTransaction().begin();
}
//更新实体。当实体正在被容器管理时,你可以调用实体的set 方法对数据进行修改,在容器决定flush 时,更新的数据才会同步到数据库。
public void flush() throws TransactionRequiredException, PersistenceException {
((EntityManager)this.entityManager.get()).flush();
}
//提交事务
public void commit() throws IllegalStateException, RollbackException {
((EntityManager)this.entityManager.get()).getTransaction().commit();
}
//撤消(回滚)当前事务。即撤消事务启动后的所有数据库更新操作,从而不对数据库产生影响
public void rollback() throws IllegalStateException, PersistenceException {
((EntityManager)this.entityManager.get()).getTransaction().rollback();
}
//使当前事务只能被撤消
public void fail() throws IllegalStateException {
((EntityManager)this.entityManager.get()).getTransaction().setRollbackOnly();
}
//关闭事务
public void close() throws IllegalStateException {
((EntityManager)this.entityManager.get()).close();
this.entityManager.remove();
}
//给对象加锁
public void lock(Object o, LockModeType lock) throws IllegalStateException {
((EntityManager)this.entityManager.get()).lock(o, lock);
}
//添加实体,相当于add。通常persist之后会调用flush方法将实例插入数据库中
public void persist(Object o){
((EntityManager)this.entityManager.get()).persist(o);
}
//addOrUpdate
public User merge(Object o){
return ((EntityManager)this.entityManager.get()).merge(o);
}
//删除对象
public void delete(Object o){
((EntityManager)this.entityManager.get()).remove(o);
}
//返回Query对象,以执行JPQL语句
public Query query(String jpql) {
return ((EntityManager)this.entityManager.get()).createQuery(jpql);
}
//返回Query对象,以执行SQL语句
public Query createNativeQuery(String sql) {
return ((EntityManager)this.entityManager.get()).createNativeQuery(sql);
}
}
五、JPA的高级查询
首先让我们来了解一下以下类:
CriteriaQuery:查询构造器(查询语句拼装器)。组合要查询的内容和查询的条件。
CriteriaBuiller:CriteriaQuery工厂。
Root:查询根对象,定义查询的From子句中能出现的类型。CriteriaQuery.select(root)就可以拼装出select * from User 这一串。
Predicate:构造条件器。Predicate[] 可以支持多个过滤条件。
构造高级查询上下文:
public class CriteriaQueryContext {
public Class e;
public CriteriaQuery c;
public CriteriaBuilder b;
public Root r;
...
}
public CriteriaQueryContext criteria(Class class) {
CriteriaQueryContext ctx = new CriteriaQueryContext();
ctx.e = class;
ctx.b = ((EntityManager)this.entityManager.get()).getCriteriaBuilder();
ctx.c = ctx.b.createQuery(class);
ctx.r = ctx.c.from(class);
return ctx;
}
查询条件的使用
在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等方法构建。
下面的代码片段展示了Predicate 实例检查年龄大于24岁的员工实例:
public User getUserById(String userId)
{
CriteriaQueryContext c = this.criteria(User.class);
Predicate condition = c.b.equal(c.r.get("userid"), userId);
c.c.where(condition);
return(
this.entityManager.createQuery(c.c).getSingleResult();
);
}
Expression 用在查询语句的select,where和having子句中,该接口有 isNull, isNotNull 和 in方法。
CriteriaQueryContext c = this.criteria(User.class);
c.c.where(c.r.get(User.age).in(20, 24));
Criteria Query也允许开发者编写复合谓词,通过该查询可以为多条件测试下面的查询检查两个条件。
CriteriaQueryContext c = this.criteria(User.class);
c.c.where(
criteriaBuilder.and(
criteriaBuilder.like(c.r.get(User.name), "M%"),
criteriaBuilder.equal(c.r.get(User.age), 25)
));
我们也可以使用Predicate[]来添加多个过滤条件,Predicate[]使用模式为:
List predicatesList = new ArrayList();
predicatesList.add(.....Pridicate....)
criteriaQuery.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
Predicate[]的demo:
List predicatesList = new ArrayList();
Predicate p1 = c.b.in(c.r.get("id")).value(id);
predicatesList.add(p1);
Predicate p2 = c.b.in(c.r.get("name")).value(name);
predicatesList.add(p2);
c.c.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
c.c.orderBy(c.b.asc(c.r.get(age)));