在上文Hibernate使用中曾经提到过Hibernate是JPA实现的一个超集,但当时使用的都是原生Hibernate,在本文中我们将拥抱JPA规范,重构持久化层。
下面是ApplicationContxt文件
XML
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="sbeat.model" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <property name="jpaProperties"> <props> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> </bean> <tx:annotation-driven /> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="dataSource" ref="dataSource" /> </bean>
java
CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaQuery<T> query=cb.createQuery(clazz); //clazz是你想要转换的类型,就是你的Entity.claa,如果你查的是count,就是Long.claa Root<T> root=query.from(clazz); query.select(root);//选取实体 //选择的条件 List<Predicate> predicates=new ArrayList<Predicate>(); predicates.add(cb.equal(..)); predicates.add(..); ... query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
上面通过数组来组合与条件,还有一种方式:
java
Predicate predicate=cb.conjunction();//交集 predicate=cb.and(predicate,cb.equal(root.get("sex"),condition.get("sex"))); Predicate predicate=cb.disjunction();//并集 predicate=cb.or(predicate,cb.equal(root.get("sex"),condition.get("sex")));
JPA里面对类型控制比较严格,如下所示:
java
//比较大小 cb.gt(root.<Integer>get("degree"),(Integer) condition.get("degree")); //like cb.like(root.get("user").<String> get("nickName"),keyword) //in 条件 root.get("tags").in(condition.get("tag"))
对于关联映射,如果是ToOne,你可以连写get
root.get("user").get("account");
对于ToMany的,你可以使用Join
java
CriteriaQuery<Parent> criteria = cb.createQuery((Class<Parent>) Parent.class); Root<Parent> parent = criteria.from(Parent.class); criteria.select((Selection<T>) parent); SetJoin<Parent, Children> children = parent.joinSet("children", JoinType.LEFT); Predicate sexPredicate = cb.equal(children.get("sex"), "MALE"); parent.fetch(children); //parent.fetch("children");//try also this criteria.where(sexPredicate);
取分页内容
java
TypedQuery<T> typedQuery=entityManager.createQuery(query); typedQuery.setFirstResult((pageNum-1)*PAGE_SIZE); typedQuery.setMaxResults(PAGE_SIZE);
取查询数目
java
CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaQuery<Long> query=cb.createQuery(Long.class); query.select(cb.count(query.from(clazz)));//选取实体 return entityManager.createQuery(query).getSingleResult();
java
CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaUpdate<T> op=cb.createCriteriaUpdate(clazz); Root<T> root=op.from(clazz); op.set(fieldName, value); op.where(cb.equal(root.get(keyName), delta.get(keyName))); entityManager.createQuery(op).executeUpdate();
JPA的JPQL语句和Hibernate的HQL语句十分类似
java
Query query=entityManager.createQuery("SELECT r FROM Resume r WHERE r.user.id=:userId"); query.setParameter("id", userId); return (Resume) query.getSingleResult();
java
public interface GenericDAO<T> { public void insert(T t); public void update(T t); public void simpleUpdate(Map<Object, Object> delta); public void delete(T t); public T load(Long id); public void refresh(T t); public List<T> list(int pageNum); public Long count(); public List<T> findByCondition(Map<Object,Object> condition); public Long countByCondition(Map<Object,Object> condition); } @SuppressWarnings("unchecked") public class GenericDAOImpl<T> implements GenericDAO<T> { private Class<T> clazz; @PersistenceContext protected EntityManager entityManager; protected Session getCurrentSession() { return entityManager.unwrap(Session.class); } public GenericDAOImpl(){ //取得T的类型变量 ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); clazz = (Class<T>) type.getActualTypeArguments()[0]; } public void insert(T t) { entityManager.persist(t); } public void update(T t) { entityManager.merge(t); } public void simpleUpdate(Map<Object, Object> delta) { Field[] fields=clazz.getDeclaredFields(); CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaUpdate<T> op=cb.createCriteriaUpdate(clazz); Root<T> root=op.from(clazz); String keyName="id";//默认选择基准为Id //调整选择域 if(delta.containsKey("keyName")) keyName=(String) delta.get("keyName"); for(Field field:fields){ String fieldName=field.getName(); if(fieldName==keyName) continue; if(delta.containsKey(fieldName)){ op.set(fieldName, delta.get(fieldName)); } } op.where(cb.equal(root.get(keyName), delta.get(keyName))); entityManager.createQuery(op).executeUpdate(); } public void delete(T t) { entityManager.remove(t); } public T load(Long id) { return (T) entityManager.find(clazz, id); } public List<T> list(int pageNum) { CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaQuery<T> query=cb.createQuery(clazz); Root<T> root=query.from(clazz); query.select(root);//选取实体 query.orderBy(cb.desc(root.get("created")));//排序 TypedQuery<T> typedQuery=entityManager.createQuery(query); if(pageNum>0){ typedQuery.setFirstResult((pageNum-1)*SbeatConfig.PAGE_SIZE); typedQuery.setMaxResults(SbeatConfig.PAGE_SIZE); } return typedQuery.getResultList(); } public void refresh(T t) { entityManager.refresh(t); } public Long count() { //返回数目 CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaQuery<Long> query=cb.createQuery(Long.class); query.select(cb.count(query.from(clazz)));//选取实体 return entityManager.createQuery(query).getSingleResult(); } public List<T> findByCondition( Map<Object, Object> condition) { Field[] fields=clazz.getDeclaredFields(); CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaQuery<T> query=cb.createQuery(clazz); Root<T> root=query.from(clazz); query.select(root);//选取实体 //选择的条件 List<Predicate> predicates=new ArrayList<Predicate>(); for(Field field:fields){ String fieldName=field.getName(); if(condition.containsKey(fieldName)){ predicates.add(cb.equal(root.get(fieldName), condition.get(fieldName))); } } query.where(cb.and(predicates.toArray(new Predicate[predicates.size()]))); query.orderBy(cb.desc(root.get("created"))); TypedQuery<T> typedQuery=entityManager.createQuery(query); Integer pageNum=0; if(condition.containsKey(pageNum)){ pageNum=(Integer) condition.get("pageNum"); } if(pageNum>0){ typedQuery.setFirstResult((pageNum-1)*SbeatConfig.PAGE_SIZE); typedQuery.setMaxResults(SbeatConfig.PAGE_SIZE); } return typedQuery.getResultList(); } public Long countByCondition(Map<Object, Object> condition) { Field[] fields=clazz.getDeclaredFields(); CriteriaBuilder cb=entityManager.getCriteriaBuilder(); CriteriaQuery<Long> query=cb.createQuery(Long.class); Root<T> root=query.from(clazz); query.select(cb.count(root));//选取实体 List<Predicate> predicates=new ArrayList<Predicate>(); for(Field field:fields){ String fieldName=field.getName(); if(condition.containsKey(fieldName)){ predicates.add(cb.equal(root.get(fieldName), condition.get(fieldName))); } } query.where(cb.and(predicates.toArray(new Predicate[predicates.size()]))); return entityManager.createQuery(query).getSingleResult(); } }