通过Hibernate的元信息处理组件等等,利用spring封装的jdbc bean rowmapper自动映射为bean
又见hibernate的dao封装,不要拍砖了,只是记录而已,个人总结的最佳实践。
代码主要内容:
- Hibernate 泛型DAO
- 分页:
- 基于实体Example的分页
- 基于HQL的分页
- 基于实体类的分页
- 工具方法:
- hibernate的处理——获取hibernate元数据样例
- jdbc的处理
- 通用Hibernate非泛型Dao
先上类图,给个大概印象:
通用实体Dao,可以操作所有hibernate实体:
/**
* 基于Hibernate的实现.<br>
* <ol>
* <li>支持Autowired自动装载{@link SessionFactory}</li>
* </ol>
* @author <a href="mailto:[email protected]">skzr.org</a>
* @version 1.0.0
* @since JDK1.6
*/
public class BaseDaoHibernateImpl extends HibernateDaoSupport implements IBaseDao { // NOPMD by skzrorg on 11-4-30 下午2:35
protected final transient ILocalLogger logger = LocalLoggerFactory.getLogger(getClass());
@Autowired
protected JdbcTemplate jdbcTemplate;
@Autowired
public final void setSuperSessionFactory(SessionFactory sessionFactory) {
setSessionFactory(sessionFactory);
}
/**
* 查询结果映射到对象<br>
* 具体实现见:{@link BeanPropertyRowMapper}
* @param <Bean> 对象类型
* @param elementType 必须
* @param sql
* @param paramters 参数
* @return
*/
protected final <Bean> List<Bean> query(Class<Bean> elementType, String sql, Object... paramters) {
if (logger.isDebugEnabled()) logger.debug(I10NDao.jdbcTemplateQueryBean, elementType, sql, UtilObject.toString(paramters));
return UtilJdbcTemplate.query(jdbcTemplate, elementType, sql, paramters);
}
/**
* 执行sql update
* @param sql
* @param paramters 参数
* @return {@link JdbcTemplate#update(String, Object...)}
*/
protected final int update(String sql, Object... paramters) {
if (logger.isDebugEnabled()) logger.debug(I10NDao.jdbcTemplateUpdate, sql, UtilObject.toString(paramters));
return jdbcTemplate.update(sql, paramters);
}
@SuppressWarnings("unchecked")
public <T> List<T> find(String hql, Object... values) {
return getHibernateTemplate().find(hql, values);
}
public <T> T findSingle(String hql, Object... values) {
List<T> entities = find(hql, values);
return DataAccessUtils.requiredSingleResult(entities);
}
@Override
public void delete(Object entity) {
getHibernateTemplate().delete(entity);
}
@Override
public <T> int deleteById(Class<T> entityClass, Serializable id) {
return getHibernateTemplate().execute(new DeleteByIdHibernateCallback(entityClass, id));
}
@Override
public final <T, PK extends Serializable> int deleteByIds(Class<T> entityClass, Collection<PK> ids) {
return getHibernateTemplate().execute(new DeleteByIdHibernateCallback(entityClass, ids));
}
@Override
public <T> T get(Class<T> entityClass, Serializable id) {
return getHibernateTemplate().get(entityClass, id);
}
@Override
public <T> List<T> loadAll(Class<T> entityClass) {
return getHibernateTemplate().loadAll(entityClass);
}
@Override
public void saveOrUpdate(Object entity) {
getHibernateTemplate().saveOrUpdate(entity);
}
@Override
public void saveOrUpdateAll(Collection<?> entities) {
getHibernateTemplate().saveOrUpdateAll(entities);
}
@SuppressWarnings("unchecked")
public <T> List<T> findByExample(T exampleEntity) {
return getHibernateTemplate().findByExample(exampleEntity);
}
@Override
public <PAGE extends PageByHQL<?>> PAGE findByPage(PAGE page) {
return getHibernateTemplate().execute(new PageByHQLHibernateCallback<PAGE>(page));
}
@Override
public <PAGE extends PageByExample<?>> PAGE findByPageWithExample(PAGE page) {
return UtilHibernate.findByPageWithExample(getHibernateTemplate(), page);
}
}
泛型Dao
package org.skzr.framework.dao.impl; import java.io.Serializable; import java.util.Collection; import java.util.List; import org.hibernate.SessionFactory; import org.skzr.framework.dao.IEntityDao; import org.skzr.framework.dao.page.PageByEntity; import org.skzr.framework.dao.page.PageByExample; import org.skzr.framework.dao.page.PageByHQLHibernateCallback; import org.skzr.framework.i10n.I10NDao; import org.skzr.framework.util.UtilAssert; import org.skzr.framework.util.UtilHibernate; import org.skzr.framework.util.UtilJdbcTemplate; import org.skzr.framework.util.UtilObject; import org.skzr.logging.ILocalLogger; import org.skzr.logging.LocalLoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; /** * 实例化配置时使用: * <ol> * <li>支持Autowired自动装载{@link SessionFactory}</li> * </ol> * @param <T> 实体类型 * @param <PK> 实体的主键标识类型 * @author <a href="mailto:[email protected]">skzr.org</a> * @version 1.0.0 * @since JDK1.6 */ public class EntityDaoHibernateImpl<T, PK extends Serializable> extends HibernateDaoSupport implements IEntityDao<T, PK> { protected final transient ILocalLogger logger = LocalLoggerFactory.getLogger(getClass()); @Autowired protected JdbcTemplate jdbcTemplate; private final Class<T> entityClass; public EntityDaoHibernateImpl(Class<T> entityClass) { UtilAssert.notNull(entityClass, logger.getText(I10NDao.entityClassNeed, "new EntityDaoHibernateImpl()")); this.entityClass = entityClass; } /** * 查询结果映射到对象<br> * 具体实现见:{@link BeanPropertyRowMapper} * @param <Bean> 对象类型 * @param elementType 必须 * @param sql * @param paramters 参数 * @return */ protected final <Bean> List<Bean> query(Class<Bean> elementType, String sql, Object... paramters) { if (logger.isDebugEnabled()) logger.debug(I10NDao.jdbcTemplateQueryBean, elementType, sql, UtilObject.toString(paramters)); return UtilJdbcTemplate.query(jdbcTemplate, elementType, sql, paramters); } /** * 执行sql update * @param sql * @param paramters 参数 * @return {@link JdbcTemplate#update(String, Object...)} */ protected final int update(String sql, Object... paramters) { if (logger.isDebugEnabled()) logger.debug(I10NDao.jdbcTemplateUpdate, sql, UtilObject.toString(paramters)); return jdbcTemplate.update(sql, paramters); } @Autowired public final void setSuperSessionFactory(SessionFactory sessionFactory) { setSessionFactory(sessionFactory); } @Override public void delete(T entity) { getHibernateTemplate().delete(entity); } @Override public int deleteById(final PK id) { return getHibernateTemplate().execute(new DeleteByIdHibernateCallback(entityClass, id)); } @Override public int deleteByIds(final Collection<PK> ids) { return getHibernateTemplate().execute(new DeleteByIdHibernateCallback(entityClass, ids)); } @Override public T get(PK id) { return getHibernateTemplate().get(entityClass, id); } @Override public List<T> loadAll() { return getHibernateTemplate().loadAll(entityClass); } @Override public void saveOrUpdate(T entity) { getHibernateTemplate().saveOrUpdate(entity); } @Override public void saveOrUpdateAll(Collection<T> entities) { getHibernateTemplate().saveOrUpdateAll(entities); } @Override @SuppressWarnings("unchecked") public List<T> findByExample(T exampleEntity) { return getHibernateTemplate().findByExample(exampleEntity); } @Override public <PAGE extends PageByEntity<T>> PAGE findByPage(PAGE page) { return getHibernateTemplate().execute(new PageByHQLHibernateCallback<PAGE>(page)); } @Override public <PAGE extends PageByExample<T>> PAGE findByPageWithExample(PAGE page) { return UtilHibernate.findByPageWithExample(getHibernateTemplate(), page); } }
分页代码:
/** * @param <T> 实体类型 * @author <a href="mailto:[email protected]">skzr.org</a> * @version 1.0.0 * @since JDK1.6 */ public class Page<T> { /** <结果> */ private List<T> datas; /** 每页记录数 */ private int pageSize = getDefaultPageSize(); /** 当前页号从1开始 */ private int pageNumber = 1; /** 总记录数 */ private int totalCount; public static int getDefaultPageSize() { return 20; } public void setDatas(List<T> datas) { this.datas = datas; } /** * 返回结果集,如果{@link #datas}空返回{@link Collections#EMPTY_LIST} * @return <T> */ @SuppressWarnings("unchecked") public List<T> getDatas() { return datas == null ? Collections.EMPTY_LIST : datas; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public int getTotalCount() { return totalCount; } /** * 设置每页记录数 * @param pageSize 页大小 */ public void setPageSize(int pageSize) { this.pageSize = pageSize < 1 ? getDefaultPageSize() : pageSize; } public int getPageSize() { return pageSize; } /** * 设置查询第几页数据 * @param pageNumber 页码 */ public void setPageNumber(int pageNumber) { this.pageNumber = pageNumber < 1 ? 1 : pageNumber; } /** * 第一条记录索引位置 * @return */ public int getFirstResult() { return (pageNumber - 1) * pageSize; } /** * 是否需要查询. * <ol> * <li>根据已知的总记录数{@link #totalCount}判断:如果总记录数超过{@link #getFirstResult()}需要查询,不需要查询</li> * </ol> * @return {@link #totalCount}>{@link #getFirstResult()} */ public boolean needQuery() { return totalCount > getFirstResult(); } }
基于实体查询的分页:
/** * 实体分页 * @param <T> 实体类型 * @author <a href="mailto:[email protected]">skzr.org</a> * @version 1.0.0 * @since JDK1.6 */ public class PageByExample<T> extends Page<T> { protected final transient ILocalLogger logger = LocalLoggerFactory.getLogger(getClass()); private final T exampleEntity; public T getExampleEntity() { return exampleEntity; } public PageByExample(T exampleEntity) { UtilAssert.notNull(exampleEntity, logger.getText(I10NDao.entityNeed, "PageByExample")); this.exampleEntity = exampleEntity; } @SuppressWarnings("unchecked") public Class<T> getEntityClass() { return (Class<T>) exampleEntity.getClass(); } }
基于HQL分页:
/** * @param <T> 实体类型 * @author <a href="mailto:[email protected]">skzr.org</a> * @version 1.0.0 * @since JDK1.6 */ public class PageByHQL<T> extends Page<T> { protected final transient ILocalLogger logger = LocalLoggerFactory.getLogger(getClass()); private final String hql; public String getHql() { return hql; } public PageByHQL(String hql) { UtilAssert.notEmptyStr(hql, logger.getText(I10NDao.hqlNeed, "PageByHQL")); this.hql = hql; } public List<?> getParameters() { return null; } }
基于实体分页:
/** * 实体分页 * @param <T> 实体类型 * @author <a href="mailto:[email protected]">skzr.org</a> * @version 1.0.0 * @since JDK1.6 */ public class PageByEntity<T> extends PageByHQL<T> { public PageByEntity(Class<T> entityClass) { super("from " + entityClass.getName()); } }
工具方法:
/** * 这里是所有Hibernate相关的帮助方法 * @author <a href="mailto:[email protected]">skzr.org</a> * @version 1.0.0 * @since JDK1.6 */ public final class UtilHibernate { private static transient ILocalLogger logger = LocalLoggerFactory.getLogger(UtilHibernate.class); private UtilHibernate() { throw new IllegalArgumentException(logger.getText(I10NFramework.utilClassInstance)); } /** * 获取主键属性名 * @param session * @param entityClass 实体类 * @return 主键名 * @see #getIdentifierPropertyName(SessionFactory, Class) */ public static String getIdentifierPropertyName(Session session, Class<?> entityClass) { return session.getSessionFactory().getClassMetadata(entityClass).getIdentifierPropertyName(); } /** * 获取主键属性名 * @param sessionFactory * @param entityClass 实体类 * @return 主键名 */ public static String getIdentifierPropertyName(SessionFactory sessionFactory, Class<?> entityClass) { return sessionFactory.getClassMetadata(entityClass).getIdentifierPropertyName(); } /** * 输入的Hql转化为求数据个数的hql * @param hql * @return hql的count hql */ public static String getCountHql(String hql) { StringBuilder buf = new StringBuilder(hql.length()); //find order by and delete String tmp = hql.toLowerCase(Locale.ENGLISH); int from0 = tmp.indexOf("from"); int order0 = tmp.lastIndexOf("order "); if (order0 > 0) { //find order by int order1 = tmp.indexOf("by", order0 + "order ".length()); //find by if (order1 > 0 && tmp.substring(order0 + "order ".length(), order1).isEmpty()) { order1 = order1 + "by".length(); if (tmp.indexOf('\'', order1) == -1 && tmp.indexOf(')', order1) == -1) { // NOPMD by skzrorg on 11-4-30 下午2:33 buf.append("select count(*) ").append(hql.substring(from0, order0)); } } } if (buf.length() == 0) buf.append("select count(*) ").append(hql.substring(from0)); logger.debug(I10NDao.hqlCount, hql, buf); return buf.toString(); } /** Query设置条件值 */ public static void setParameters(Query query, List<?> parameters) { if (parameters == null || parameters.isEmpty()) return; for (int i = 0, len = parameters.size(); i < len; i++) { query.setParameter(i, parameters.get(i)); } } /** 创建Hibernate Query */ public static Query createQuery(Session session, String hql, List<?> parameters) { Query query = session.createQuery(hql); setParameters(query, parameters); return query; } @SuppressWarnings("unchecked") public static <PAGE extends PageByExample<?>> PAGE findByPageWithExample(HibernateTemplate hibernateTemplate, PAGE page) { final Class<?> entityClass = page.getEntityClass(); page.setTotalCount(hibernateTemplate.execute(new HibernateCallback<Integer>() { @Override public Integer doInHibernate(Session session) throws SQLException { Query countQuery = session.createQuery("select count(" + getIdentifierPropertyName(session, entityClass) + ") from " + entityClass.getName()); return ((Number) countQuery.uniqueResult()).intValue(); } })); page.setDatas(hibernateTemplate.findByExample(page.getExampleEntity())); return page; } }
jdbc的:
/** * 提供{@link JdbcTemplate}的工具方法 * @author <a href="mailto:[email protected]">skzr.org</a> * @version 1.0.0 * @since JDK1.6 */ public final class UtilJdbcTemplate { private static final ILocalLogger logger = LocalLoggerFactory.getLogger(UtilJdbcTemplate.class); private UtilJdbcTemplate() { throw new IllegalArgumentException(logger.getText(I10NFramework.utilClassInstance)); } /** * 查询结果映射到对象<br> * 具体实现见:{@link BeanPropertyRowMapper} * @param <T> 对象类型 * @param jdbcTemplate 必须 * @param elementType 必须 * @param sql * @param paramters 参数 * @return * @see BeanPropertyRowMapper */ public static <T> List<T> query(JdbcTemplate jdbcTemplate, Class<T> elementType, String sql, Object... paramters) { return jdbcTemplate.query(sql, paramters, new BeanPropertyRowMapper<T>(elementType)); } }