配置文件:spring-jpa.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <!-- BoneCP教程见http://www.cnblogs.com/zhwl/archive/2013/07/23/3208550.html --> <!-- JPA实体管理器工厂 --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="${springJPA.dataSource}" /> <property name="persistenceProvider" ref="persistenceProvider" /> <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> <property name="jpaDialect" ref="jpaDialect" /> <property name="packagesToScan" value="${springJPA.packagesToScan}" /> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop> <prop key="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</prop> <prop key="hibernate.max_fetch_depth">3</prop> <prop key="hibernate.jdbc.fetch_size">18</prop> <prop key="hibernate.jdbc.batch_size">10</prop> <prop key="hibernate.hbm2ddl.auto">${springJPA.jpaProperties.hibernate.hbm2ddl.auto}</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">false</prop> <prop key="javax.persistence.validation.mode">none</prop> <!-- 查询缓存 --> <prop key="hibernate.cache.use_query_cache">true</prop> <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> <!--若为ALL,则默认全部开启二级缓存 ,实体上的@cacheable都不用打--> <prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop> <prop key="hibernate.generate_statistics">true</prop> </props> </property> </bean> <!-- 用于指定持久化实现厂商类 --> <bean id="persistenceProvider" class="org.hibernate.ejb.HibernatePersistence" /> <!-- 用于设置JPA实现厂商的特定属性 --> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="${springJPA.jpaVendorAdapter.database}" /> </bean> <!-- 用于指定一些高级特性 --> <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- 启用 annotation事务--> <tx:annotation-driven /> <!-- 配置Spring Data JPA扫描目录--> <jpa:repositories base-package="com.wonders.**.dao" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" repository-impl-postfix="Impl" factory-class="com.wonders.frame.core.dao.DefaultRepositoryFactoryBean"> </jpa:repositories> </beans>
工厂bean:DefaultRepositoryFactoryBean
/** * */ package com.wonders.frame.core.dao; import java.io.Serializable; import javax.persistence.EntityManager; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; import org.springframework.data.repository.core.support.RepositoryFactorySupport; /** * * */ public class DefaultRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> { /** * Returns a {@link RepositoryFactorySupport}. * * @param entityManager * @return */ protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { return new DefaultRepositoryFactory(entityManager); } }
工厂类:DefaultRepositoryFactory
package com.wonders.frame.core.dao; import java.io.Serializable; import javax.persistence.EntityManager; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.querydsl.QueryDslUtils; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.util.Assert; import com.wonders.frame.core.dao.impl.GenericRepositoryImpl; /** * * */ public class DefaultRepositoryFactory extends JpaRepositoryFactory { private final EntityManager entityManager; public DefaultRepositoryFactory(EntityManager entityManager) { super(entityManager); Assert.notNull(entityManager); this.entityManager = entityManager; } @Override protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) { //TODO JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainClass()); return new GenericRepositoryImpl(entityInformation, entityManager); // custom implementation } @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { return GenericRepositoryImpl.class; } }
自定义扩展接口:GenericRepository
package com.wonders.frame.core.dao; import java.io.Serializable; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import javax.persistence.Query; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.transaction.annotation.Transactional; import com.wonders.frame.core.model.vo.SimplePage; /** * @ * 针对spring data jpa所提供的接口{@link JpaRepository}再次扩展 * @NoRepositoryBean是必须的 */ @NoRepositoryBean public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID>,JpaSpecificationExecutor<T> { List<T> findAll(HashMap<String,Object> queryParams, LinkedHashMap<String, String> orderby); SimplePage<T> findByPage(HashMap<String,Object> queryParams, LinkedHashMap<String, String> orderby, Integer pageSize,Integer pageNum); SimplePage<T> findByPageWithSql(String sql, HashMap<String, Object> queryParams, Integer pageSize, Integer pageNum); SimplePage<T> findByPageWithWhereHql(String whereHql, HashMap<String, Object> queryParams, Integer pageSize, Integer pageNum); SimplePage<T> findByPage(HashMap<String, Object> queryParams, String orderby, Integer pageSize, Integer pageNum); /** * * 根据sql语句查询,结果是实体的集合 * * @param sql * * @param entityClass * * @return */ public List<T> findAllBySql(Class<T> entityClass, String sql); public String getUniqueResultBySql(String sql,HashMap<String,Object> queryParams); //public List<T> findByAttachIds(String[] ids); // @Transactional // public void updateModelNameAndModelId(String modelName, Integer modelId, String[] ids); }
package com.wonders.frame.core.dao.impl; import java.io.Serializable; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.Query; import org.apache.log4j.Logger; import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; import com.wonders.frame.core.dao.GenericRepository; import com.wonders.frame.core.model.vo.PageInfo; import com.wonders.frame.core.model.vo.SimplePage; import com.wonders.frame.core.utils.ReflectUtil; /** * {@link GenericRepository}接口实现类,并在{@link SimpleJpaRepository}基础上扩展。 * @param <T> ORM对象 * @param <ID> 主键ID */ @NoRepositoryBean // 必须的 public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements GenericRepository<T, ID> { static Logger logger = Logger.getLogger(GenericRepositoryImpl.class); private final EntityManager em; private final Class<T> entityClass; private final String entityName; /** * 构造函数 * @param domainClass * @param em */ public GenericRepositoryImpl(final JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); this.em = entityManager; this.entityClass=entityInformation.getJavaType(); this.entityName=entityInformation.getEntityName(); } /** * 构造函数 * @param domainClass * @param em */ public GenericRepositoryImpl(Class<T> domainClass, EntityManager em) { this(JpaEntityInformationSupport.getMetadata(domainClass, em), em); } @Override public List<T> findAll(HashMap<String,Object> queryParams, LinkedHashMap<String, String> orderby){ String whereHql=buildWhereQuery(queryParams); String orderHql=buildOrderby(orderby); String hql = "select o from "+entityName+" o where o.removed=0"; Query query=createQuery(hql+whereHql+orderHql,queryParams); List<T> list=(List<T>)query.getResultList(); return list; } @Override public SimplePage<T> findByPage(HashMap<String,Object> queryParams, LinkedHashMap<String, String> orderby, Integer pageSize,Integer pageNum) { return findByPage(queryParams,buildOrderby(orderby), pageSize, pageNum); } @Override public SimplePage<T> findByPage(HashMap<String,Object> queryParams, String orderby, Integer pageSize,Integer pageNum) { String whereHql=buildWhereQuery(queryParams); String orderHql=orderby; String hql="select count(*) from "+ entityName+ " o where o.removed=0 "; Query query=createQuery(hql+whereHql+orderHql,queryParams); PageInfo pageInfo=new PageInfo(((Long)query.getSingleResult()).intValue(),pageSize); pageInfo.refresh(pageNum); hql = "select o from "+ entityName+ " o where o.removed=0 "; query=createQuery(hql+whereHql+orderHql,queryParams); query.setFirstResult(pageInfo.getStartRecord()).setMaxResults(pageInfo.getPageSize()); return new SimplePage<T>(pageInfo,query.getResultList()); } private Query createQuery(String hql,HashMap<String,Object> queryParams){ Query query = em.createQuery(hql); setQueryParams(query, queryParams); return query; } @Override public SimplePage<T> findByPageWithWhereHql(String whereHql, HashMap<String,Object> queryParams, Integer pageSize,Integer pageNum) { String hql="select count(*) from "+ entityName+ " o where o.removed=0 "; if(whereHql==null){ whereHql=""; } Query query = em.createQuery(hql+whereHql); setQueryParams(query, queryParams); PageInfo pageInfo=new PageInfo(((Long)query.getSingleResult()).intValue(),pageSize); pageInfo.refresh(pageNum); hql = "select o from "+ entityName+ " o where o.removed=0 "; query = em.createQuery(hql+whereHql); setQueryParams(query, queryParams); query.setFirstResult(pageInfo.getStartRecord()).setMaxResults(pageInfo.getPageSize()); return new SimplePage<T>(pageInfo,query.getResultList()); } @Override public SimplePage<T> findByPageWithSql(String sql, HashMap<String,Object> queryParams, Integer pageSize,Integer pageNum) { Query query = em.createNativeQuery("select count(*) from ("+sql+")"); setQueryParams(query, queryParams); PageInfo pageInfo=new PageInfo(((Long)query.getSingleResult()).intValue(),pageSize); pageInfo.refresh(pageNum); query = em.createNativeQuery(sql); setQueryParams(query, queryParams); query.setFirstResult(pageInfo.getStartRecord()).setMaxResults(pageInfo.getPageSize()); return new SimplePage<T>(pageInfo,query.getResultList()); } private void setQueryParams(Query query, HashMap<String, Object> queryParams){ if(queryParams!=null && queryParams.size()>0){ for(String key : queryParams.keySet()){ Class clazz=ReflectUtil.getFieldType(this.entityClass, key.replaceAll("_s","").replaceAll("_e", "").replaceAll("_in", "")); if(clazz!=null && clazz.equals(String.class) && !key.endsWith("_in")){ query.setParameter(key, '%'+queryParams.get(key).toString()+'%'); }else{ query.setParameter(key, queryParams.get(key)); } } } } private String buildOrderby(LinkedHashMap<String, String> orderby) { // TODO Auto-generated method stub StringBuffer orderbyql = new StringBuffer(""); if(orderby!=null && orderby.size()>0){ orderbyql.append(" order by "); for(String key : orderby.keySet()){ orderbyql.append("o.").append(key).append(" ").append(orderby.get(key)).append(","); } orderbyql.deleteCharAt(orderbyql.length()-1); } return orderbyql.toString(); } private String buildWhereQuery(HashMap<String, Object> queryParams) { // TODO Auto-generated method stub StringBuffer whereQueryHql = new StringBuffer(""); if(queryParams!=null && queryParams.size()>0){ for(String key : queryParams.keySet()){ // if(key.equalsIgnoreCase("id")){ // whereQueryHql.append(" and ").append("o.").append(key).append(" in(:").append(key).append(")"); // }else if(key.endsWith("_s")){ whereQueryHql.append(" and ").append("o.").append(key.replace("_s", "")).append(" >=:").append(key); }else if(key.endsWith("_e")){ whereQueryHql.append(" and ").append("o.").append(key.replace("_e", "")).append(" <=:").append(key); }else if(key.endsWith("_in")){ whereQueryHql.append(" and ").append("o.").append(key.replace("_in", "")).append(" in:").append(key); }else{ Class clazz=ReflectUtil.getFieldType(this.entityClass, key); if(clazz!=null && clazz.equals(String.class)){ whereQueryHql.append(" and ").append("o.").append(key).append(" like :").append(key); }else{ whereQueryHql.append(" and ").append("o.").append(key).append(" =:").append(key); } } } } return whereQueryHql.toString(); } @Override public List<T> findAllBySql(Class<T> entityClass, String sql) { //创建原生SQL查询QUERY实例,指定了返回的实体类型 Query query = em.createNativeQuery(sql,entityClass); //执行查询,返回的是实体列表, List<T> EntityList = query.getResultList(); return EntityList; } public String getUniqueResultBySql(String sql,HashMap<String,Object> queryParams){ Query query = em.createNativeQuery(sql); for(String key : queryParams.keySet()){ query.setParameter(key, queryParams.get(key)); } //执行查询,返回的是实体列表, String result = (String)query.getSingleResult(); return result; } // public List<T> findByAttachIds(String[] ids){ // String idsString =""; // if(ids==null || ids.length<1) return null; // for(int i=0; i<ids.length; i++){ // try { // Long.valueOf(ids[i]); // } catch (NumberFormatException e) { // return null; // } // idsString += ids[i] +","; // } // idsString = idsString.substring(0,idsString.length()-1); // String hql ="from Attach t where t.removed='0' and t.id in ("+idsString+")"; // Query query=createQuery(hql, null); // List<T> list=(List<T>)query.getResultList(); // return list; // } // // @Transactional // public void updateModelNameAndModelId(String modelName, Integer modelId, String[] ids){ // String idsString =""; // if(ids==null || ids.length<1) return; // for(int i=0; i<ids.length; i++){ // try { // Long.valueOf(ids[i]); // } catch (NumberFormatException e) { // return; // } // idsString += ids[i] +","; // } // idsString = idsString.substring(0,idsString.length()-1); // String hql ="update Attach a set a.modelName ="+modelName+", a.modelId ="+modelId+" where a.id in ("+idsString+")"; // createQuery(hql, null).executeUpdate(); // } }
使用范例:自定义接口继承 扩展接口
package com.wonders.frame.cpq.dao; import java.util.List; import javax.persistence.QueryHint; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.QueryHints; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; import com.wonders.frame.core.dao.GenericRepository; import com.wonders.frame.cpq.model.bo.CpqMain; public interface CpqMainDao extends GenericRepository<CpqMain, Integer>{ public Page<CpqMain> findAll(Pageable pageable); @Query("select a from CpqMain a where a.removed = 0 and a.id =?") public CpqMain findById(Integer id); @Transactional @Modifying @Query("update CpqMain a set a.removed = 1 where a.id =:id") public Integer removeById(@Param("id")Integer id); @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") }) public List<CpqMain> findAll(); }