package com.idoo.iosms.core.hibernate.hibernate;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.transform.ResultTransformer;
import org.springframework.util.Assert;
import com.idoo.iosms.core.hibernate.PageGenericDao;
import com.idoo.iosms.core.utils.Page;
import com.idoo.iosms.core.utils.PropertyFilter;
import com.idoo.iosms.core.utils.ReflectionUtils;
import com.idoo.iosms.core.utils.PropertyFilter.MatchType;
public class HibernateDao<T, PK extends Serializable> extends
HibernateGenericDao<T, PK> implements PageGenericDao<T, PK> {
public HibernateDao() {
super();
}
public HibernateDao(final SessionFactory sessionFactory,
final Class<T> entityClass) {
super(sessionFactory, entityClass);
}
@SuppressWarnings("unchecked")
public Page<T> queryPage(Page<T> page, String hql, Object... values) {
// TODO Auto-generated method stub
Assert.notNull(page, "page不能为空");
Query q = createQuery(hql, values);
if (page.isAutoCount()) {
int totalCount = countHqlResult(hql, values);
page.setTotalCount(totalCount);
}
setPageParameter(q, page);
List<T> result = q.list();
page.setResultList(result);
return page;
}
@SuppressWarnings("unchecked")
public Page<T> queryPage(Page<T> page, String hql,
Map<String, Object> values) {
// TODO Auto-generated method stub
Assert.notNull(page, "page不能为空");
Query q = createQuery(hql, values);
if (page.isAutoCount()) {
int totalCount = countHqlResult(hql, values);
page.setTotalCount(totalCount);
}
setPageParameter(q, page);
List<T> result = q.list();
page.setResultList(result);
return page;
}
@SuppressWarnings("unchecked")
public Page<T> queryPage(Page<T> page, Criterion... criterions) {
// TODO Auto-generated method stub
Assert.notNull(page, "page不能为空");
Criteria c = createCriteria(criterions);
if (page.isAutoCount()) {
int totalCount = countCriteriaResult(c);
page.setTotalCount(totalCount);
}
setPageParameter(c, page);
List<T> result = c.list();
page.setResultList(result);
return page;
}
public Page<T> queryPage(final Page<T> page,
final List<PropertyFilter> filters) {
Criterion[] criterions = buildPropertyFilterCriterions(filters);
return queryPage(page, criterions);
}
@SuppressWarnings("unchecked")
public int countCriteriaResult(Criteria c) {
// TODO Auto-generated method stub
CriteriaImpl impl = (CriteriaImpl) c;
// 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作
Projection projection = impl.getProjection();
ResultTransformer transformer = impl.getResultTransformer();
List<CriteriaImpl.OrderEntry> orderEntries = null;
try {
orderEntries = (List<CriteriaImpl.OrderEntry>) ReflectionUtils
.getFieldValue(impl, "orderEntries");
ReflectionUtils.setFieldValue(impl, "orderEntries",
new ArrayList<Object>());
} catch (Exception e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
// 执行Count查询
int totalCount = (Integer) c.setProjection(Projections.rowCount())
.uniqueResult();
// 将之前的Projection,ResultTransformer和OrderBy条件重新设回去
c.setProjection(projection);
if (projection == null) {
c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
}
if (transformer != null) {
c.setResultTransformer(transformer);
}
try {
ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries);
} catch (Exception e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
return totalCount;
}
public int countHqlResult(String hql, Object... values) {
String fromHql = hql;
// select子句与order by子句会影响count查询,进行简单的排除.
fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
fromHql = StringUtils.substringBefore(fromHql, "order by");
String selectHql = "*";
// 如果含有 distinct 描述符,进行简单处理
if (StringUtils.indexOf(hql, "distinct") != -1) {
selectHql = StringUtils.substringBetween(hql, "select", "from")
.trim();
}
String countHql = "select count(" + selectHql + ") " + fromHql;
try {
Long count = findUnique(countHql, values);
return count.intValue();
} catch (Exception e) {
throw new RuntimeException("hql can't be auto count, hql is:"
+ countHql, e);
}
}
public int countHqlResult(String hql, Map<String, Object> values) {
// TODO Auto-generated method stub
String fromHql = hql;
// select子句与order by子句会影响count查询,进行简单的排除.
fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
fromHql = StringUtils.substringBefore(fromHql, "order by");
String countHql = "select count(*) " + fromHql;
try {
Long count = findUnique(countHql, values);
return count.intValue();
} catch (Exception e) {
throw new RuntimeException("hql can't be auto count, hql is:"
+ countHql, e);
}
}
/**
*
* Description : 设置分页参数到Query对象,辅助函数
*
* @param q
* @param page
* @return
*
*/
@SuppressWarnings("static-access")
protected Query setPageParameter(final Query q, final Page<T> page) {
// 如果每页显示的记录数 为-1,查询所有记录 ,不做分页
if (page.getPageSize() != page.ALL_SIZE) {
q.setFirstResult(page.getBeginCount());
q.setMaxResults(page.getPageSize());
}
return q;
}
/**
*
* Description : 设置分页参数到Criteria对象,辅助函数
*
* @param c
* @param page
* @return
*
*/
protected Criteria setPageParameter(final Criteria c, final Page<T> page) {
c.setFirstResult(page.getCurrentPage() - 1);
c.setMaxResults(page.getPageSize());
if (page.isOrderBySetted()) {
String[] orderByArray = StringUtils.split(page.getOrderBy(), ',');
String[] orderArray = StringUtils.split(page.getOrder(), ',');
Assert.isTrue(orderByArray.length == orderArray.length,
"分页多重排序参数中,排序字段与排序方向的个数不相等");
for (int i = 0; i < orderByArray.length; i++) {
if (Page.ASC.equals(orderArray[i])) {
c.addOrder(Order.asc(orderByArray[i]));
} else {
c.addOrder(Order.desc(orderByArray[i]));
}
}
}
return c;
}
/**
*
* Description : 按属性条件列表创建Criterion数组,辅助函数
*
* @param filters
* @return
*
*/
protected Criterion[] buildPropertyFilterCriterions(
final List<PropertyFilter> filters) {
List<Criterion> criterionList = new ArrayList<Criterion>();
for (PropertyFilter filter : filters) {
if (!filter.isMultiProperty()) { // 只有一个属性需要比较的情况.
Criterion criterion = buildPropertyFilterCriterion(
filter.getPropertyName(), filter.getPropertyValue(),
filter.getMatchType());
criterionList.add(criterion);
} else {// 包含多个属性需要比较的情况,进行or处理.
Disjunction disjunction = Restrictions.disjunction();
for (String param : filter.getPropertyNames()) {
Criterion criterion = buildPropertyFilterCriterion(param,
filter.getPropertyValue(), filter.getMatchType());
disjunction.add(criterion);
}
criterionList.add(disjunction);
}
}
return criterionList.toArray(new Criterion[criterionList.size()]);
}
/**
*
* Description : 按属性条件参数创建Criterion,辅助函数
*
* @param propertyName
* @param propertyValue
* @param matchType
* @return
*
*/
protected Criterion buildPropertyFilterCriterion(final String propertyName,
final Object propertyValue, final MatchType matchType) {
Assert.hasText(propertyName, "propertyName不能为空");
Criterion criterion = null;
try {
// 根据MatchType构造criterion
if (MatchType.EQ.equals(matchType)) {
criterion = Restrictions.eq(propertyName, propertyValue);
} else if (MatchType.LIKE.equals(matchType)) {
criterion = Restrictions.like(propertyName,
(String) propertyValue, MatchMode.ANYWHERE);
} else if (MatchType.LE.equals(matchType)) {
criterion = Restrictions.le(propertyName, propertyValue);
} else if (MatchType.LT.equals(matchType)) {
criterion = Restrictions.lt(propertyName, propertyValue);
} else if (MatchType.GE.equals(matchType)) {
criterion = Restrictions.ge(propertyName, propertyValue);
} else if (MatchType.GT.equals(matchType)) {
criterion = Restrictions.gt(propertyName, propertyValue);
}
} catch (Exception e) {
throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
}
return criterion;
}
}
package com.idoo.iosms.core.hibernate.hibernate;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.Assert;
import com.idoo.iosms.core.hibernate.GenericDao;
import com.idoo.iosms.core.utils.ReflectionUtils;
public class HibernateGenericDao<T, PK extends Serializable> implements
GenericDao<T, PK> {
protected Logger logger = LoggerFactory.getLogger(getClass());
protected SessionFactory sessionFactory;
protected Class<T> entityClass;
public HibernateGenericDao() {
this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());
}
public HibernateGenericDao(final SessionFactory sessionFactory,
final Class<T> entityClass) {
this.sessionFactory = sessionFactory;
this.entityClass = entityClass;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Autowired
public void setSessionFactory(
final @Qualifier("sessionFactory") SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getSession() {
return sessionFactory.getCurrentSession();
}
public void delete(T entity) {
Assert.notNull(entity, "entity不能为空");
getSession().delete(entity);
logger.debug("delete entity: {}", entity);
}
@SuppressWarnings("unchecked")
public <X> List<X> query(String hql, Object... values) {
return createQuery(hql, values).list();
}
@SuppressWarnings("unchecked")
public <X> List<X> query(String hql, Map<String, Object> values) {
return createQuery(hql, values).list();
}
@SuppressWarnings("unchecked")
public <X> X findUnique(String hql, Object... values) {
return (X) createQuery(hql, values).uniqueResult();
}
@SuppressWarnings("unchecked")
public <X> X findUnique(String hql, Map<String, Object> values) {
return (X) createQuery(hql, values).uniqueResult();
}
@SuppressWarnings("unchecked")
public T findUnique(final Criterion... criterions) {
return (T) createCriteria(criterions).uniqueResult();
}
@SuppressWarnings("unchecked")
public T get(Serializable id) {
Assert.notNull(id, "id不能为空");
return (T) getSession().get(entityClass, id);
}
public Serializable save(T entity) {
Assert.notNull(entity, "entity不能为空");
Serializable id = getSession().save(entity);
logger.debug("save entity: {}", entity);
return id;
}
public void saveOrUpdate(T entity) {
Assert.notNull(entity, "entity不能为空");
getSession().saveOrUpdate(entity);
logger.debug("save entity: {}", entity);
}
public void update(T entity) {
Assert.notNull(entity, "entity不能为空");
getSession().update(entity);
logger.debug("save entity: {}", entity);
}
public Query createQuery(String queryString, Map<String, Object> values) {
Assert.hasText(queryString, "queryString不能为空");
Query query = getSession().createQuery(queryString);
query.setCacheable(true);
;
if (values != null) {
query.setProperties(values);
}
return query;
}
public Query createQuery(String queryString, Object... values) {
Assert.hasText(queryString, "queryString不能为空");
Query query = getSession().createQuery(queryString);
query.setCacheable(true);
;
if (values != null) {
for (int i = 0; i < values.length; i++) {
if (values[i] != null
&& StringUtils.isNotEmpty(values[i].toString()))
query.setParameter(i, values[i]);
}
}
return query;
}
public int executeUpdate(final String hql, final Object... values) {
return createQuery(hql, values).executeUpdate();
}
public int executeUpdate(final String hql, final Map<String, Object> values) {
return createQuery(hql, values).executeUpdate();
}
public void initEntity(T entity) {
Hibernate.initialize(entity);
}
public void initEntity(List<T> entityList) {
for (T entity : entityList) {
Hibernate.initialize(entity);
}
}
/**
*
* Description : 根据Criterion条件创建Criteria
*
* @param criterions
* @return
*
*/
public Criteria createCriteria(final Criterion... criterions) {
Criteria criteria = getSession().createCriteria(entityClass);
for (Criterion c : criterions) {
criteria.add(c);
}
return criteria;
}
}
package com.idoo.iosms.core.hibernate;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
/**
*
* @param <T>
* @param <ID>
* @Description : 基类 DAO 接口
*/
public interface GenericDao<T, PK extends Serializable> {
/**
*
* Description : 保存 实体对象
*
* @param entity
*
*/
public Serializable save(final T entity);
/**
*
* Description : 删除 实体对象
*
* @param entity
*
*/
public void delete(final T entity);
/**
*
* Description : 获取 实体对象
*
* @param id
* @return
*
*/
public T get(final PK id);
/**
*
* Description : 更新 实体对象
*
* @param entity
*
*/
public void update(final T entity);
/**
*
* Description : 保存或更新 实体对象
*
* @param entity
*
*/
public void saveOrUpdate(final T entity);
/**
*
* Description : 初始化对象. 使用load()方法得到的仅是对象Proxy, 在传到View层前需要进行初始化.
* 只初始化entity的直接属性,但不会初始化延迟加载的关联集合和属性. 如需初始化关联属性,可实现新的函数,执行:
* Hibernate.initialize(user.getRoles()),初始化User的直接属性和关联集合.
* Hibernate.initialize
* (user.getDescription()),初始化User的直接属性和延迟加载的Description属性.
*
*
* @param entity
*
*/
public void initEntity(T entity);
/**
*
* Description : 初始化对象
*
* @param entityList
*
*/
public void initEntity(List<T> entityList);
/**
*
* Description : 按HQL查询对象列表
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> List<X> query(final String hql, final Object... values);
/**
*
* Description : 按HQL查询对象列表
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> List<X> query(final String hql, final Map<String, Object> values);
/**
*
* Description : 按HQL查询唯一对象
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> X findUnique(final String hql, final Object... values);
/**
*
* Description : 按HQL查询唯一对象
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> X findUnique(final String hql, final Map<String, Object> values);
/**
*
* Description : 按Criteria查询唯一对象
*
* @param criterions
* @return
*
*/
public T findUnique(final Criterion... criterions);
/**
*
* Description : 根据查询HQL与参数列表创建Query对象
*
* @param queryString
* @param values
* @return
*
*/
public Query createQuery(final String queryString, final Object... values);
/**
*
* Description : 根据查询HQL与参数列表创建Query对象
*
* @param queryString
* @param values
* @return
*
*/
public Query createQuery(final String queryString,
final Map<String, Object> values);
/**
*
* Description : 根据查询HQL与参数列表 执行
*
* @param queryString
* @param values
* @return
*
*/
public int executeUpdate(final String queryString, final Object... values);
/**
*
* Description : 根据查询HQL与参数列表 执行
*
* @param queryString
* @param values
* @return
*
*/
public int executeUpdate(final String queryString,
final Map<String, Object> values);
}
package com.idoo.iosms.core.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
/**
*
* 反射的Util函数集合 提供访问私有变量,获取泛型类型Class,提取集合中元素的属性,转换字符串到对象等Util函数
*/
public class ReflectionUtils {
private static Logger logger = LoggerFactory
.getLogger(ReflectionUtils.class);
/**
*
* Description : 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*
* @param object
* @param fieldName
* @return
*
*/
public static Object getFieldValue(final Object object,
final String fieldName) {
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
makeAccessible(field);
Object result = null;
try {
result = field.get(object);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}", e.getMessage());
}
return result;
}
/**
*
* Description : 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*
* @param object
* @param fieldName
* @param value
*
*/
public static void setFieldValue(final Object object,
final String fieldName, final Object value) {
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
makeAccessible(field);
try {
field.set(object, value);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
}
/**
*
* Description : 直接调用对象方法, 无视private/protected修饰符.
*
* @param object
* @param methodName
* @param parameterTypes
* @param parameters
* @return
*
*/
public static Object invokeMethod(final Object object,
final String methodName, final Class<?>[] parameterTypes,
final Object[] parameters) {
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if (method == null)
throw new IllegalArgumentException("Could not find method ["
+ methodName + "] on target [" + object + "]");
method.setAccessible(true);
try {
return method.invoke(object, parameters);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
*
* Description : 循环向上转型, 获取对象的DeclaredField. 如向上转型到Object仍无法找到, 返回null.
*
* @param object
* @param fieldName
* @return
*
*/
protected static Field getDeclaredField(final Object object,
final String fieldName) {
Assert.notNull(object, "object不能为空");
Assert.hasText(fieldName, "fieldName");
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
// Field不在当前类定义,继续向上转型
}
}
return null;
}
/**
*
* Description : 强行设置Field可访问.
*
* @param field
*
*/
protected static void makeAccessible(final Field field) {
if (!Modifier.isPublic(field.getModifiers())
|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
field.setAccessible(true);
}
}
/**
*
* Description : 循环向上转型,获取对象的DeclaredMethod. 如向上转型到Object仍无法找到, 返回null.
*
* @param object
* @param methodName
* @param parameterTypes
* @return
*
*/
protected static Method getDeclaredMethod(Object object, String methodName,
Class<?>[] parameterTypes) {
Assert.notNull(object, "object不能为空");
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
// Method不在当前类定义,继续向上转型
}
}
return null;
}
/**
*
* Description : 通过反射,获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
*
* @param <T>
* @param clazz
* @return
*
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getSuperClassGenricType(final Class clazz) {
return getSuperClassGenricType(clazz, 0);
}
/**
* 通过反射,获得定义Class时声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
*
* 如public UserDao extends HibernateDao<User,Long>
*
* @param clazz
* clazz The class to introspect
* @param index
* the Index of the generic ddeclaration,start from 0.
* @return the index generic declaration, or Object.class if cannot be
* determined
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(final Class clazz,
final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(clazz.getSimpleName()
+ "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn("Index: " + index + ", Size of "
+ clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName()
+ " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}
/**
* 提取集合中的对象的属性(通过getter函数), 组合成List.
*
* @param collection
* 来源集合.
* @param propertyName
* 要提取的属性名.
*/
@SuppressWarnings("unchecked")
public static List convertElementPropertyToList(
final Collection collection, final String propertyName) {
List list = new ArrayList();
try {
for (Object obj : collection) {
list.add(PropertyUtils.getProperty(obj, propertyName));
}
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
return list;
}
/**
* 提取集合中的对象的属性(通过getter函数), 组合成由分割符分隔的字符串.
*
* @param collection
* 来源集合.
* @param propertyName
* 要提取的属性名.
* @param separator
* 分隔符.
*/
@SuppressWarnings("unchecked")
public static String convertElementPropertyToString(
final Collection collection, final String propertyName,
final String separator) {
List list = convertElementPropertyToList(collection, propertyName);
return StringUtils.join(list, separator);
}
/**
* 转换字符串类型到clazz的property类型的值.
*
* @param value
* 待转换的字符串
* @param clazz
* 提供类型信息的Class
* @param propertyName
* 提供类型信息的Class的属性.
*/
public static Object convertValue(Object value, Class<?> toType) {
try {
DateConverter dc = new DateConverter();
dc.setUseLocaleFormat(true);
dc.setPatterns(new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss" });
ConvertUtils.register(dc, Date.class);
return ConvertUtils.convert(value, toType);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
*
* Description : 将反射时的checked exception转换为unchecked exception.
*
* @param e
* @return
*
*/
public static RuntimeException convertReflectionExceptionToUnchecked(
Exception e) {
if (e instanceof IllegalAccessException
|| e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException)
return new IllegalArgumentException("Reflection Exception.", e);
else if (e instanceof InvocationTargetException)
return new RuntimeException("Reflection Exception.",
((InvocationTargetException) e).getTargetException());
else if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException("Unexpected Checked Exception.", e);
}
}
package com.idoo.iosms.core.hibernate;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import com.idoo.iosms.core.utils.Page;
import com.idoo.iosms.core.utils.PropertyFilter;
public interface PageGenericDao<T, PK extends Serializable> extends GenericDao<T, PK> {
/**
*
* Description : 按HQL分页查询
*
* @param page
* @param hql
* @param values
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final String hql, final Object... values);
/**
*
* Description : 按HQL分页查询
*
* @param page
* @param hql
* @param values
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final String hql, final Map<String, Object> values);
/**
*
* Description : 按Criteria分页查询
*
* @param page
* @param criterions
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final Criterion... criterions);
/**
*
* Description : 按属性过滤条件列表分页查找对象
*
* @param page
* @param filters
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final List<PropertyFilter> filters);
/**
*
* Description : 执行count查询获得本次Hql查询所能获得的对象总数
*
* @param hql
* @param values
* @return
*
*/
public int countHqlResult(final String hql, final Object... values);
/**
*
* Description : 执行count查询获得本次Hql查询所能获得的对象总数
*
* @param hql
* @param values
* @return
*
*/
public int countHqlResult(final String hql, final Map<String, Object> values);
/**
*
* Description : 执行count查询获得本次Criteria查询所能获得的对象总数
*
* @param c
* @return
*
*/
public int countCriteriaResult(final Criteria c);
}
package com.idoo.iosms.core.utils;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.StringUtils;
public class Page<T>
{
public static final int ALL_SIZE = -1;// 查询所有记录
public static final int FRONT_SIZE = 4; // 前台展示的页面大小
public static final int FIRST_PAGE = 1; // 第一页
public static final int DEFAULT_SIZE = 10; // 每页默认显示10条
public static final String ASC = "asc";
public static final String DESC = "desc";
private int beginCount; // 开始的记录数
private int totalCount; // 记录总数
private int pageSize; // 每页显示的记录数
private int totalPage; // 总页数
private int currentPage; // 当前页码
private int prePage;
private int nextPage;
@SuppressWarnings("unused")
private boolean hasPrePage; // 是否有上一页
@SuppressWarnings("unused")
private boolean hasNextPage; // 是否有下一页
private boolean autoCount = true;// 是否计算记录总数
private String orderBy; // 排序字段
private String order; // 排序方式
private String resultContent; // 基于文本的分页
private List<T> resultList = Collections.emptyList(); // 基于记录的分页
public Page()
{
}
public static Page<String> getBlankPage(int pageSize)
{
Page<String> page = new Page<String>(0, pageSize);
page.setResultContent("");
return page;
}
public Page(List<T> resultList)
{
this.resultList = resultList;
}
public Page(int totalCount, int pageSize)
{
this(totalCount, pageSize, 1);
}
public Page(int totalCount, int pageSize, int currentPage)
{
if (pageSize > 0)
{
this.pageSize = pageSize;
} else
{
this.pageSize = DEFAULT_SIZE;
}
this.totalCount = totalCount;
if (totalCount <= 0)
{
this.totalPage = 1;
} else
{
this.totalPage = (totalCount - 1) / pageSize + 1;
}
setCurrentPage(currentPage);
}
public Page(List<T> resultList, int totalCount, int pageSize,
int currentPage)
{
this(totalCount, pageSize, currentPage);
this.resultList = resultList;
}
public Page(String resultContent, int totalCount, int pageSize,
int currentPage)
{
this(totalCount, pageSize, currentPage);
this.resultContent = resultContent;
}
public void setCurrentPage(int currentPage)
{
if (currentPage <= 0)
{
currentPage = FIRST_PAGE;
}
this.currentPage = currentPage;
this.beginCount = (currentPage - 1) * pageSize;
if (currentPage > 1)
{
this.setHasPrePage(true);
this.prePage = currentPage - 1;
} else
{
this.setHasPrePage(false);
}
if (currentPage < totalPage)
{
this.setHasNextPage(true);
this.nextPage = currentPage + 1;
} else
{
this.setHasNextPage(false);
}
}
public int getBeginCount()
{
return beginCount;
}
public int getTotalCount()
{
return totalCount;
}
@SuppressWarnings("static-access")
public int getPageSize()
{
if (pageSize <= 0 && pageSize != -1)
{
pageSize = this.DEFAULT_SIZE;
}
return pageSize;
}
/**
*
* Description : 根据pageSize与totalCount计算总页数
*
* @return
*
*/
public int getTotalPage()
{
if (totalCount < 0)
totalPage = -1;
if (pageSize == -1)
{
totalPage = 1;
}
totalPage = totalCount / pageSize;
if (totalCount % pageSize > 0)
{
totalPage++;
}
return totalPage;
}
@SuppressWarnings("static-access")
public int getCurrentPage()
{
if (currentPage <= 0)
{
currentPage = this.FIRST_PAGE;
}
return currentPage;
}
/**
*
* Description : 是否还有上一页
*
* @return
*
*/
public boolean isHasPrePage()
{
return hasPrePage = (currentPage - 1 >= 1);
}
/**
*
* Description : 是否还有下一页.
*
* @return
*
*/
public boolean isHasNextPage()
{
return hasNextPage = (currentPage + 1 <= getTotalPage());
}
/**
*
* Description : 取得上页的页号, 序号从1开始. 当前页为首页时返回首页序号.
*
* @return
*
*/
public int getPrePage()
{
if (isHasPrePage())
prePage = currentPage - 1;
else
prePage = currentPage;
return prePage;
}
/**
*
* Description : 取得下页的页号, 序号从1开始 当前页为尾页时仍返回尾页序号.
*
* @return
*
*/
public int getNextPage()
{
if (isHasNextPage())
nextPage = currentPage + 1;
else
nextPage = currentPage;
return nextPage;
}
public List<T> getResultList()
{
return resultList;
}
public void setResultList(List<T> resultList)
{
this.resultList = resultList;
}
public String getResultContent()
{
return resultContent;
}
public void setResultContent(String resultContent)
{
this.resultContent = resultContent;
}
/**
*
* Description : 获得排序字段,无默认值.多个排序字段时用','分隔
*
* @return
*
*/
public String getOrderBy()
{
return orderBy;
}
/**
*
* Description : 设置排序字段,多个排序字段时用','分隔.
*
* @param orderBy
*
*/
public void setOrderBy(final String orderBy)
{
this.orderBy = orderBy;
}
public Page<T> orderBy(final String theOrderBy)
{
setOrderBy(theOrderBy);
return this;
}
/**
*
* Description : 获得排序方向
*
* @return
*
*/
public String getOrder()
{
return order;
}
/**
*
* Description : 设置排序方式向
*
* @param order
* 可选值为desc或asc,多个排序字段时用','分隔.
*
*/
public void setOrder(final String order)
{
// 检查order字符串的合法值
String[] orders = StringUtils.split(StringUtils.lowerCase(order), ',');
for (String orderStr : orders)
{
if (!StringUtils.equals(DESC, orderStr)
&& !StringUtils.equals(ASC, orderStr))
throw new IllegalArgumentException("排序方向" + orderStr + "不是合法值");
}
this.order = StringUtils.lowerCase(order);
}
public Page<T> order(final String theOrder)
{
setOrder(theOrder);
return this;
}
/**
*
* Description : 是否已设置排序字段,无默认值
*
* @return
*
*/
public boolean isOrderBySetted()
{
return (StringUtils.isNotBlank(orderBy) && StringUtils
.isNotBlank(order));
}
/**
*
* Description : 查询对象时是否自动另外执行count查询获取总记录数, 默认为 true
*
* @return
*
*/
public boolean isAutoCount()
{
return autoCount;
}
public void setAutoCount(final boolean autoCount)
{
this.autoCount = autoCount;
}
public Page<T> autoCount(final boolean theAutoCount)
{
setAutoCount(theAutoCount);
return this;
}
public void setTotalCount(int totalCount)
{
this.totalCount = totalCount;
}
public void setBeginCount(int beginCount)
{
this.beginCount = beginCount;
}
public void setPageSize(int pageSize)
{
this.pageSize = pageSize;
}
public void setHasPrePage(boolean hasPrePage) {
this.hasPrePage = hasPrePage;
}
public void setHasNextPage(boolean hasNextPage) {
this.hasNextPage = hasNextPage;
}
}
package com.idoo.iosms.core.utils;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;
public class PropertyFilter {
/**
* 多个属性间OR关系的分隔符.
*/
public static final String OR_SEPARATOR = "_OR_";
/**
* 属性比较类型.
*/
public enum MatchType {
EQ, LIKE, LT, GT, LE, GE;
}
/**
* 属性数据类型.
*/
public enum PropertyType {
S(String.class), I(Integer.class), L(Long.class), N(Double.class), D(Date.class), B(Boolean.class);
private Class<?> clazz;
PropertyType(Class<?> clazz) {
this.clazz = clazz;
}
public Class<?> getValue() {
return clazz;
}
}
private String[] propertyNames = null;
private Class<?> propertyType = null;
private Object propertyValue = null;
private MatchType matchType = MatchType.EQ;
public PropertyFilter() {
}
/**
* @param filterName 比较属性字符串,含待比较的比较类型、属性值类型及属性列表.
* eg. LIKES_NAME_OR_LOGIN_NAME
* @param value 待比较的值.
*/
public PropertyFilter(final String filterName, final Object value) {
String matchTypeStr = StringUtils.substringBefore(filterName, "_");
String matchTypeCode = StringUtils.substring(matchTypeStr, 0, matchTypeStr.length() - 1);
String propertyTypeCode = StringUtils.substring(matchTypeStr, matchTypeStr.length() - 1, matchTypeStr.length());
try {
matchType = Enum.valueOf(MatchType.class, matchTypeCode);
} catch (RuntimeException e) {
throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性比较类型.", e);
}
try {
propertyType = Enum.valueOf(PropertyType.class, propertyTypeCode).getValue();
} catch (RuntimeException e) {
throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性值类型.", e);
}
String propertyNameStr = StringUtils.substringAfter(filterName, "_");
propertyNames = StringUtils.split(propertyNameStr, PropertyFilter.OR_SEPARATOR);
Assert.isTrue(propertyNames.length > 0, "filter名称" + filterName + "没有按规则编写,无法得到属性名称.");
//按entity property中的类型将字符串转化为实际类型.
this.propertyValue = ReflectionUtils.convertValue(value, propertyType);
}
/**
* 是否有多个属性.
*/
public boolean isMultiProperty() {
return (propertyNames.length > 1);
}
/**
* 获取比较属性名称列表.
*/
public String[] getPropertyNames() {
return propertyNames;
}
/**
* 获取唯一的属性名称.
*/
public String getPropertyName() {
if (propertyNames.length > 1)
throw new IllegalArgumentException("There are not only one property");
return propertyNames[0];
}
/**
* 获取比较值.
*/
public Object getPropertyValue() {
return propertyValue;
}
/**
* 获取比较值的类型.
*/
public Class<?> getPropertyType() {
return propertyType;
}
/**
* 获取比较类型.
*/
public MatchType getMatchType() {
return matchType;
}
}
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.transform.ResultTransformer;
import org.springframework.util.Assert;
import com.idoo.iosms.core.hibernate.PageGenericDao;
import com.idoo.iosms.core.utils.Page;
import com.idoo.iosms.core.utils.PropertyFilter;
import com.idoo.iosms.core.utils.ReflectionUtils;
import com.idoo.iosms.core.utils.PropertyFilter.MatchType;
public class HibernateDao<T, PK extends Serializable> extends
HibernateGenericDao<T, PK> implements PageGenericDao<T, PK> {
public HibernateDao() {
super();
}
public HibernateDao(final SessionFactory sessionFactory,
final Class<T> entityClass) {
super(sessionFactory, entityClass);
}
@SuppressWarnings("unchecked")
public Page<T> queryPage(Page<T> page, String hql, Object... values) {
// TODO Auto-generated method stub
Assert.notNull(page, "page不能为空");
Query q = createQuery(hql, values);
if (page.isAutoCount()) {
int totalCount = countHqlResult(hql, values);
page.setTotalCount(totalCount);
}
setPageParameter(q, page);
List<T> result = q.list();
page.setResultList(result);
return page;
}
@SuppressWarnings("unchecked")
public Page<T> queryPage(Page<T> page, String hql,
Map<String, Object> values) {
// TODO Auto-generated method stub
Assert.notNull(page, "page不能为空");
Query q = createQuery(hql, values);
if (page.isAutoCount()) {
int totalCount = countHqlResult(hql, values);
page.setTotalCount(totalCount);
}
setPageParameter(q, page);
List<T> result = q.list();
page.setResultList(result);
return page;
}
@SuppressWarnings("unchecked")
public Page<T> queryPage(Page<T> page, Criterion... criterions) {
// TODO Auto-generated method stub
Assert.notNull(page, "page不能为空");
Criteria c = createCriteria(criterions);
if (page.isAutoCount()) {
int totalCount = countCriteriaResult(c);
page.setTotalCount(totalCount);
}
setPageParameter(c, page);
List<T> result = c.list();
page.setResultList(result);
return page;
}
public Page<T> queryPage(final Page<T> page,
final List<PropertyFilter> filters) {
Criterion[] criterions = buildPropertyFilterCriterions(filters);
return queryPage(page, criterions);
}
@SuppressWarnings("unchecked")
public int countCriteriaResult(Criteria c) {
// TODO Auto-generated method stub
CriteriaImpl impl = (CriteriaImpl) c;
// 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作
Projection projection = impl.getProjection();
ResultTransformer transformer = impl.getResultTransformer();
List<CriteriaImpl.OrderEntry> orderEntries = null;
try {
orderEntries = (List<CriteriaImpl.OrderEntry>) ReflectionUtils
.getFieldValue(impl, "orderEntries");
ReflectionUtils.setFieldValue(impl, "orderEntries",
new ArrayList<Object>());
} catch (Exception e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
// 执行Count查询
int totalCount = (Integer) c.setProjection(Projections.rowCount())
.uniqueResult();
// 将之前的Projection,ResultTransformer和OrderBy条件重新设回去
c.setProjection(projection);
if (projection == null) {
c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
}
if (transformer != null) {
c.setResultTransformer(transformer);
}
try {
ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries);
} catch (Exception e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
return totalCount;
}
public int countHqlResult(String hql, Object... values) {
String fromHql = hql;
// select子句与order by子句会影响count查询,进行简单的排除.
fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
fromHql = StringUtils.substringBefore(fromHql, "order by");
String selectHql = "*";
// 如果含有 distinct 描述符,进行简单处理
if (StringUtils.indexOf(hql, "distinct") != -1) {
selectHql = StringUtils.substringBetween(hql, "select", "from")
.trim();
}
String countHql = "select count(" + selectHql + ") " + fromHql;
try {
Long count = findUnique(countHql, values);
return count.intValue();
} catch (Exception e) {
throw new RuntimeException("hql can't be auto count, hql is:"
+ countHql, e);
}
}
public int countHqlResult(String hql, Map<String, Object> values) {
// TODO Auto-generated method stub
String fromHql = hql;
// select子句与order by子句会影响count查询,进行简单的排除.
fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
fromHql = StringUtils.substringBefore(fromHql, "order by");
String countHql = "select count(*) " + fromHql;
try {
Long count = findUnique(countHql, values);
return count.intValue();
} catch (Exception e) {
throw new RuntimeException("hql can't be auto count, hql is:"
+ countHql, e);
}
}
/**
*
* Description : 设置分页参数到Query对象,辅助函数
*
* @param q
* @param page
* @return
*
*/
@SuppressWarnings("static-access")
protected Query setPageParameter(final Query q, final Page<T> page) {
// 如果每页显示的记录数 为-1,查询所有记录 ,不做分页
if (page.getPageSize() != page.ALL_SIZE) {
q.setFirstResult(page.getBeginCount());
q.setMaxResults(page.getPageSize());
}
return q;
}
/**
*
* Description : 设置分页参数到Criteria对象,辅助函数
*
* @param c
* @param page
* @return
*
*/
protected Criteria setPageParameter(final Criteria c, final Page<T> page) {
c.setFirstResult(page.getCurrentPage() - 1);
c.setMaxResults(page.getPageSize());
if (page.isOrderBySetted()) {
String[] orderByArray = StringUtils.split(page.getOrderBy(), ',');
String[] orderArray = StringUtils.split(page.getOrder(), ',');
Assert.isTrue(orderByArray.length == orderArray.length,
"分页多重排序参数中,排序字段与排序方向的个数不相等");
for (int i = 0; i < orderByArray.length; i++) {
if (Page.ASC.equals(orderArray[i])) {
c.addOrder(Order.asc(orderByArray[i]));
} else {
c.addOrder(Order.desc(orderByArray[i]));
}
}
}
return c;
}
/**
*
* Description : 按属性条件列表创建Criterion数组,辅助函数
*
* @param filters
* @return
*
*/
protected Criterion[] buildPropertyFilterCriterions(
final List<PropertyFilter> filters) {
List<Criterion> criterionList = new ArrayList<Criterion>();
for (PropertyFilter filter : filters) {
if (!filter.isMultiProperty()) { // 只有一个属性需要比较的情况.
Criterion criterion = buildPropertyFilterCriterion(
filter.getPropertyName(), filter.getPropertyValue(),
filter.getMatchType());
criterionList.add(criterion);
} else {// 包含多个属性需要比较的情况,进行or处理.
Disjunction disjunction = Restrictions.disjunction();
for (String param : filter.getPropertyNames()) {
Criterion criterion = buildPropertyFilterCriterion(param,
filter.getPropertyValue(), filter.getMatchType());
disjunction.add(criterion);
}
criterionList.add(disjunction);
}
}
return criterionList.toArray(new Criterion[criterionList.size()]);
}
/**
*
* Description : 按属性条件参数创建Criterion,辅助函数
*
* @param propertyName
* @param propertyValue
* @param matchType
* @return
*
*/
protected Criterion buildPropertyFilterCriterion(final String propertyName,
final Object propertyValue, final MatchType matchType) {
Assert.hasText(propertyName, "propertyName不能为空");
Criterion criterion = null;
try {
// 根据MatchType构造criterion
if (MatchType.EQ.equals(matchType)) {
criterion = Restrictions.eq(propertyName, propertyValue);
} else if (MatchType.LIKE.equals(matchType)) {
criterion = Restrictions.like(propertyName,
(String) propertyValue, MatchMode.ANYWHERE);
} else if (MatchType.LE.equals(matchType)) {
criterion = Restrictions.le(propertyName, propertyValue);
} else if (MatchType.LT.equals(matchType)) {
criterion = Restrictions.lt(propertyName, propertyValue);
} else if (MatchType.GE.equals(matchType)) {
criterion = Restrictions.ge(propertyName, propertyValue);
} else if (MatchType.GT.equals(matchType)) {
criterion = Restrictions.gt(propertyName, propertyValue);
}
} catch (Exception e) {
throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
}
return criterion;
}
}
package com.idoo.iosms.core.hibernate.hibernate;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.Assert;
import com.idoo.iosms.core.hibernate.GenericDao;
import com.idoo.iosms.core.utils.ReflectionUtils;
public class HibernateGenericDao<T, PK extends Serializable> implements
GenericDao<T, PK> {
protected Logger logger = LoggerFactory.getLogger(getClass());
protected SessionFactory sessionFactory;
protected Class<T> entityClass;
public HibernateGenericDao() {
this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());
}
public HibernateGenericDao(final SessionFactory sessionFactory,
final Class<T> entityClass) {
this.sessionFactory = sessionFactory;
this.entityClass = entityClass;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Autowired
public void setSessionFactory(
final @Qualifier("sessionFactory") SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getSession() {
return sessionFactory.getCurrentSession();
}
public void delete(T entity) {
Assert.notNull(entity, "entity不能为空");
getSession().delete(entity);
logger.debug("delete entity: {}", entity);
}
@SuppressWarnings("unchecked")
public <X> List<X> query(String hql, Object... values) {
return createQuery(hql, values).list();
}
@SuppressWarnings("unchecked")
public <X> List<X> query(String hql, Map<String, Object> values) {
return createQuery(hql, values).list();
}
@SuppressWarnings("unchecked")
public <X> X findUnique(String hql, Object... values) {
return (X) createQuery(hql, values).uniqueResult();
}
@SuppressWarnings("unchecked")
public <X> X findUnique(String hql, Map<String, Object> values) {
return (X) createQuery(hql, values).uniqueResult();
}
@SuppressWarnings("unchecked")
public T findUnique(final Criterion... criterions) {
return (T) createCriteria(criterions).uniqueResult();
}
@SuppressWarnings("unchecked")
public T get(Serializable id) {
Assert.notNull(id, "id不能为空");
return (T) getSession().get(entityClass, id);
}
public Serializable save(T entity) {
Assert.notNull(entity, "entity不能为空");
Serializable id = getSession().save(entity);
logger.debug("save entity: {}", entity);
return id;
}
public void saveOrUpdate(T entity) {
Assert.notNull(entity, "entity不能为空");
getSession().saveOrUpdate(entity);
logger.debug("save entity: {}", entity);
}
public void update(T entity) {
Assert.notNull(entity, "entity不能为空");
getSession().update(entity);
logger.debug("save entity: {}", entity);
}
public Query createQuery(String queryString, Map<String, Object> values) {
Assert.hasText(queryString, "queryString不能为空");
Query query = getSession().createQuery(queryString);
query.setCacheable(true);
;
if (values != null) {
query.setProperties(values);
}
return query;
}
public Query createQuery(String queryString, Object... values) {
Assert.hasText(queryString, "queryString不能为空");
Query query = getSession().createQuery(queryString);
query.setCacheable(true);
;
if (values != null) {
for (int i = 0; i < values.length; i++) {
if (values[i] != null
&& StringUtils.isNotEmpty(values[i].toString()))
query.setParameter(i, values[i]);
}
}
return query;
}
public int executeUpdate(final String hql, final Object... values) {
return createQuery(hql, values).executeUpdate();
}
public int executeUpdate(final String hql, final Map<String, Object> values) {
return createQuery(hql, values).executeUpdate();
}
public void initEntity(T entity) {
Hibernate.initialize(entity);
}
public void initEntity(List<T> entityList) {
for (T entity : entityList) {
Hibernate.initialize(entity);
}
}
/**
*
* Description : 根据Criterion条件创建Criteria
*
* @param criterions
* @return
*
*/
public Criteria createCriteria(final Criterion... criterions) {
Criteria criteria = getSession().createCriteria(entityClass);
for (Criterion c : criterions) {
criteria.add(c);
}
return criteria;
}
}
package com.idoo.iosms.core.hibernate;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
/**
*
* @param <T>
* @param <ID>
* @Description : 基类 DAO 接口
*/
public interface GenericDao<T, PK extends Serializable> {
/**
*
* Description : 保存 实体对象
*
* @param entity
*
*/
public Serializable save(final T entity);
/**
*
* Description : 删除 实体对象
*
* @param entity
*
*/
public void delete(final T entity);
/**
*
* Description : 获取 实体对象
*
* @param id
* @return
*
*/
public T get(final PK id);
/**
*
* Description : 更新 实体对象
*
* @param entity
*
*/
public void update(final T entity);
/**
*
* Description : 保存或更新 实体对象
*
* @param entity
*
*/
public void saveOrUpdate(final T entity);
/**
*
* Description : 初始化对象. 使用load()方法得到的仅是对象Proxy, 在传到View层前需要进行初始化.
* 只初始化entity的直接属性,但不会初始化延迟加载的关联集合和属性. 如需初始化关联属性,可实现新的函数,执行:
* Hibernate.initialize(user.getRoles()),初始化User的直接属性和关联集合.
* Hibernate.initialize
* (user.getDescription()),初始化User的直接属性和延迟加载的Description属性.
*
*
* @param entity
*
*/
public void initEntity(T entity);
/**
*
* Description : 初始化对象
*
* @param entityList
*
*/
public void initEntity(List<T> entityList);
/**
*
* Description : 按HQL查询对象列表
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> List<X> query(final String hql, final Object... values);
/**
*
* Description : 按HQL查询对象列表
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> List<X> query(final String hql, final Map<String, Object> values);
/**
*
* Description : 按HQL查询唯一对象
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> X findUnique(final String hql, final Object... values);
/**
*
* Description : 按HQL查询唯一对象
*
* @param <X>
* @param hql
* @param values
* @return
*
*/
public <X> X findUnique(final String hql, final Map<String, Object> values);
/**
*
* Description : 按Criteria查询唯一对象
*
* @param criterions
* @return
*
*/
public T findUnique(final Criterion... criterions);
/**
*
* Description : 根据查询HQL与参数列表创建Query对象
*
* @param queryString
* @param values
* @return
*
*/
public Query createQuery(final String queryString, final Object... values);
/**
*
* Description : 根据查询HQL与参数列表创建Query对象
*
* @param queryString
* @param values
* @return
*
*/
public Query createQuery(final String queryString,
final Map<String, Object> values);
/**
*
* Description : 根据查询HQL与参数列表 执行
*
* @param queryString
* @param values
* @return
*
*/
public int executeUpdate(final String queryString, final Object... values);
/**
*
* Description : 根据查询HQL与参数列表 执行
*
* @param queryString
* @param values
* @return
*
*/
public int executeUpdate(final String queryString,
final Map<String, Object> values);
}
package com.idoo.iosms.core.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
/**
*
* 反射的Util函数集合 提供访问私有变量,获取泛型类型Class,提取集合中元素的属性,转换字符串到对象等Util函数
*/
public class ReflectionUtils {
private static Logger logger = LoggerFactory
.getLogger(ReflectionUtils.class);
/**
*
* Description : 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*
* @param object
* @param fieldName
* @return
*
*/
public static Object getFieldValue(final Object object,
final String fieldName) {
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
makeAccessible(field);
Object result = null;
try {
result = field.get(object);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}", e.getMessage());
}
return result;
}
/**
*
* Description : 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*
* @param object
* @param fieldName
* @param value
*
*/
public static void setFieldValue(final Object object,
final String fieldName, final Object value) {
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
makeAccessible(field);
try {
field.set(object, value);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
}
/**
*
* Description : 直接调用对象方法, 无视private/protected修饰符.
*
* @param object
* @param methodName
* @param parameterTypes
* @param parameters
* @return
*
*/
public static Object invokeMethod(final Object object,
final String methodName, final Class<?>[] parameterTypes,
final Object[] parameters) {
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if (method == null)
throw new IllegalArgumentException("Could not find method ["
+ methodName + "] on target [" + object + "]");
method.setAccessible(true);
try {
return method.invoke(object, parameters);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
*
* Description : 循环向上转型, 获取对象的DeclaredField. 如向上转型到Object仍无法找到, 返回null.
*
* @param object
* @param fieldName
* @return
*
*/
protected static Field getDeclaredField(final Object object,
final String fieldName) {
Assert.notNull(object, "object不能为空");
Assert.hasText(fieldName, "fieldName");
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
// Field不在当前类定义,继续向上转型
}
}
return null;
}
/**
*
* Description : 强行设置Field可访问.
*
* @param field
*
*/
protected static void makeAccessible(final Field field) {
if (!Modifier.isPublic(field.getModifiers())
|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
field.setAccessible(true);
}
}
/**
*
* Description : 循环向上转型,获取对象的DeclaredMethod. 如向上转型到Object仍无法找到, 返回null.
*
* @param object
* @param methodName
* @param parameterTypes
* @return
*
*/
protected static Method getDeclaredMethod(Object object, String methodName,
Class<?>[] parameterTypes) {
Assert.notNull(object, "object不能为空");
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
// Method不在当前类定义,继续向上转型
}
}
return null;
}
/**
*
* Description : 通过反射,获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
*
* @param <T>
* @param clazz
* @return
*
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getSuperClassGenricType(final Class clazz) {
return getSuperClassGenricType(clazz, 0);
}
/**
* 通过反射,获得定义Class时声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
*
* 如public UserDao extends HibernateDao<User,Long>
*
* @param clazz
* clazz The class to introspect
* @param index
* the Index of the generic ddeclaration,start from 0.
* @return the index generic declaration, or Object.class if cannot be
* determined
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(final Class clazz,
final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(clazz.getSimpleName()
+ "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn("Index: " + index + ", Size of "
+ clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName()
+ " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}
/**
* 提取集合中的对象的属性(通过getter函数), 组合成List.
*
* @param collection
* 来源集合.
* @param propertyName
* 要提取的属性名.
*/
@SuppressWarnings("unchecked")
public static List convertElementPropertyToList(
final Collection collection, final String propertyName) {
List list = new ArrayList();
try {
for (Object obj : collection) {
list.add(PropertyUtils.getProperty(obj, propertyName));
}
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
return list;
}
/**
* 提取集合中的对象的属性(通过getter函数), 组合成由分割符分隔的字符串.
*
* @param collection
* 来源集合.
* @param propertyName
* 要提取的属性名.
* @param separator
* 分隔符.
*/
@SuppressWarnings("unchecked")
public static String convertElementPropertyToString(
final Collection collection, final String propertyName,
final String separator) {
List list = convertElementPropertyToList(collection, propertyName);
return StringUtils.join(list, separator);
}
/**
* 转换字符串类型到clazz的property类型的值.
*
* @param value
* 待转换的字符串
* @param clazz
* 提供类型信息的Class
* @param propertyName
* 提供类型信息的Class的属性.
*/
public static Object convertValue(Object value, Class<?> toType) {
try {
DateConverter dc = new DateConverter();
dc.setUseLocaleFormat(true);
dc.setPatterns(new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss" });
ConvertUtils.register(dc, Date.class);
return ConvertUtils.convert(value, toType);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
*
* Description : 将反射时的checked exception转换为unchecked exception.
*
* @param e
* @return
*
*/
public static RuntimeException convertReflectionExceptionToUnchecked(
Exception e) {
if (e instanceof IllegalAccessException
|| e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException)
return new IllegalArgumentException("Reflection Exception.", e);
else if (e instanceof InvocationTargetException)
return new RuntimeException("Reflection Exception.",
((InvocationTargetException) e).getTargetException());
else if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException("Unexpected Checked Exception.", e);
}
}
package com.idoo.iosms.core.hibernate;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import com.idoo.iosms.core.utils.Page;
import com.idoo.iosms.core.utils.PropertyFilter;
public interface PageGenericDao<T, PK extends Serializable> extends GenericDao<T, PK> {
/**
*
* Description : 按HQL分页查询
*
* @param page
* @param hql
* @param values
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final String hql, final Object... values);
/**
*
* Description : 按HQL分页查询
*
* @param page
* @param hql
* @param values
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final String hql, final Map<String, Object> values);
/**
*
* Description : 按Criteria分页查询
*
* @param page
* @param criterions
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final Criterion... criterions);
/**
*
* Description : 按属性过滤条件列表分页查找对象
*
* @param page
* @param filters
* @return
*
*/
public Page<T> queryPage(final Page<T> page, final List<PropertyFilter> filters);
/**
*
* Description : 执行count查询获得本次Hql查询所能获得的对象总数
*
* @param hql
* @param values
* @return
*
*/
public int countHqlResult(final String hql, final Object... values);
/**
*
* Description : 执行count查询获得本次Hql查询所能获得的对象总数
*
* @param hql
* @param values
* @return
*
*/
public int countHqlResult(final String hql, final Map<String, Object> values);
/**
*
* Description : 执行count查询获得本次Criteria查询所能获得的对象总数
*
* @param c
* @return
*
*/
public int countCriteriaResult(final Criteria c);
}
package com.idoo.iosms.core.utils;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.StringUtils;
public class Page<T>
{
public static final int ALL_SIZE = -1;// 查询所有记录
public static final int FRONT_SIZE = 4; // 前台展示的页面大小
public static final int FIRST_PAGE = 1; // 第一页
public static final int DEFAULT_SIZE = 10; // 每页默认显示10条
public static final String ASC = "asc";
public static final String DESC = "desc";
private int beginCount; // 开始的记录数
private int totalCount; // 记录总数
private int pageSize; // 每页显示的记录数
private int totalPage; // 总页数
private int currentPage; // 当前页码
private int prePage;
private int nextPage;
@SuppressWarnings("unused")
private boolean hasPrePage; // 是否有上一页
@SuppressWarnings("unused")
private boolean hasNextPage; // 是否有下一页
private boolean autoCount = true;// 是否计算记录总数
private String orderBy; // 排序字段
private String order; // 排序方式
private String resultContent; // 基于文本的分页
private List<T> resultList = Collections.emptyList(); // 基于记录的分页
public Page()
{
}
public static Page<String> getBlankPage(int pageSize)
{
Page<String> page = new Page<String>(0, pageSize);
page.setResultContent("");
return page;
}
public Page(List<T> resultList)
{
this.resultList = resultList;
}
public Page(int totalCount, int pageSize)
{
this(totalCount, pageSize, 1);
}
public Page(int totalCount, int pageSize, int currentPage)
{
if (pageSize > 0)
{
this.pageSize = pageSize;
} else
{
this.pageSize = DEFAULT_SIZE;
}
this.totalCount = totalCount;
if (totalCount <= 0)
{
this.totalPage = 1;
} else
{
this.totalPage = (totalCount - 1) / pageSize + 1;
}
setCurrentPage(currentPage);
}
public Page(List<T> resultList, int totalCount, int pageSize,
int currentPage)
{
this(totalCount, pageSize, currentPage);
this.resultList = resultList;
}
public Page(String resultContent, int totalCount, int pageSize,
int currentPage)
{
this(totalCount, pageSize, currentPage);
this.resultContent = resultContent;
}
public void setCurrentPage(int currentPage)
{
if (currentPage <= 0)
{
currentPage = FIRST_PAGE;
}
this.currentPage = currentPage;
this.beginCount = (currentPage - 1) * pageSize;
if (currentPage > 1)
{
this.setHasPrePage(true);
this.prePage = currentPage - 1;
} else
{
this.setHasPrePage(false);
}
if (currentPage < totalPage)
{
this.setHasNextPage(true);
this.nextPage = currentPage + 1;
} else
{
this.setHasNextPage(false);
}
}
public int getBeginCount()
{
return beginCount;
}
public int getTotalCount()
{
return totalCount;
}
@SuppressWarnings("static-access")
public int getPageSize()
{
if (pageSize <= 0 && pageSize != -1)
{
pageSize = this.DEFAULT_SIZE;
}
return pageSize;
}
/**
*
* Description : 根据pageSize与totalCount计算总页数
*
* @return
*
*/
public int getTotalPage()
{
if (totalCount < 0)
totalPage = -1;
if (pageSize == -1)
{
totalPage = 1;
}
totalPage = totalCount / pageSize;
if (totalCount % pageSize > 0)
{
totalPage++;
}
return totalPage;
}
@SuppressWarnings("static-access")
public int getCurrentPage()
{
if (currentPage <= 0)
{
currentPage = this.FIRST_PAGE;
}
return currentPage;
}
/**
*
* Description : 是否还有上一页
*
* @return
*
*/
public boolean isHasPrePage()
{
return hasPrePage = (currentPage - 1 >= 1);
}
/**
*
* Description : 是否还有下一页.
*
* @return
*
*/
public boolean isHasNextPage()
{
return hasNextPage = (currentPage + 1 <= getTotalPage());
}
/**
*
* Description : 取得上页的页号, 序号从1开始. 当前页为首页时返回首页序号.
*
* @return
*
*/
public int getPrePage()
{
if (isHasPrePage())
prePage = currentPage - 1;
else
prePage = currentPage;
return prePage;
}
/**
*
* Description : 取得下页的页号, 序号从1开始 当前页为尾页时仍返回尾页序号.
*
* @return
*
*/
public int getNextPage()
{
if (isHasNextPage())
nextPage = currentPage + 1;
else
nextPage = currentPage;
return nextPage;
}
public List<T> getResultList()
{
return resultList;
}
public void setResultList(List<T> resultList)
{
this.resultList = resultList;
}
public String getResultContent()
{
return resultContent;
}
public void setResultContent(String resultContent)
{
this.resultContent = resultContent;
}
/**
*
* Description : 获得排序字段,无默认值.多个排序字段时用','分隔
*
* @return
*
*/
public String getOrderBy()
{
return orderBy;
}
/**
*
* Description : 设置排序字段,多个排序字段时用','分隔.
*
* @param orderBy
*
*/
public void setOrderBy(final String orderBy)
{
this.orderBy = orderBy;
}
public Page<T> orderBy(final String theOrderBy)
{
setOrderBy(theOrderBy);
return this;
}
/**
*
* Description : 获得排序方向
*
* @return
*
*/
public String getOrder()
{
return order;
}
/**
*
* Description : 设置排序方式向
*
* @param order
* 可选值为desc或asc,多个排序字段时用','分隔.
*
*/
public void setOrder(final String order)
{
// 检查order字符串的合法值
String[] orders = StringUtils.split(StringUtils.lowerCase(order), ',');
for (String orderStr : orders)
{
if (!StringUtils.equals(DESC, orderStr)
&& !StringUtils.equals(ASC, orderStr))
throw new IllegalArgumentException("排序方向" + orderStr + "不是合法值");
}
this.order = StringUtils.lowerCase(order);
}
public Page<T> order(final String theOrder)
{
setOrder(theOrder);
return this;
}
/**
*
* Description : 是否已设置排序字段,无默认值
*
* @return
*
*/
public boolean isOrderBySetted()
{
return (StringUtils.isNotBlank(orderBy) && StringUtils
.isNotBlank(order));
}
/**
*
* Description : 查询对象时是否自动另外执行count查询获取总记录数, 默认为 true
*
* @return
*
*/
public boolean isAutoCount()
{
return autoCount;
}
public void setAutoCount(final boolean autoCount)
{
this.autoCount = autoCount;
}
public Page<T> autoCount(final boolean theAutoCount)
{
setAutoCount(theAutoCount);
return this;
}
public void setTotalCount(int totalCount)
{
this.totalCount = totalCount;
}
public void setBeginCount(int beginCount)
{
this.beginCount = beginCount;
}
public void setPageSize(int pageSize)
{
this.pageSize = pageSize;
}
public void setHasPrePage(boolean hasPrePage) {
this.hasPrePage = hasPrePage;
}
public void setHasNextPage(boolean hasNextPage) {
this.hasNextPage = hasNextPage;
}
}
package com.idoo.iosms.core.utils;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;
public class PropertyFilter {
/**
* 多个属性间OR关系的分隔符.
*/
public static final String OR_SEPARATOR = "_OR_";
/**
* 属性比较类型.
*/
public enum MatchType {
EQ, LIKE, LT, GT, LE, GE;
}
/**
* 属性数据类型.
*/
public enum PropertyType {
S(String.class), I(Integer.class), L(Long.class), N(Double.class), D(Date.class), B(Boolean.class);
private Class<?> clazz;
PropertyType(Class<?> clazz) {
this.clazz = clazz;
}
public Class<?> getValue() {
return clazz;
}
}
private String[] propertyNames = null;
private Class<?> propertyType = null;
private Object propertyValue = null;
private MatchType matchType = MatchType.EQ;
public PropertyFilter() {
}
/**
* @param filterName 比较属性字符串,含待比较的比较类型、属性值类型及属性列表.
* eg. LIKES_NAME_OR_LOGIN_NAME
* @param value 待比较的值.
*/
public PropertyFilter(final String filterName, final Object value) {
String matchTypeStr = StringUtils.substringBefore(filterName, "_");
String matchTypeCode = StringUtils.substring(matchTypeStr, 0, matchTypeStr.length() - 1);
String propertyTypeCode = StringUtils.substring(matchTypeStr, matchTypeStr.length() - 1, matchTypeStr.length());
try {
matchType = Enum.valueOf(MatchType.class, matchTypeCode);
} catch (RuntimeException e) {
throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性比较类型.", e);
}
try {
propertyType = Enum.valueOf(PropertyType.class, propertyTypeCode).getValue();
} catch (RuntimeException e) {
throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性值类型.", e);
}
String propertyNameStr = StringUtils.substringAfter(filterName, "_");
propertyNames = StringUtils.split(propertyNameStr, PropertyFilter.OR_SEPARATOR);
Assert.isTrue(propertyNames.length > 0, "filter名称" + filterName + "没有按规则编写,无法得到属性名称.");
//按entity property中的类型将字符串转化为实际类型.
this.propertyValue = ReflectionUtils.convertValue(value, propertyType);
}
/**
* 是否有多个属性.
*/
public boolean isMultiProperty() {
return (propertyNames.length > 1);
}
/**
* 获取比较属性名称列表.
*/
public String[] getPropertyNames() {
return propertyNames;
}
/**
* 获取唯一的属性名称.
*/
public String getPropertyName() {
if (propertyNames.length > 1)
throw new IllegalArgumentException("There are not only one property");
return propertyNames[0];
}
/**
* 获取比较值.
*/
public Object getPropertyValue() {
return propertyValue;
}
/**
* 获取比较值的类型.
*/
public Class<?> getPropertyType() {
return propertyType;
}
/**
* 获取比较类型.
*/
public MatchType getMatchType() {
return matchType;
}
}