- 浏览: 94681 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (90)
- spring mvc (7)
- hudson(持续集成引擎) (1)
- jquery (5)
- mongodb (2)
- httpclient (1)
- spring3.1 (4)
- hibernate4.1 (6)
- tomcat;database; (1)
- mysql;存储引擎; (1)
- dwr (1)
- httpsession (2)
- symbian (1)
- lighttpd (3)
- nginx (3)
- apache (2)
- 链表 (1)
- jetty (2)
- Redis (1)
- memcached (1)
- squid (1)
- 反向代理 (1)
- 360doc (1)
- struts2 (2)
- mail (1)
- annotation (2)
- captcha (1)
- ehcache (2)
- ThreadPoolTaskExecutor (1)
- json (2)
- tomcat (3)
- cookie (1)
- session (1)
- 面试 (3)
- hadoop (3)
- JDK (1)
- 内存 (1)
- hibernate二级缓存 (1)
- hadoop mapreduce (1)
- linux (2)
- spring security (2)
- http (2)
- excel (1)
- unix (1)
- compass (1)
- lucene (1)
- kindeditor (1)
- C++ (1)
- java (1)
- cas (1)
- eclipse (2)
- olap (1)
- oltp (1)
- Git (1)
- BI (1)
- lago (1)
- 存储过程 (2)
- 书本 (1)
- VMware虚拟机 (1)
- 网络技术 (1)
- 登陆 (1)
- SapphireCache (1)
- ssl (1)
- webservice (1)
- RPC (1)
- 连接池 (1)
- google api (1)
- oracle (1)
- javascript (1)
- mysql (1)
- 离线文件 (0)
- 多线程 (0)
最新评论
-
davinsam:
import org.mysterylab.utopiafra ...
hibernate dao -
davinsam:
dao类使用说明弄错了,怎么跟basehibernatedao ...
hibernate dao -
like_shadows:
真不错,顶
mongodb基本知识
[size=large]有分页功能的 HibernateDao
BaseHibernateDao
Dao使用说明
[/size]
package org.mysterylab.utopiaframework.core.orm.hibernate3; 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.mysterylab.utopiaframework.core.orm.Page; import org.mysterylab.utopiaframework.core.orm.PropertyFilter; import org.mysterylab.utopiaframework.core.orm.PropertyFilter.MatchType; import org.mysterylab.utopiaframework.util.reflect.ReflectionUtil; import org.springframework.util.Assert; /** * 在 {@link BaseHibernateDao} 的基础上加入了如下特性: * <ul> * <li>1) 分页查询.</li> * <li>2) 按属性过滤条件列表查询.</li> * </ul> * * @param <T> * DAO 操作的对象类型 * @param <PK> * 主键类型 * * @author * @see PropertyFilter */ public class HibernateDao<T, PK extends Serializable> extends BaseHibernateDao<T, PK> { /** * 通过子类的泛型定义获得对象的类型.<br> * 比如: * <pre> * {@code * public class UserDao extends HibernateDao<User, Long> * } * </pre> */ public HibernateDao() { super(); } /** * 跳过 DAO 层, 直接在 Service 层使用 BaseHibernateDao 的构造函数, * 在构造函数中定义对象类型. * <pre> * {@code * HibernateDao<User, Long> userDao = new HibernateDao<User, Long>(sessionFactory, User.class); * } * </pre> * @param sessionFactory * @param entityClass */ public HibernateDao(final SessionFactory sessionFactory, final Class<T> entityClass) { super(sessionFactory, entityClass); } /** * 分页获取全部对象. * * @param page * @return */ public Page<T> getAll(final Page<T> page) { return findPage(page); } /** * 按 HQL 分页查询. * * @param page * 分页参数. 注意不支持其中的 orderBy 参数 * @param hql * hql 语句 * @param values * 数量可变的查询参数,按顺序绑定 * * @return 分页查询结果, 附带结果列表及所有查询输入参数 */ @SuppressWarnings("unchecked") public Page<T> findPage(final Page<T> page, final String hql, final Object... values) { Assert.notNull(page, "page can not be null"); Query query = createQuery(hql, values); if (page.isAutoCount()) { long totalCount = countHqlResult(hql, values); page.setTotalCount(totalCount); } setPageParameterToQuery(query, page); List result = query.list(); page.setResult(result); return page; } /** * 按 HQL 分页查询. * * @param page * 分页参数. 注意不支持其中的 orderBy 参数 * @param hql * hql 语句 * @param values * 命名参数, 按名称绑定 * * @return 分页查询结果, 附带结果列表及所有查询输入参数 */ @SuppressWarnings("unchecked") public Page<T> findPage(final Page<T> page, final String hql, final Map<String, ?> values) { Assert.notNull(page, "page can not be null"); Query query = createQuery(hql, values); if (page.isAutoCount()) { long totalCount = countHqlResult(hql, values); page.setTotalCount(totalCount); } setPageParameterToQuery(query, page); List result = query.list(); page.setResult(result); return page; } /** * 按 Criteria 分页查询. * * @param page * 分页参数. * @param criterions * 数量可变的 Criterion * * @return 分页查询结果.附带结果列表及所有查询输入参数. */ @SuppressWarnings("unchecked") public Page<T> findPage(final Page<T> page, final Criterion... criterions) { Assert.notNull(page, "page can not be null"); Criteria criteria = createCriteria(criterions); if (page.isAutoCount()) { long totalCount = countCriteriaResult(criteria); page.setTotalCount(totalCount); } setPageParameterToCriteria(criteria, page); List result = criteria.list(); page.setResult(result); return page; } /** * 设置分页参数到 Query 对象, 辅助函数. * * @param query * @param page * @return */ protected Query setPageParameterToQuery(final Query query, final Page<T> page) { Assert.isTrue(page.getPageSize() > 0, "Page#pageSize must larger than 0"); // 注意 Hibernate 的 firstResult 的序号从 0 开始 query.setFirstResult(page.getFirst() - 1); query.setMaxResults(page.getPageSize()); return query; } /** * 设置分页参数到 Criteria 对象, 辅助函数. * * @param criteria * @param page * @return */ protected Criteria setPageParameterToCriteria(final Criteria criteria, final Page<T> page) { Assert.isTrue(page.getPageSize() > 0, "Page Size must larger than zero"); // 注意 Hibernate 的 firstResult 的序号从 0 开始 criteria.setFirstResult(page.getFirst() - 1); criteria.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])) { criteria.addOrder(Order.asc(orderByArray[i])); } else { criteria.addOrder(Order.desc(orderByArray[i])); } } } return criteria; } /** * 执行 count 查询获得本次 Hql 查询所能获得的对象总数.<br> * 注意本函数只能自动处理简单的 hql 语句, 复杂的 hql 查询请另行编写 count 语句查询. * * @param hql * @param values * @return */ protected long countHqlResult(final String hql, final Object... values) { String countHql = prepareCountHql(hql); try { Long count = findUnique(countHql, values); return count; } catch (Exception e) { throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e); } } /** * 执行 count 查询获得本次 Hql 查询所能获得的对象总数.<br> * 注意本函数只能自动处理简单的 hql 语句, 复杂的 hql 查询请另行编写 count 语句查询. * * @param hql * @param values * @return */ protected long countHqlResult(final String hql, final Map<String, ?> values) { String countHql = prepareCountHql(hql); try { Long count = findUnique(countHql, values); return count; } catch (Exception e) { throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e); } } /** * 为 count 查询获得 Hql 查询获得的对象总数做预处理. * * @param orgHql * @return */ private String prepareCountHql(String orgHql) { String fromHql = orgHql; /* * select 子句与 order by 子句会影响 count 查询, 进行简单的排除. 比如: * select name from order as o order by o.number asc -> from order as o */ fromHql = "from " + StringUtils.substringAfter(fromHql, "from"); fromHql = StringUtils.substringBefore(fromHql, "order by"); String countHql = "select count(*) " + fromHql; return countHql; } /** * 执行 count 查询获得本次 Criteria 查询所能获得的对象总数. * * @param criteria * @return */ @SuppressWarnings("unchecked") protected long countCriteriaResult(final Criteria criteria) { CriteriaImpl impl = (CriteriaImpl) criteria; // 先把 Projection、ResultTransformer、OrderBy 取出来, 清空三者后再执行 Count 操作 Projection projection = impl.getProjection(); ResultTransformer transformer = impl.getResultTransformer(); List<CriteriaImpl.OrderEntry> orderEntries = null; try { orderEntries = (List) ReflectionUtil.getFieldValue(impl, "orderEntries"); ReflectionUtil.setFieldValue(impl, "orderEntries", new ArrayList()); } catch (Exception e) { logger.error("exception could not be happened", e.getMessage()); } // 执行 Count 查询 Long totalCountObject = (Long) criteria.setProjection(Projections.rowCount()) .setMaxResults(1).uniqueResult(); long totalCount = (totalCountObject != null) ? totalCountObject : 0; // 将之前的 Projection, ResultTransformer 和 OrderBy 条件重新设回去 criteria.setProjection(projection); if (projection == null) { criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); } if (transformer != null) { criteria.setResultTransformer(transformer); } try { ReflectionUtil.setFieldValue(impl, "orderEntries", orderEntries); } catch (Exception e) { logger.error("exception could not be happened", e.getMessage()); } return totalCount; } /** * 按属性查找对象列表, 支持多种匹配方式. * * @param matchType * 匹配方式, 目前支持的取值见 {@link PropertyFilter} 的 MatcheType enum */ public List<T> findBy(final String propertyName, final Object value, final MatchType matchType) { Criterion criterion = buildCriterion(propertyName, value, matchType); return find(criterion); } /** * 按属性过滤条件列表查找对象列表. * * @param filters * @return */ public List<T> find(List<PropertyFilter> filters) { Criterion[] criterions = buildCriterionByPropertyFilter(filters); return find(criterions); } /** * 按属性过滤条件列表分页查找对象. * * @param page * @param filters * @return */ public Page<T> findPage(final Page<T> page, final List<PropertyFilter> filters) { Criterion[] criterions = buildCriterionByPropertyFilter(filters); return findPage(page, criterions); } /** * 按属性条件参数创建 Criterion, 辅助函数. * * @param propertyName * @param propertyValue * @param matchType * @return */ protected Criterion buildCriterion(final String propertyName, final Object propertyValue, final MatchType matchType) { Assert.hasText(propertyName, "propertyName can not be null"); Criterion criterion = null; // 根据 MatchType 构造 criterion switch (matchType) { case EQ: criterion = Restrictions.eq(propertyName, propertyValue); break; case LIKE: criterion = Restrictions.like(propertyName, (String) propertyValue, MatchMode.ANYWHERE); break; case LE: criterion = Restrictions.le(propertyName, propertyValue); break; case LT: criterion = Restrictions.lt(propertyName, propertyValue); break; case GE: criterion = Restrictions.ge(propertyName, propertyValue); break; case GT: criterion = Restrictions.gt(propertyName, propertyValue); } return criterion; } /** * 按属性条件列表创建 Criterion 数组, 辅助函数. * * @param filters * @return */ protected Criterion[] buildCriterionByPropertyFilter( final List<PropertyFilter> filters) { List<Criterion> criterionList = new ArrayList<Criterion>(); for (PropertyFilter filter : filters) { if (!filter.hasMultiProperties()) { // 只有一个属性需要比较的情况 Criterion criterion = buildCriterion(filter.getPropertyName(), filter.getMatchValue(), filter.getMatchType()); criterionList.add(criterion); } else { // 包含多个属性需要比较的情况,进行or处理 Disjunction disjunction = Restrictions.disjunction(); for (String param : filter.getPropertyNames()) { Criterion criterion = buildCriterion(param, filter .getMatchValue(), filter.getMatchType()); disjunction.add(criterion); } criterionList.add(disjunction); } } return criterionList.toArray(new Criterion[criterionList.size()]); } }
BaseHibernateDao
package org.mysterylab.utopiaframework.core.orm.hibernate3; import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; import javax.persistence.NonUniqueResultException; import org.hibernate.Criteria; import org.hibernate.Hibernate; import org.hibernate.ObjectNotFoundException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.CriteriaSpecification; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.hibernate.metadata.ClassMetadata; import org.mysterylab.utopiaframework.util.reflect.ReflectionUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.Assert; /** * 封装了 Hibernate3 原生 API 的 DAO 泛型基类. 通过 Hibernate 来操纵对象, 主要是 {@link Session} * 的一些方法的二次封装和 HQL 与 QBC 的一些简单检索. * * @author * @param <T> * DAO 操作的对象类型 * @param <PK> * 主键类型 */ public class BaseHibernateDao<T, PK extends Serializable> { protected Logger logger = LoggerFactory.getLogger(getClass()); protected SessionFactory sessionFactory; protected Class<T> entityClass; /** * 通过子类的泛型定义获得对象的类型. 比如: * <pre> * {@code * public class UserDao extends BaseHibernateDao<User, Long> * } * </pre> */ public BaseHibernateDao() { this.entityClass = ReflectionUtil.getSuperClassGenericType(getClass()); } /** * 跳过 DAO 层, 直接在 Service 层使用 BaseHibernateDao 的构造函数, * 在构造函数中定义对象类型. * <pre> * {@code * BaseHibernateDao<User, Long> userDao = new BaseHibernateDao<User, Long>(sessionFactory, User.class); * } * </pre> * @param sessionFactory * @param entityClass */ public BaseHibernateDao(final SessionFactory sessionFactory, final Class<T> entityClass) { this.sessionFactory = sessionFactory; this.entityClass = entityClass; } public SessionFactory getSessionFactory() { return sessionFactory; } /** * 当配置有 sessionFactory 的时候采用 Spring 的自动注入. * * @param sessionFactory */ @Autowired public void setSessionFactory(final SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } /** * 获取 Hibernate 的 Session. 注意在使用 {@link SessionFactory#getCurrentSession()} * 方法的时候, Hibernate 的操作默认必须包含在一个 Transaction 中. 如果这些操作 CRUD * 操作不被包含在一个具体的事务中, 则会抛出如下异常: * <pre> * org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here * </pre> * 这里顺便说下 {@link SessionFactory#openSession()} 方法与其的区别: opensSession() * 得到一个新的 session, 而 getCurrentSession() 则是从当前线程中得到事务开始时创建的 * Transaction 的那个 session, 如果事务没有正确启动的话, 就没有一个 session 被绑定到当前线程 * * @return */ public Session getSession() { return sessionFactory.getCurrentSession(); } /** * 取得对象的主键名. * * @return */ public String getIdName() { ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass); return meta.getIdentifierPropertyName(); } /** * 按 id 获取对象. 采用 {@link Session#load(Class, Serializable)} 方法在数据库中不存在与 * OID 对应的记录的时候, 会抛出 {@link ObjectNotFoundException} 的异常. 采用 get() * 还是采用 load() 方法的区别在于前者是立即加载, 而后者是延迟加载, 使用的场合有: * <ul> * <li>1) 如果加载一个对象的目的是为了访问它的各个属性, 用 get() 方法.</li> * <li>2) 如果加载一个对象的目的是为了删除它, 或者是为了建立与别的对象的关联关系, 用 load() 方法.</li> * </ul> * 比如以下代码: * <pre> * Transaction tx = session.beginTransaction(); * // 立即检索策略 * Order order = (Order) session.get(Order.class, new Long(1)); * // 延迟检索策略 * Customer customer = (Customer) session.load(Customer.class, new Long(1)); * // 建立 Ordre 与 Customer 的多对一单向关联关系 * order.setCustomer(customer); * tx.commit(); * // Session 不需要知道 Customer 的各个属性的值, 而只要知道 Customer 对象的 OID 即可生成如下 sql 语句: * // update ORDER set CUSTOMER_ID=1, ORDER_NUMBER=... where ID=1; * </pre> * * @param id * 主键 * @return * @see #get(Serializable) * @see #delete(Serializable) */ @SuppressWarnings("unchecked") public T load(final PK id) { Assert.notNull(id, "id can not be null"); return (T) getSession().load(entityClass, id); } /** * 按 id 获取对象. 采用 {@link Session#get(Class, Serializable)} 方法在数据库不存在与 * OID 对应的记录的时候, 会返回 null. * * @param id * 主键 * @return * @see #load(Serializable) */ @SuppressWarnings("unchecked") public T get(final PK id) { Assert.notNull(id, "id can not be null"); return (T) getSession().get(entityClass, id); } /** * 按 id 列表获取对象列表. * * @param ids * @return */ public List<T> get(final Collection<PK> ids) { return find(Restrictions.in(getIdName(), ids)); } /** * 获取全部对象. * * @return */ public List<T> getAll() { return find(); } /** * 获取全部对象, 支持按属性排序. 采用 QBC 的检索方式. * * @param orderByProperty * @param isAsc * @return */ @SuppressWarnings("unchecked") public List<T> getAll(String orderByProperty, boolean isAsc) { Criteria c = createCriteria(); if (isAsc) { c.addOrder(Order.asc(orderByProperty)); } else { c.addOrder(Order.desc(orderByProperty)); } return c.list(); } /** * 按属性查找对象列表, 匹配方式为相等. 采用 QBC 的检索方式. * * @param propertyName * @param value * @return */ public List<T> findBy(final String propertyName, final Object value) { Assert.hasText(propertyName, "propertyName can not be null"); Criterion criterion = Restrictions.eq(propertyName, value); return find(criterion); } /** * 采用 QBC 的检索方式查询对象列表. * * @param criterions * 数量可变的 Criterion */ @SuppressWarnings("unchecked") public List<T> find(final Criterion... criterions) { return createCriteria(criterions).list(); } /** * 采用 QBC 的检索方式查询唯一对象. 可能有以下几种情况: * <ul> * <li>1) 如果有多个值抛 {@link NonUniqueResultException} 异常, 需要用 setMaxResults(1) 方法来限制.</li> * <li>2) 如果有值且只有一个, 返回一个 Object.</li> * <li>3) 如果没值, 返回 null.</li> * </ul> * * @param criterions * 数量可变的 Criterion */ @SuppressWarnings("unchecked") public T findUnique(final Criterion... criterions) { return (T) createCriteria(criterions).setMaxResults(1).uniqueResult(); } /** * 按属性查找唯一对象, 匹配方式为相等. 采用 QBC 的检索方式. * * @param propertyName * @param value * @return * @see #findUnique(Criterion...) */ @SuppressWarnings("unchecked") public T findUniqueBy(final String propertyName, final Object value) { Assert.hasText(propertyName, "propertyName can not be null"); Criterion criterion = Restrictions.eq(propertyName, value); return (T) createCriteria(criterion).setMaxResults(1).uniqueResult(); } /** * 采用 HQL 的检索方式查询对象列表. * * @param values * 数量可变的参数, 按顺序绑定 */ @SuppressWarnings("unchecked") public <X> List<X> find(final String hql, final Object... values) { return createQuery(hql, values).list(); } /** * 采用 HQL 的检索方式查询对象列表. * * @param values * 命名参数, 按名称绑定 */ @SuppressWarnings("unchecked") public <X> List<X> find(final String hql, final Map<String, ?> values) { return createQuery(hql, values).list(); } /** * 采用 HQL 的检索方式查询唯一对象. * * @param values * 数量可变的参数, 按顺序绑定 * @see #findUnique(Criterion...) */ @SuppressWarnings("unchecked") public <X> X findUnique(final String hql, final Object... values) { return (X) createQuery(hql, values).setMaxResults(1).uniqueResult(); } /** * 采用 HQL 的检索方式查询唯一对象. * * @param values * 命名参数, 按名称绑定 * @see #findUnique(Criterion...) */ @SuppressWarnings("unchecked") public <X> X findUnique(final String hql, final Map<String, ?> values) { return (X) createQuery(hql, values).setMaxResults(1).uniqueResult(); } /** * 保存新增或修改的对象. * * @param entity * 对象 */ public void save(final T entity) { Assert.notNull(entity, "entity can not be null"); getSession().saveOrUpdate(entity); logger.debug("save entity: {}", entity); } /** * 删除对象. * * @param entity * 对象必须是 session 中的对象或含 id 属性的 transient 对象 */ public void delete(final T entity) { Assert.notNull(entity, "entity can not be null"); getSession().delete(entity); logger.debug("delete entity: {}", entity); } /** * 按 id 删除对象. * * @param id * 主键 * @see #load(Serializable) */ public void delete(final PK id) { Assert.notNull(id, "id can not be null"); delete(load(id)); logger.debug("delete entity {},id is {}", entityClass.getSimpleName(), id); } /** * 采用 HQL 的检索方式进行批量修改/删除操作. * * @param values * 数量可变的参数,按顺序绑定 * @return 更新记录数. */ public int batchExecute(final String hql, final Object... values) { return createQuery(hql, values).executeUpdate(); } /** * 采用 HQL 的检索方式进行批量修改/删除操作. * * @param values * 命名参数,按名称绑定 * @return 更新记录数. */ public int batchExecute(final String hql, final Map<String, ?> values) { return createQuery(hql, values).executeUpdate(); } /** * 根据查询 HQL 与参数列表创建 Query 对象. 与 find() 函数可进行更加灵活的操作. 比如: * <pre> * Query query = session.createQuery("from Order o where o.customer=":customer and " * + "o.orderNumber like :orderNumber"); * query.setParameter(1, customer); * query.setParameter(2, orderNumber); * </pre> * 上面的程序默认是使用了 Hibernate 的自动根据参数值的 Java 类型来进行对应的映射类型, * 这样可以减少在第三个参数中指定 Java 类型的麻烦. 但是对于日期的 java.util.Date 类型, * 会对应多种 Hibernate 映射类型, 如 Hibernate.DATE 或 Hibernate.TIMESTAMP, * 因此必须在 setParameter() 方法中显式地指定到底对应那种 Hibernate 映射类型. 比如: * <pre> * Query query = session.createQuery("from Customer c where c.birthday=:birthday"); * query.setParameter("birthday", birthday, Hibernate.DATE); * </pre> * * @param values * 数量可变的参数, 按顺序绑定 */ public Query createQuery(final String queryString, final Object... values) { Assert.hasText(queryString, "queryString can not be null"); Query query = getSession().createQuery(queryString); if (values != null) { for (int i = 0; i < values.length; i++) { // 按顺序绑定参数 query.setParameter(i, values[i]); } } return query; } /** * 根据查询 HQL 与参数列表创建 Query 对象. 与 find() 函数可进行更加灵活的操作. 比如: * <pre> * Query query = session.createQuery("from Customer as c where c.name=:name " * + "and c.age=:age"; * Customer customer = new Customer(); * customer.setName("Tom"); * customer.setAge(21); * // 命名参数中的 "name" 和 "age" 分别对应 Customer 类的 name 属性和 age 属性, 否则会抛异常 * query.setProperties(customer); * </pre> * 在本方法中采用的是传递一个 {@link Map} 作为参数, 同样会根据 Map 的名来进行自动绑定. 另外, * setProperties() 方法调用 setParameter() 方法, setParameter() 方法再根据 Customer * 对象的属性的 Java 类型来判断 Hibernate 映射类型. 如果命名参数为日期类型, 则不能通过 * setProperties() 方法来绑定. 另外, 参数绑定对 null 是安全的, 比如如下代码不会抛异常: * <pre> * String name = null; * session.createQuery("from Customer c where c.name=:name").setString("name", name).list(); * </pre> * 上面的查询语句对应的 SQL 语句是: * <pre> * select * from CUSTOMERS where NMAE=null; * </pre> * 这条查询语句的查询结果永远为空. 如果要查询名字为 null 的客户, 应该使用 "is null" * 比较运算符, 比如: * <pre> * // HQL 检索方式 * session.createQuery("from Customer c where c.name is null"); * // QBC 检索方式 * session.createCriteria(Customer.class).add(Restrictions.isNull("name")); * </pre> * * @param values * 命名参数, 按名称绑定 * @see #find(String, Object...) */ public Query createQuery(final String queryString, final Map<String, ?> values) { Assert.hasText(queryString, "queryString can not be null"); Query query = getSession().createQuery(queryString); if (values != null) { // 把命名参数与对象的属性值进行绑定 query.setProperties(values); } return query; } /** * 根据 Criterion 条件创建 Criteria. 与 find() 函数可进行更加灵活的操作. * * @param criterions * 数量可变的 Criterion */ public Criteria createCriteria(final Criterion... criterions) { Criteria criteria = getSession().createCriteria(entityClass); for (Criterion c : criterions) { criteria.add(c); } return criteria; } /** * 初始化对象. 使用 load() 方法得到的仅是对象 Proxy, 在传到 View 层前需要进行初始化. * 如果传入 entity, 则只初始化 entity 的直接属性, 但不会初始化延迟加载的关联集合和属性. * 如需初始化关联属性,需执行: * <pre> * Hibernate.initialize(user.getRoles()) // 初始化User的直接属性和关联集合 * Hibernate.initialize(user.getDescription()) // 初始化User的直接属性和延迟加载的Description属性 * </pre> */ public void initProxyObject(Object proxy) { Hibernate.initialize(proxy); } /** * 为 Query 添加 distinct transformer. 预加载关联对象的 HQL 会引起主对象重复, * 需要进行 distinct 处理. * * @param query * @return */ public Query distinct(Query query) { query.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); return query; } /** * 为 Criteria 添加 distinct transformer. 预加载关联对象的 HQL 会引起主对象重复, * 需要进行 distinct 处理. * * @param criteria * @return */ public Criteria distinct(Criteria criteria) { criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); return criteria; } /** * 判断对象的属性值在数据库内是否唯一.<br> * 在修改对象的情景下, 如果属性新修改的值 (value) 等于属性原来的值 (orgValue) 则不作比较. * * @param propertyName * @param newValue * @param oldValue * @return */ public boolean isPropertyUnique(final String propertyName, final Object newValue, final Object oldValue) { if (newValue == null || newValue.equals(oldValue)) { return true; } Object object = findUniqueBy(propertyName, newValue); return (object == null); } /** * 清除当前 Session. */ public void flush() { getSession().flush(); } }
Dao使用说明
package org.mysterylab.utopiaframework.core.orm.hibernate3; import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; import javax.persistence.NonUniqueResultException; import org.hibernate.Criteria; import org.hibernate.Hibernate; import org.hibernate.ObjectNotFoundException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.CriteriaSpecification; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.hibernate.metadata.ClassMetadata; import org.mysterylab.utopiaframework.util.reflect.ReflectionUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.Assert; /** * 封装了 Hibernate3 原生 API 的 DAO 泛型基类. 通过 Hibernate 来操纵对象, 主要是 {@link Session} * 的一些方法的二次封装和 HQL 与 QBC 的一些简单检索. * * @author * @param <T> * DAO 操作的对象类型 * @param <PK> * 主键类型 */ public class BaseHibernateDao<T, PK extends Serializable> { protected Logger logger = LoggerFactory.getLogger(getClass()); protected SessionFactory sessionFactory; protected Class<T> entityClass; /** * 通过子类的泛型定义获得对象的类型. 比如: * <pre> * {@code * public class UserDao extends BaseHibernateDao<User, Long> * } * </pre> */ public BaseHibernateDao() { this.entityClass = ReflectionUtil.getSuperClassGenericType(getClass()); } /** * 跳过 DAO 层, 直接在 Service 层使用 BaseHibernateDao 的构造函数, * 在构造函数中定义对象类型. * <pre> * {@code * BaseHibernateDao<User, Long> userDao = new BaseHibernateDao<User, Long>(sessionFactory, User.class); * } * </pre> * @param sessionFactory * @param entityClass */ public BaseHibernateDao(final SessionFactory sessionFactory, final Class<T> entityClass) { this.sessionFactory = sessionFactory; this.entityClass = entityClass; } public SessionFactory getSessionFactory() { return sessionFactory; } /** * 当配置有 sessionFactory 的时候采用 Spring 的自动注入. * * @param sessionFactory */ @Autowired public void setSessionFactory(final SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } /** * 获取 Hibernate 的 Session. 注意在使用 {@link SessionFactory#getCurrentSession()} * 方法的时候, Hibernate 的操作默认必须包含在一个 Transaction 中. 如果这些操作 CRUD * 操作不被包含在一个具体的事务中, 则会抛出如下异常: * <pre> * org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here * </pre> * 这里顺便说下 {@link SessionFactory#openSession()} 方法与其的区别: opensSession() * 得到一个新的 session, 而 getCurrentSession() 则是从当前线程中得到事务开始时创建的 * Transaction 的那个 session, 如果事务没有正确启动的话, 就没有一个 session 被绑定到当前线程 * * @return */ public Session getSession() { return sessionFactory.getCurrentSession(); } /** * 取得对象的主键名. * * @return */ public String getIdName() { ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass); return meta.getIdentifierPropertyName(); } /** * 按 id 获取对象. 采用 {@link Session#load(Class, Serializable)} 方法在数据库中不存在与 * OID 对应的记录的时候, 会抛出 {@link ObjectNotFoundException} 的异常. 采用 get() * 还是采用 load() 方法的区别在于前者是立即加载, 而后者是延迟加载, 使用的场合有: * <ul> * <li>1) 如果加载一个对象的目的是为了访问它的各个属性, 用 get() 方法.</li> * <li>2) 如果加载一个对象的目的是为了删除它, 或者是为了建立与别的对象的关联关系, 用 load() 方法.</li> * </ul> * 比如以下代码: * <pre> * Transaction tx = session.beginTransaction(); * // 立即检索策略 * Order order = (Order) session.get(Order.class, new Long(1)); * // 延迟检索策略 * Customer customer = (Customer) session.load(Customer.class, new Long(1)); * // 建立 Ordre 与 Customer 的多对一单向关联关系 * order.setCustomer(customer); * tx.commit(); * // Session 不需要知道 Customer 的各个属性的值, 而只要知道 Customer 对象的 OID 即可生成如下 sql 语句: * // update ORDER set CUSTOMER_ID=1, ORDER_NUMBER=... where ID=1; * </pre> * * @param id * 主键 * @return * @see #get(Serializable) * @see #delete(Serializable) */ @SuppressWarnings("unchecked") public T load(final PK id) { Assert.notNull(id, "id can not be null"); return (T) getSession().load(entityClass, id); } /** * 按 id 获取对象. 采用 {@link Session#get(Class, Serializable)} 方法在数据库不存在与 * OID 对应的记录的时候, 会返回 null. * * @param id * 主键 * @return * @see #load(Serializable) */ @SuppressWarnings("unchecked") public T get(final PK id) { Assert.notNull(id, "id can not be null"); return (T) getSession().get(entityClass, id); } /** * 按 id 列表获取对象列表. * * @param ids * @return */ public List<T> get(final Collection<PK> ids) { return find(Restrictions.in(getIdName(), ids)); } /** * 获取全部对象. * * @return */ public List<T> getAll() { return find(); } /** * 获取全部对象, 支持按属性排序. 采用 QBC 的检索方式. * * @param orderByProperty * @param isAsc * @return */ @SuppressWarnings("unchecked") public List<T> getAll(String orderByProperty, boolean isAsc) { Criteria c = createCriteria(); if (isAsc) { c.addOrder(Order.asc(orderByProperty)); } else { c.addOrder(Order.desc(orderByProperty)); } return c.list(); } /** * 按属性查找对象列表, 匹配方式为相等. 采用 QBC 的检索方式. * * @param propertyName * @param value * @return */ public List<T> findBy(final String propertyName, final Object value) { Assert.hasText(propertyName, "propertyName can not be null"); Criterion criterion = Restrictions.eq(propertyName, value); return find(criterion); } /** * 采用 QBC 的检索方式查询对象列表. * * @param criterions * 数量可变的 Criterion */ @SuppressWarnings("unchecked") public List<T> find(final Criterion... criterions) { return createCriteria(criterions).list(); } /** * 采用 QBC 的检索方式查询唯一对象. 可能有以下几种情况: * <ul> * <li>1) 如果有多个值抛 {@link NonUniqueResultException} 异常, 需要用 setMaxResults(1) 方法来限制.</li> * <li>2) 如果有值且只有一个, 返回一个 Object.</li> * <li>3) 如果没值, 返回 null.</li> * </ul> * * @param criterions * 数量可变的 Criterion */ @SuppressWarnings("unchecked") public T findUnique(final Criterion... criterions) { return (T) createCriteria(criterions).setMaxResults(1).uniqueResult(); } /** * 按属性查找唯一对象, 匹配方式为相等. 采用 QBC 的检索方式. * * @param propertyName * @param value * @return * @see #findUnique(Criterion...) */ @SuppressWarnings("unchecked") public T findUniqueBy(final String propertyName, final Object value) { Assert.hasText(propertyName, "propertyName can not be null"); Criterion criterion = Restrictions.eq(propertyName, value); return (T) createCriteria(criterion).setMaxResults(1).uniqueResult(); } /** * 采用 HQL 的检索方式查询对象列表. * * @param values * 数量可变的参数, 按顺序绑定 */ @SuppressWarnings("unchecked") public <X> List<X> find(final String hql, final Object... values) { return createQuery(hql, values).list(); } /** * 采用 HQL 的检索方式查询对象列表. * * @param values * 命名参数, 按名称绑定 */ @SuppressWarnings("unchecked") public <X> List<X> find(final String hql, final Map<String, ?> values) { return createQuery(hql, values).list(); } /** * 采用 HQL 的检索方式查询唯一对象. * * @param values * 数量可变的参数, 按顺序绑定 * @see #findUnique(Criterion...) */ @SuppressWarnings("unchecked") public <X> X findUnique(final String hql, final Object... values) { return (X) createQuery(hql, values).setMaxResults(1).uniqueResult(); } /** * 采用 HQL 的检索方式查询唯一对象. * * @param values * 命名参数, 按名称绑定 * @see #findUnique(Criterion...) */ @SuppressWarnings("unchecked") public <X> X findUnique(final String hql, final Map<String, ?> values) { return (X) createQuery(hql, values).setMaxResults(1).uniqueResult(); } /** * 保存新增或修改的对象. * * @param entity * 对象 */ public void save(final T entity) { Assert.notNull(entity, "entity can not be null"); getSession().saveOrUpdate(entity); logger.debug("save entity: {}", entity); } /** * 删除对象. * * @param entity * 对象必须是 session 中的对象或含 id 属性的 transient 对象 */ public void delete(final T entity) { Assert.notNull(entity, "entity can not be null"); getSession().delete(entity); logger.debug("delete entity: {}", entity); } /** * 按 id 删除对象. * * @param id * 主键 * @see #load(Serializable) */ public void delete(final PK id) { Assert.notNull(id, "id can not be null"); delete(load(id)); logger.debug("delete entity {},id is {}", entityClass.getSimpleName(), id); } /** * 采用 HQL 的检索方式进行批量修改/删除操作. * * @param values * 数量可变的参数,按顺序绑定 * @return 更新记录数. */ public int batchExecute(final String hql, final Object... values) { return createQuery(hql, values).executeUpdate(); } /** * 采用 HQL 的检索方式进行批量修改/删除操作. * * @param values * 命名参数,按名称绑定 * @return 更新记录数. */ public int batchExecute(final String hql, final Map<String, ?> values) { return createQuery(hql, values).executeUpdate(); } /** * 根据查询 HQL 与参数列表创建 Query 对象. 与 find() 函数可进行更加灵活的操作. 比如: * <pre> * Query query = session.createQuery("from Order o where o.customer=":customer and " * + "o.orderNumber like :orderNumber"); * query.setParameter(1, customer); * query.setParameter(2, orderNumber); * </pre> * 上面的程序默认是使用了 Hibernate 的自动根据参数值的 Java 类型来进行对应的映射类型, * 这样可以减少在第三个参数中指定 Java 类型的麻烦. 但是对于日期的 java.util.Date 类型, * 会对应多种 Hibernate 映射类型, 如 Hibernate.DATE 或 Hibernate.TIMESTAMP, * 因此必须在 setParameter() 方法中显式地指定到底对应那种 Hibernate 映射类型. 比如: * <pre> * Query query = session.createQuery("from Customer c where c.birthday=:birthday"); * query.setParameter("birthday", birthday, Hibernate.DATE); * </pre> * * @param values * 数量可变的参数, 按顺序绑定 */ public Query createQuery(final String queryString, final Object... values) { Assert.hasText(queryString, "queryString can not be null"); Query query = getSession().createQuery(queryString); if (values != null) { for (int i = 0; i < values.length; i++) { // 按顺序绑定参数 query.setParameter(i, values[i]); } } return query; } /** * 根据查询 HQL 与参数列表创建 Query 对象. 与 find() 函数可进行更加灵活的操作. 比如: * <pre> * Query query = session.createQuery("from Customer as c where c.name=:name " * + "and c.age=:age"; * Customer customer = new Customer(); * customer.setName("Tom"); * customer.setAge(21); * // 命名参数中的 "name" 和 "age" 分别对应 Customer 类的 name 属性和 age 属性, 否则会抛异常 * query.setProperties(customer); * </pre> * 在本方法中采用的是传递一个 {@link Map} 作为参数, 同样会根据 Map 的名来进行自动绑定. 另外, * setProperties() 方法调用 setParameter() 方法, setParameter() 方法再根据 Customer * 对象的属性的 Java 类型来判断 Hibernate 映射类型. 如果命名参数为日期类型, 则不能通过 * setProperties() 方法来绑定. 另外, 参数绑定对 null 是安全的, 比如如下代码不会抛异常: * <pre> * String name = null; * session.createQuery("from Customer c where c.name=:name").setString("name", name).list(); * </pre> * 上面的查询语句对应的 SQL 语句是: * <pre> * select * from CUSTOMERS where NMAE=null; * </pre> * 这条查询语句的查询结果永远为空. 如果要查询名字为 null 的客户, 应该使用 "is null" * 比较运算符, 比如: * <pre> * // HQL 检索方式 * session.createQuery("from Customer c where c.name is null"); * // QBC 检索方式 * session.createCriteria(Customer.class).add(Restrictions.isNull("name")); * </pre> * * @param values * 命名参数, 按名称绑定 * @see #find(String, Object...) */ public Query createQuery(final String queryString, final Map<String, ?> values) { Assert.hasText(queryString, "queryString can not be null"); Query query = getSession().createQuery(queryString); if (values != null) { // 把命名参数与对象的属性值进行绑定 query.setProperties(values); } return query; } /** * 根据 Criterion 条件创建 Criteria. 与 find() 函数可进行更加灵活的操作. * * @param criterions * 数量可变的 Criterion */ public Criteria createCriteria(final Criterion... criterions) { Criteria criteria = getSession().createCriteria(entityClass); for (Criterion c : criterions) { criteria.add(c); } return criteria; } /** * 初始化对象. 使用 load() 方法得到的仅是对象 Proxy, 在传到 View 层前需要进行初始化. * 如果传入 entity, 则只初始化 entity 的直接属性, 但不会初始化延迟加载的关联集合和属性. * 如需初始化关联属性,需执行: * <pre> * Hibernate.initialize(user.getRoles()) // 初始化User的直接属性和关联集合 * Hibernate.initialize(user.getDescription()) // 初始化User的直接属性和延迟加载的Description属性 * </pre> */ public void initProxyObject(Object proxy) { Hibernate.initialize(proxy); } /** * 为 Query 添加 distinct transformer. 预加载关联对象的 HQL 会引起主对象重复, * 需要进行 distinct 处理. * * @param query * @return */ public Query distinct(Query query) { query.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); return query; } /** * 为 Criteria 添加 distinct transformer. 预加载关联对象的 HQL 会引起主对象重复, * 需要进行 distinct 处理. * * @param criteria * @return */ public Criteria distinct(Criteria criteria) { criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); return criteria; } /** * 判断对象的属性值在数据库内是否唯一.<br> * 在修改对象的情景下, 如果属性新修改的值 (value) 等于属性原来的值 (orgValue) 则不作比较. * * @param propertyName * @param newValue * @param oldValue * @return */ public boolean isPropertyUnique(final String propertyName, final Object newValue, final Object oldValue) { if (newValue == null || newValue.equals(oldValue)) { return true; } Object object = findUniqueBy(propertyName, newValue); return (object == null); } /** * 清除当前 Session. */ public void flush() { getSession().flush(); } }
[/size]
评论
2 楼
davinsam
2012-08-31
import org.mysterylab.utopiaframework.core.orm.Page;
import org.mysterylab.utopiaframework.core.orm.PropertyFilter;
import org.mysterylab.utopiaframework.core.orm.PropertyFilter.MatchType;
import org.mysterylab.utopiaframework.util.reflect.ReflectionUtil;
这些类怎么实现???
import org.mysterylab.utopiaframework.core.orm.PropertyFilter;
import org.mysterylab.utopiaframework.core.orm.PropertyFilter.MatchType;
import org.mysterylab.utopiaframework.util.reflect.ReflectionUtil;
这些类怎么实现???
1 楼
davinsam
2012-08-31
dao类使用说明弄错了,怎么跟basehibernatedao一样啦?能重新写一下吗?
发表评论
-
hibernate find illustrate
2012-05-03 17:05 735Find()方法下FetchType.LAZY、FetchTy ... -
hibernate relative annotation
2012-05-03 16:57 1317[size=large] @TriggerRemove Re ... -
hibernate Join-subclass
2012-05-03 11:13 1777Join-subclass基础(用于两个表之间通过连接外键) ... -
hibernate component
2012-05-03 11:10 949Component 本次做MySNS时也用到了Componen ... -
SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结
2012-04-20 13:01 1241转载【http://sishuok.com/for ...
相关推荐
《深入解析HibernateDao.java》 在Java开发领域,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。本文将深入探讨`HibernateDao.java`这一关键组件,揭示其背后的原理与实践应用。 `...
HibernateDao 是一种基于 Hibernate ORM(对象关系映射)框架的通用数据访问对象,它简化了对数据库的操作,提供了更高级别的抽象,使开发者能够更加专注于业务逻辑而不是底层的数据操作。在Java开发中,Hibernate...
hibernateDao工具类
本文将深入探讨如何使用代理来实现Hibernate Dao层的自动事务管理,以提高代码的可维护性和事务处理的效率。 首先,理解Dao(Data Access Object)层的作用至关重要。Dao层是应用与数据库之间的一层抽象,它封装了...
Hibernate DAO(Data Access Object)生成工具是用于自动化创建数据访问层对象的实用程序,它可以显著提高开发效率,尤其是在处理大量数据库交互的项目中。DAO模式是一种设计模式,它提供了对数据库操作的抽象,使得...
《深入理解HibernateDAO的写法》 在Java企业级开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。而HibernateDAO则是基于Hibernate进行数据访问的对象,是业务逻辑层和持久层之间...
**Hibernate DAO生成器详解** 在Java开发中,Hibernate是一个非常流行的ORM(对象关系映射)框架,它使得Java开发者能够方便地操作数据库,无需过多关注SQL的细节。然而,随着项目规模的扩大,手动编写数据访问对象...
"Hibernate封装DAO层"就是将Hibernate的功能整合到DAO设计模式中,以实现更加高效、规范的数据库操作。 1. **DAO设计模式**: DAO模式是软件设计模式的一种,它的核心思想是创建一个独立于具体数据库操作的对象,...
### 一个通用的Hibernate DAO知识点解析 #### 一、标题:一个通用的Hibernate DAO - **含义**:此标题指的是一种使用Hibernate框架实现的数据访问对象(DAO)设计模式的具体实现方式。它强调了该DAO类是通用的,...
标题 "使用模式设计及java5新特性在HibernateDAO中的应用" 涉及到的是软件开发中的两个关键领域:设计模式和Java编程语言的新特性,特别是在数据访问对象(DAO)层如何结合使用它们。这篇文章可能详细阐述了如何利用...
本资源“Spring + Hibernate DAO 代码上传”显然提供了一组整合了这两个框架的代码示例,帮助开发者理解如何在实际项目中利用它们进行数据访问操作。以下是关于Spring和Hibernate以及它们整合使用的详细知识点: 1....
Hibernate DAO(Data Access Object)是Java开发中一种常见的数据访问层设计模式,它与Hibernate ORM框架结合使用,用于处理数据库操作。DAO模式的主要目的是将业务逻辑与数据访问逻辑分离,提高代码的可重用性和可...
Haha.Hibernate SprintSideExt 通用HibernateDAO 文章资源 详见:http://blog.csdn.net/lijun7788/article/details/6658847
开发HIBERNATE,只要继承此类.一切变得简单多了. 继承的DAO类可一行代码实行增,删,改. 另外也支持查询.分页查询. 在事务方面还不完善. 代码是我自己写的.资源分要使用5点. 但大家可以在下载后点评一下.这样5点的积分...
这是一个DAO代码生成工具,只需要配置好数据库连接信息,和按照你的需求配置要生成到的路径,运行BAT文件就会生成操作数据库的代码,可以完成增加,删除,修改,查询等操作,不需要写SQL语句,生成完全面向对象的代码....
在提供的代码片段中,我们可以看到一个`HibernateDao`类,它是对Hibernate的一些基本操作进行了封装,包括获取、删除等方法。下面将详细解释这些知识点。 1. **SessionFactory**: `SessionFactory`是Hibernate的...