首页

基于springframework的JpaDaoSupport的BaseJpaDao实现通用实体服务类EntityService

标签:spring,jpa,orm,JpaDaoSupport,CriteriaQuery,CriteriaBuilder,EntityManager,persistence,hibernate-jpa     发布时间:2017-03-13   

一、前言

通过springframework的orm的org.springframework.orm.jpa.support.JpaDaoSupport实现通用dao对象实现,实现通用的实体服务类EntityService,便于业务服务类继承复用

二、代码示例

1.继承dao依赖类BaseJpaDao,代码如下

import java.util.List;@b@import javax.persistence.EntityManager;@b@import javax.persistence.PersistenceException;@b@import javax.persistence.Query;@b@import javax.persistence.TypedQuery;@b@import javax.persistence.criteria.CriteriaBuilder;@b@import javax.persistence.criteria.CriteriaQuery;@b@import javax.persistence.criteria.Root;@b@import javax.persistence.criteria.Selection;@b@@b@import org.springframework.orm.jpa.JpaCallback;@b@import org.springframework.orm.jpa.JpaTemplate;@b@import org.springframework.orm.jpa.support.JpaDaoSupport;@b@import org.springframework.util.Assert;@b@@b@import com.woopa.common.persist.expression.JpaCriteriaExpressionParser;@b@import com.woopa.common.persist.expression.SQLLikeExpressionParser; @b@@b@public class BaseJpaDao extends JpaDaoSupport {@b@	@b@	JpaTemplate template;@b@	@b@	protected void initDao(){@b@		template = super.getJpaTemplate();@b@	}@b@	/**@b@	 * 分页查询@b@	 * @param <T>@b@	 * @param start@b@	 * @param limit@b@	 * @param queryString@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> List<T> queryForPage(final int start, final int limit,@b@			final String queryString, final Object... values){@b@		return template.executeFind(new JpaCallback<List<T>>(){@b@			@Override@b@			public List<T> doInJpa(EntityManager em) throws PersistenceException {@b@				Query query = em.createQuery(queryString);@b@				if(values != null){@b@					for(int i=0,len=values.length; i<len; i++){@b@						query.setParameter(i+1, values[i]);@b@					}@b@				}@b@				@b@				template.prepareQuery(query);@b@				@b@				return query.setFirstResult(start).setMaxResults(limit).getResultList();@b@			}@b@		});@b@	}@b@	/**@b@	 * 单对象查询,如查询结果集大于一条记录,则抛出异常@b@	 * @param <T>@b@	 * @param queryString@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> T queryForObject(final String queryString, final Object... values){@b@		return template.execute(new JpaCallback<T>(){@b@			@Override@b@			public T doInJpa(EntityManager em) throws PersistenceException {@b@				Query query = em.createQuery(queryString);@b@				if(values != null){@b@					for(int i=0,len=values.length; i<len; i++){@b@						query.setParameter(i+1, values[i]);@b@					}@b@				}@b@				@b@				template.prepareQuery(query);@b@				@b@				return (T) query.getSingleResult();@b@			}@b@		});@b@	}@b@	/**@b@	 * 简化表达式查询@b@	 * IN查询表达可写为propertyName@I5,表示IN的参数有5个,@b@	 * 同时参数values对应IN查询的参数必须是一个数组,数组长度应与@I后面的数字相等@b@	 * @param <T>@b@	 * @param entityClass 实体类@b@	 * @param expressions@b@	 * @param values@b@	 * @return @b@	 */@b@	public <T> List<T> queryByExpressions(final Class<T> entityClass, final String[] expressions, final Object... values){@b@		return template.executeFind(new JpaCallback<List<T>>(){@b@			@Override@b@			public List<T> doInJpa(EntityManager em)@b@					throws PersistenceException {@b@				TypedQuery<T> query = createQueryByExpressions(em, entityClass, expressions, values);@b@				@b@				template.prepareQuery(query);@b@				@b@				return query.getResultList();@b@			}@b@		});@b@	}@b@	/**@b@	 * 简化表达式查询@b@	 * IN查询表达可写为propertyName@I5,表示IN的参数有5个,@b@	 * 同时参数values对应IN查询的参数必须是一个数组,数组长度应与@I后面的数字相等@b@	 * @param <T>@b@	 * @param entityClass 实体类@b@	 * @param selectHeadString 自定义SELECT头@b@	 * @param expressions@b@	 * @param values@b@	 * @return @b@	 */@b@	public <T> T selectByExpressions(final Class entityClass, final String selectHeadString,@b@			final String[] expressions, final Object... values){@b@		Assert.notNull(expressions);@b@		Assert.notNull(expressions);@b@		Assert.notEmpty(expressions);@b@		@b@		return template.execute(new JpaCallback<T>(){@b@			@Override@b@			public T doInJpa(EntityManager em)@b@					throws PersistenceException {@b@				Query query = createQueryByExpressions(em, entityClass, selectHeadString, expressions, values);@b@				@b@				template.prepareQuery(query);@b@				@b@				return (T) query.getSingleResult();@b@			}@b@		});@b@	}@b@	/**@b@	 * 简化表达式查询@b@	 * IN查询表达可写为propertyName@I5,表示IN的参数有5个,@b@	 * 同时参数values对应IN查询的参数必须是一个数组,数组长度应与@I后面的数字相等@b@	 * @param <T>@b@	 * @param entityClass 实体类@b@	 * @param selectHeadString 自定义SELECT头@b@	 * @param expressions@b@	 * @param values@b@	 * @return @b@	 */@b@	public List selectMutilByExpressions(final Class entityClass, final String selectHeadString,@b@			final String[] expressions, final Object... values){@b@		Assert.notNull(expressions);@b@		Assert.notNull(expressions);@b@		Assert.notEmpty(expressions);@b@		@b@		return template.executeFind(new JpaCallback(){@b@			@Override@b@			public List doInJpa(EntityManager em)@b@					throws PersistenceException {@b@				Query query = createQueryByExpressions(em, entityClass, selectHeadString, expressions, values);@b@				@b@				template.prepareQuery(query);@b@				@b@				return query.getResultList();@b@			}@b@		});@b@	}@b@	@b@	@b@	/**@b@	 * 简化表达式分页查询@b@	 * IN查询表达可写为propertyName@I5,表示IN的参数有5个,@b@	 * 同时参数values对应IN查询的参数必须是一个数组,数组长度应与@I后面的数字相等@b@	 * @param <T>@b@	 * @param entityClass 实体类@b@	 * @param start@b@	 * @param limit@b@	 * @param expressions@b@	 * @param values@b@	 * @return @b@	 */@b@	public <T> List<T> queryForPageByExpressions(final Class<T> entityClass, final int start, final int limit, @b@			final String[] expressions, final Object... values){@b@		return template.executeFind(new JpaCallback<List<T>>(){@b@			@Override@b@			public List<T> doInJpa(EntityManager em)@b@					throws PersistenceException {@b@				TypedQuery<T> query = createQueryByExpressions(em, entityClass, expressions, values);@b@				@b@				template.prepareQuery(query);@b@				@b@				return query.setFirstResult(start).setMaxResults(limit).getResultList();@b@			}@b@		});@b@	}@b@	@b@	/**@b@	 * 辅助方法,根据查询表达式和参数创建Query对象@b@	 */@b@	private <T> TypedQuery<T> createQueryByExpressions(EntityManager em, Class<T> entityClass,@b@			String[] expressions, Object... values) throws PersistenceException {@b@		TypedQuery<T> query =  em.createQuery("select o from "+entityClass.getCanonicalName()+" o where 1=1"@b@				+ SQLLikeExpressionParser.parseToHQL(expressions), entityClass);@b@		@b@		if (null != values){@b@			int index = 1;@b@			for(int i=0,len=values.length; i<len; i++){@b@				//判断如果参数是一个对象数组, 则为IN查询参数,分离数组对象按一般参数处理@b@				if(values[i].getClass().isArray()){@b@					Object[] inValues = (Object[]) values[i];@b@					for (int j = 0,inLen=inValues.length; j < inLen; j++){@b@						query.setParameter(index ++, inValues[j]);@b@					}@b@				}else{@b@					query.setParameter(index ++, values[i]);@b@				}@b@			}@b@		}@b@		return query;@b@	}@b@	/**@b@	 * 辅助方法,根据查询表达式和参数创建Query对象, 可指定SELECT字段@b@	 */@b@	private Query createQueryByExpressions(EntityManager em, Class entityClass, String selectHeadString, @b@			String[] expressions, Object... values) throws PersistenceException {@b@		if(selectHeadString == null){@b@			selectHeadString = "select o";@b@		}@b@		Query query =  em.createQuery(selectHeadString+" from "+entityClass.getCanonicalName()+" o where 1=1"@b@				+ SQLLikeExpressionParser.parseToHQL(expressions));@b@		@b@		if (null != values){@b@			int index = 1;@b@			for(int i=0,len=values.length; i<len; i++){@b@				//判断如果参数是一个对象数组, 则为IN查询参数,分离数组对象按一般参数处理@b@				if(values[i].getClass().isArray()){@b@					Object[] inValues = (Object[]) values[i];@b@					for (int j = 0,inLen=inValues.length; j < inLen; j++){@b@						query.setParameter(index ++, inValues[j]);@b@					}@b@				}else{@b@					query.setParameter(index ++, values[i]);@b@				}@b@			}@b@		}@b@		return query;@b@	}@b@	/**@b@	 * 查询实体类,用查询表达式动态创建Criteria查询@b@	 * <b>注意:查询表达式有括号的括号内表达式有且仅能有两个</b>@b@	 * @param <T>@b@	 * @param entityClass 实体类@b@	 * @param expressions@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> List<T> queryForEntityBean(final Class<T> entityClass,@b@			final String[] expressions, final Object... values){@b@		return template.executeFind(new JpaCallback<List<T>>(){@b@			@Override@b@			public List<T> doInJpa(EntityManager em) throws PersistenceException {@b@				CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();@b@				CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass);@b@				@b@				JpaCriteriaExpressionParser.handleExpressions(entityClass, criteriaBuilder, @b@						criteriaQuery, expressions, values);@b@				@b@				@b@				return  em.createQuery(criteriaQuery).getResultList();@b@			}@b@		});@b@	}@b@	/**@b@	 * 查询实体类,用查询表达式动态创建Criteria查询,可指定只查询那些属性字段<br/>@b@	 * <b>查询表达式有括号的括号内表达式有且仅能有两个</b><br/>@b@	 * <b>注意:实体类必须有指定字段的构造方法<br/>@b@	 * 如实体类User,指定了name和password,则User必须有public User(String name,String password)构造方法</b>@b@	 * @param <T>@b@	 * @param entityClass 实体类@b@	 * @param includeFields 包含的字段@b@	 * @param expressions@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> List<T> queryForEntityBean(final Class<T> entityClass, final String[] includeFields,@b@			final String[] expressions, final Object... values){@b@		return template.executeFind(new JpaCallback<List<T>>(){@b@			@Override@b@			public List<T> doInJpa(EntityManager em) throws PersistenceException {@b@				CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();@b@				CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass);@b@				@b@				Root<T> root = JpaCriteriaExpressionParser.handleExpressions(entityClass, criteriaBuilder, @b@						criteriaQuery, expressions, values);@b@@b@				if(includeFields != null){@b@					Selection<? extends T>[] selections = new Selection[includeFields.length];@b@					for(int i=0,len=includeFields.length; i<len; i++){@b@						selections[i] = root.get(includeFields[i]);@b@					}@b@					criteriaQuery.multiselect(selections);@b@				}@b@				@b@				return  em.createQuery(criteriaQuery).getResultList();@b@			}@b@		});@b@	}@b@	/**@b@	 * 单对象SQL查询@b@	 * @param <T>@b@	 * @param sql@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> T getBySQL(final String sql, final Object... values){@b@		return getBySQL(null, sql, values);@b@	}@b@	@b@	/**@b@	 * 单实体对象SQL查询@b@	 * @param <T>@b@	 * @param entityClass@b@	 * @param sql@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> T getBySQL(final Class<T> entityClass, final String sql, final Object... values){@b@		return template.execute(new JpaCallback<T>(){@b@			@Override@b@			public T doInJpa(EntityManager em) throws PersistenceException {@b@				Query query = null;@b@				if(entityClass != null){@b@					query = em.createNativeQuery(sql, entityClass);@b@				}else{@b@					query = em.createNativeQuery(sql);@b@				}@b@				if(values != null){@b@					for(int i=0,len=values.length; i<len; i++){@b@						query.setParameter(i+1, values[i]);@b@					}@b@				}@b@				@b@				template.prepareQuery(query);@b@				@b@				return (T) query.getSingleResult();@b@			}@b@		});@b@	}@b@	@b@	/**@b@	 * SQL查询@b@	 * @param <T>@b@	 * @param sql@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> List<T> listBySQL(final String sql, final Object... values){@b@		return listBySQL(null, sql, values);@b@	}@b@	/**@b@	 * 实体对象集合SQL查询@b@	 * @param <T>@b@	 * @param entityClass@b@	 * @param sql@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> List<T> listBySQL(final Class<T> entityClass, final String sql, final Object... values){@b@		return template.executeFind(new JpaCallback<List<T>>(){@b@			@Override@b@			public List<T> doInJpa(EntityManager em) throws PersistenceException {@b@				Query query = null;@b@				if(entityClass != null){@b@					query = em.createNativeQuery(sql, entityClass);@b@				}else{@b@					query = em.createNativeQuery(sql);@b@				}@b@				if(values != null){@b@					for(int i=0,len=values.length; i<len; i++){@b@						query.setParameter(i+1, values[i]);@b@					}@b@				}@b@				@b@				template.prepareQuery(query);@b@				@b@				return query.getResultList();@b@			}@b@		});@b@	}@b@	/**@b@	 * SQL分页查询@b@	 * @param <T>@b@	 * @param sql@b@	 * @param start@b@	 * @param limit@b@	 * @param values@b@	 * @return@b@	 */@b@	public <T> List<T> listForPageBySQL(final String sql, final int start, final int limit,final Object... values){@b@		return template.executeFind(new JpaCallback<List<T>>(){@b@			@Override@b@			public List<T> doInJpa(EntityManager em) throws PersistenceException {@b@				Query query = em.createNativeQuery(sql);@b@				if(values != null){@b@					for(int i=0,len=values.length; i<len; i++){@b@						query.setParameter(i+1, values[i]);@b@					}@b@				}@b@				@b@				template.prepareQuery(query);@b@				@b@				return query.setFirstResult(start).setMaxResults(limit).getResultList();@b@			}@b@		});@b@	}@b@	/**@b@	 * 执行SQL@b@	 * @param sql@b@	 * @param values@b@	 * @return@b@	 */@b@	public int executeSQL(final String sql, final Object... values){@b@		return template.execute(new JpaCallback(){@b@			@Override@b@			public Integer doInJpa(EntityManager em) throws PersistenceException {@b@				Query query = em.createNativeQuery(sql);@b@				if(values != null){@b@					for(int i=0,len=values.length; i<len; i++){@b@						query.setParameter(i+1, values[i]);@b@					}@b@				}@b@				@b@				return query.executeUpdate();@b@			}@b@		});@b@	}@b@	/**@b@	 * 同一SQL不同参数批量执行,参数列表中对象可以是数组@b@	 * @param sql@b@	 * @param values @b@	 * @return@b@	 */@b@	public int[] batchExecuteSQL(final String sql, final List<? extends Object> values){@b@		return template.execute(new JpaCallback(){@b@			@Override@b@			public int[] doInJpa(EntityManager em) throws PersistenceException {@b@				Query query = em.createNativeQuery(sql);@b@				if(values != null){@b@					int[] resultInts = new int[values.size()];@b@					for(int i=0,len=values.size(); i<len; i++){@b@						Object value = values.get(i);@b@						if(value.getClass().isArray()){@b@							Object[] params = (Object[]) value;@b@							for(int j=0,plen=params.length; j<plen; j++){@b@								query.setParameter(j+1, params[j]);@b@							}@b@						}else{@b@							query.setParameter(1, value);@b@						}@b@						resultInts[i] = query.executeUpdate();@b@					}@b@					return resultInts;@b@				}@b@				@b@				return new int[]{query.executeUpdate()};@b@			}@b@		});@b@	}@b@}

2. 通用服务类接口IEntityService,如下所示 

import java.util.Collection;@b@import java.util.List; @b@import com.woopa.common.persist.PageBean; @b@@b@public interface IEntityService<E> {@b@	@b@	void persist(E entity);@b@	@b@	void merge(E entity);@b@	@b@	void remove(E entity);@b@	@b@	void remove(Collection<E> entities);@b@	@b@	List<E> listAll();@b@	@b@	E get(String expression, Object... values);@b@	@b@	E get(String[] expressions, Object... values);@b@	@b@	List<E> listByExpression(String expression, Object... values);@b@	@b@	List<E> listByExpressions(String[] expressions, Object... values);@b@	@b@	List<E> listPageByExpression(final int start, final int limit,@b@			final String expression, final Object... values);@b@	@b@	List<E> listPageByExpressions(final int start, final int limit,@b@			final String[] expressions, final Object... values);@b@	@b@	PageBean<Object> queryForPageBean(int start, int limit, @b@			String listQueryString, String totalQueryString, Object... values);@b@	@b@	PageBean<E> queryForPageBeanByExpressions(int start, int limit, @b@			String[] expressions, Object... values);@b@}

3.通用服务实现类EntityService,代码如下

import java.util.Collection;@b@import java.util.HashMap;@b@import java.util.Iterator;@b@import java.util.List;@b@import java.util.Map;@b@@b@import com.woopa.common.util.Assert;@b@import com.woopa.common.util.ReflectUtils;@b@import com.woopa.common.persist.PageBean; @b@ @b@public class EntityService<E> implements IEntityService<E> {@b@	@b@	private int batchFetchSize = 20; @b@	@b@	private BaseJpaDao dao;@b@	@b@	protected Class<E> entityClass;@b@	@b@	@b@	public EntityService(){@b@		entityClass = ReflectUtils.getSuperClassGenricType(getClass(), 0);@b@	}@b@@b@	public void persist(Collection<E> entities) {@b@		Assert.notNull(entities);@b@		@b@		Iterator<E> ite = entities.iterator();@b@		@b@		for(int i=0; i<entities.size() && ite.hasNext(); i++){@b@			if(i!=0 && i%batchFetchSize == 0){@b@				dao.template.flush();@b@			}@b@			dao.template.persist(ite.next());@b@		}@b@	}@b@@b@	public void persist(E entity) {@b@		Assert.notNull(entity);@b@		@b@		dao.template.persist(entity);@b@	}@b@	@b@	public void merge(E entity) {@b@		Assert.notNull(entity);@b@		@b@		dao.template.merge(entity);@b@	}@b@@b@	/**@b@	 * 更新一个实体对象@b@	 * <b>注意:必须在一个事务中使用此方法</b>@b@	 * @param entity@b@	 */@b@	protected void refresh(E entity) {@b@		Assert.notNull(entity);@b@		@b@		dao.template.refresh(entity);@b@	}@b@@b@	public void remove(E entity) {@b@		Assert.notNull(entity);@b@		@b@		dao.template.remove(entity);@b@	}@b@@b@	public void remove(Collection<E> entities) {@b@		Assert.notNull(entities);@b@		@b@		Iterator<E> ite = entities.iterator();@b@		@b@		for(int i=0; i<entities.size() && ite.hasNext(); i++){@b@			if(i!=0 && i%batchFetchSize == 0){@b@				dao.template.flush();@b@			}@b@			dao.template.remove(ite.next());@b@		}@b@	}@b@	@b@	public E get(String expression, Object... values){@b@		return get(new String[]{expression}, values);@b@	}@b@	@b@	public E get(String[] expressions, Object... values){@b@		List<E> list = dao.queryByExpressions(entityClass, expressions, values);@b@		@b@		return list != null && list.size() > 0 ? list.get(0) : null;@b@	}@b@@b@	public List<E> listAll() {@b@		return dao.template.find("from "+entityClass.getCanonicalName()+" o");@b@	}@b@@b@	protected List<E> list(String queryString, Object... values) {@b@		return dao.template.find(queryString, values);@b@	}@b@	@b@	protected List<E> list(String queryString, String[] namedParams,@b@			Object... values) {@b@		Map<String, Object> params = null;@b@		if(namedParams != null){@b@			params = new HashMap<String, Object>(namedParams.length);@b@			for(int i=0,len=namedParams.length; i<len; i++){@b@				params.put(namedParams[i], values[i]);@b@			}@b@		}@b@		return dao.template.findByNamedParams(queryString, params);@b@	}@b@	@b@	public List<E> listByExpression(String expression, Object... values){@b@		return listByExpressions(new String[]{expression}, values);@b@	}@b@	@b@	public List<E> listByExpressions(String[] expressions, Object... values){@b@		return dao.queryByExpressions(entityClass, expressions, values);@b@	}@b@@b@@b@	public List<E> listPageByExpression(final int start, final int limit,@b@			final String expression, final Object... values){@b@		@b@		return listPageByExpressions(start, limit, new String[]{expression}, values);@b@	}@b@	@b@	public List<E> listPageByExpressions(final int start, final int limit,@b@			final String[] expressions, final Object... values){@b@		return dao.queryForPageByExpressions(entityClass, start, limit, expressions, values);@b@	}@b@	@b@	protected List<E> listForPage(int start, int limit, String queryString,@b@			Object... values) {@b@		return dao.queryForPage(start, limit, queryString, values);@b@	}@b@@b@	protected long queryForLong(String queryString, Object... values) {@b@		return dao.queryForObject(queryString, values);@b@	}@b@@b@	protected int queryForInt(String queryString, Object... values) {@b@		return dao.queryForObject(queryString, values);@b@	}@b@	@b@	protected <T> T getUnique(String queryString, Object... values){@b@		return dao.queryForObject(queryString, values);@b@	}@b@@b@	protected <T> List<T> queryForList(String queryString,@b@			Object... values) {@b@		return dao.template.find(queryString, values);@b@	}@b@@b@	protected <T> List<T> queryForPage(int start, int limit,@b@			String queryString, Object... values) {@b@		return dao.queryForPage(start, limit, queryString, values);@b@	}@b@@b@	public PageBean<Object> queryForPageBean(int start, int limit, @b@			String listQueryString , String totalQueryString, Object... values){@b@		List<Object> list = dao.queryForPage(start, limit, listQueryString, values);@b@		@b@		long totalRecords = dao.queryForObject(totalQueryString, values);@b@		@b@		return new PageBean<Object>(start, limit, list, totalRecords);@b@	}@b@	@b@	public PageBean<E> queryForPageBeanByExpressions(int start, int limit, @b@			String[] expressions, Object... values){@b@		List<E> list = dao.queryForPageByExpressions(entityClass, start, limit, expressions, values);@b@		@b@		long totalRecords = dao.selectByExpressions(entityClass, "SELECT COUNT(*)", expressions, values);@b@		@b@		return new PageBean<E>(start, limit, list, totalRecords);@b@	}@b@	@b@	public BaseJpaDao getDao() {@b@		return dao;@b@	}@b@@b@	public void setDao(BaseJpaDao dao) {@b@		this.dao = dao;@b@	}@b@@b@	public int getBatchFetchSize() {@b@		return batchFetchSize;@b@	}@b@@b@	public void setBatchFetchSize(int batchFetchSize) {@b@		this.batchFetchSize = batchFetchSize;@b@	}@b@}
<<热门下载>>