公司中一直使用的都是ibatis,因其简单,灵活,容易进行调优等。最近由于项目需要使用到了hibernate,我们的项目中DO对象非常多,如果使用ibatis或者hibernate xml配置的话会非常烦琐,有太多的重复劳动,结合考虑了下,决定使用hibernate annotation来实现。下面是hibernation持久化的泛型Dao接口及实现类,网上有很多,这里粘贴上来,是为了文章的完整性。
1. interface MetrixGenericDao.java
- package com.alibaba.corp.metrix.admin.biz.edi.dao.generic;
- /**
- * Copyright 1999-2100 Alibaba.com All right reserved. This software is the
- * confidential and proprietary information of Alibaba.com
- * ("Confidential Information"). You shall not disclose such Confidential
- * Information and shall use it only in accordance with the terms of the license
- * agreement you entered into with Alibaba.com.
- *
- * @Author: leon Mao
- * @Date: 06/03/2012
- * @Time: 16:08
- * @Description: //TODO
- */
- import java.util.List;
- import java.util.Map;
- /**
- * *
- *
- * @param <T> 泛型,指实体类 type
- * @param <PK> 泛型,指实体类主键的数据类型,如Integer,Long
- */
- public interface MetrixGenericDao<T,PK> {
- /**
- * 保存指定实体类
- *
- * @param entity 实体类
- */
- public PK save(T entity);
- /**
- * batch insert
- * @param entities
- */
- public void batchInsert(List<T> entities);
- /**
- * 删除指定实体
- *
- * @param entity 实体类
- */
- public void delete(T entity);
- /**
- * * 删除实体
- *
- * @param entityClass 实体类名
- * @param id 实体的ID
- */
- public void deleteById(Class<T> entityClass, PK id);
- /**
- * 更新或保存指定实体
- *
- * @param entity 实体类
- */
- public void saveorupdate(T entity);
- /**
- * * 更新实体 可用于添加、修改、删除操作
- *
- * @param hql 更新的HQL语句
- * @param params 参数,可有项目或多项目,代替Hql中的"?"号
- */
- public void update(String hql, Map<String,Object> params);
- /**
- * @param entity 条件实体
- * @return 结合
- */
- public List<T> findByExample(T entity);
- /**
- * 获取所有实体集合
- *
- * @param entityClass 实体
- * @return 集合
- */
- public List<T> findAll(Class<T> entityClass);
- public List<T> findAll(Class entityClass, String hql, Map<String,Object> params, int start, int limit);
- /**
- * 查找指定PK实体类对象
- *
- * @param entityClass 实体Class
- * @param id 实体PK
- * @return 实体对象
- */
- public T findById(Class<T> entityClass, PK id);
- /**
- * * 按HQL条件查询列表
- *
- * @param hql 查询语句,支持连接查询和多条件查询
- * @param params 参数数组,代替hql中的"?"号
- * @return 结果集List
- */
- public List<T> findByHql(String hql, Map<String,Object> params);
- /**
- * 查找指定属性的实体集合
- *
- * @param entityClass 实体
- * @param propertyName 属性名
- * @param value 条件
- * @return 实体集合
- */
- public List<T> findByProperty(Class<T> entityClass, String propertyName, Object value);
- /**
- * 获得总记录数
- */
- public Integer getTotalCount(Class<T> entityClass);
- }
2. implement MetrixGenericDaoImpl
- package com.alibaba.corp.metrix.admin.biz.edi.dao.generic;
- import java.io.Serializable;
- import java.sql.SQLException;
- import java.util.List;
- import java.util.Map;
- import org.hibernate.HibernateException;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.orm.hibernate3.HibernateCallback;
- import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
- import org.springframework.stereotype.Repository;
- import com.alibaba.corp.metrix.admin.biz.dataprocess.job.base.BeanFactoryUtil;
- /**
- * Copyright 1999-2100 Alibaba.com All right reserved. This software is the
- * confidential and proprietary information of Alibaba.com
- * ("Confidential Information"). You shall not disclose such Confidential
- * Information and shall use it only in accordance with the terms of the license
- * agreement you entered into with Alibaba.com.
- *
- * @Author: leon Mao
- * @Date: 06/03/2012
- * @Time: 16:23
- * @Description: //TODO
- */
- @SuppressWarnings("unchecked")
- @Repository("genericDao")
- //声明此类为数据持久层的类
- public class MetrixGenericDaoImpl<T, PK extends Serializable> extends HibernateDaoSupport implements
- MetrixGenericDao<T, PK> {
- private static Logger logger = LoggerFactory.getLogger(MetrixGenericDaoImpl.class);
- public MetrixGenericDaoImpl() {
- setSessionFactory((SessionFactory) BeanFactoryUtil.getBean("sessionFactory"));
- }
- public PK save(T entity) {
- return (PK) super.getHibernateTemplate().save(entity);
- }
- public void batchInsert(final List<T> entities) {
- super.getHibernateTemplate().execute(new HibernateCallback() {
- public Object doInHibernate(Session session) throws HibernateException, SQLException {
- for (T entity : entities) {
- try {
- session.save(entity);
- } catch (Exception e) {
- if (logger.isWarnEnabled()) {
- logger.warn("Session Save Error: ", e);
- }
- session.update(entity);
- }
- }
- return entities.size();
- }
- });
- }
- public void delete(T entity) {
- super.getHibernateTemplate().delete(entity);
- }
- public void deleteById(Class<T> entityClass, PK id) {
- super.getHibernateTemplate().delete(findById(entityClass, id));
- }
- public void saveorupdate(T entity) {
- super.getHibernateTemplate().saveOrUpdate(entity);
- }
- public void update(String hql, Map<String, Object> params) {
- Query query = super.getSession().createQuery(hql);
- if (params != null && params.size() > 0) {
- for (String key : params.keySet()) {
- query.setParameter(key, params.get(key));
- }
- }
- query.executeUpdate();
- }
- public List<T> findAll(Class<T> entityClass) {
- return super.getHibernateTemplate().loadAll(entityClass);
- }
- public List<T> findAll(Class entityClass, String hql, Map<String, Object> params, int start,
- int limit) {
- Query query = super.getSession().createQuery(hql);
- if (params != null && params.size() > 0) {
- for (String key : params.keySet()) {
- query.setParameter(key, params.get(key));
- }
- }
- if (start != 0 && limit != 0) {
- query.setFirstResult(start).setMaxResults(limit);
- }
- return query.list();
- }
- public List<T> findByExample(T entity) {
- return super.getHibernateTemplate().findByExample(entity);
- }
- public List<T> findByHql(String hql, Map<String, Object> params) {
- Query query = super.getSession().createQuery(hql);
- if (null != params && params.size() > 0) {
- for (String key : params.keySet()) {
- query.setParameter(key, params.get(key));
- }
- }
- return query.list();
- }
- public T findById(Class<T> entityClass, PK id) {
- return (T) super.getHibernateTemplate().get(entityClass, id);
- }
- public Integer getTotalCount(Class entityClass) {
- return getSession().createQuery("from " + entityClass.getSimpleName()).list().size();
- }
- public List<T> findByProperty(Class<T> entityClass, String propertyName, Object value) {
- String queryString = "from " + entityClass.getName() + " as model where model."
- + propertyName + "=?";
- return super.getHibernateTemplate().find(queryString, value);
- }
- }
3. spring配置
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
- <bean id="propertyConfigurer_metrix_service"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="order" value="1"/>
- <property name="ignoreUnresolvablePlaceholders" value="true"/>
- <property name="locations">
- <list>
- <value>classpath*:META-INF/metrix-admin.properties</value>
- </list>
- </property>
- </bean>
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="${metrix.jdbc.driverClassName}"/>
- <property name="url" value="${metrix.jdbc.url}"/>
- <property name="username" value="${metrix.jdbc.username}"/>
- <property name="password" value="${metrix.jdbc.password}"/>
- <property name="maxActive" value="10"/>
- <property name="maxIdle" value="5"/>
- <property name="minIdle" value="1"/>
- </bean>
- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
- <property name="dataSource" ref="dataSource"/>
- <property name="annotatedClasses">
- <list>
- <value>com.alibaba.corp.metrix.admin.biz.edi.model.domain.taobao.SecurityFlaw</value>
- ...
- </list>
- </property>
- <property name="annotatedPackages">
- <list>
- <value>com.alibaba.corp.metrix.admin.biz.dataprocess.model.domain</value>
- </list>
- </property>
- <property name="hibernateProperties">
- <props>
- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
- <prop key="hibernate.connection.autocommit">true</prop>
- <prop key="hibernate.show_sql">true</prop>
- <prop key="hibernate.jdbc.batch_size">50</prop>
- <prop key="hibernate.jdbc.fetch_size">50</prop>
- </props>
- </property>
- </bean>
- <!-- Dao beans -->
- <!-- <bean id="sqlDaoBaseSupport" abstract="true">
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
- <bean id="securityFlawDao" class="com.alibaba.corp.metrix.admin.biz.edi.dao.SecurityFlawDao" parent="sqlDaoBaseSupport"/>-->
- <bean id="metaManager" class="com.alibaba.corp.metrix.admin.biz.edi.meta.MetaManager" init-method="init"/>
- <bean id="metrixJobInitializer" class="com.alibaba.corp.metrix.admin.biz.dataprocess.job.base.MetrixJobInitializer" init-method="init"/>
- <!-- dao beans -->
- <bean id="securityFlawDao" class="com.alibaba.corp.metrix.admin.biz.edi.meta.MetrixDaoFactoryBean">
- <property name="daoName" value="securityFlawDao"/>
- </bean>
- <bean id="ifreeAvailableResourceDao" class="com.alibaba.corp.metrix.admin.biz.edi.meta.MetrixDaoFactoryBean">
- <property name="daoName" value="ifreeAvailableResourceDao"/>
- </bean>
- <!-- Service beans -->
- <bean id="urlRawDataAccessService" class="com.alibaba.corp.metrix.admin.biz.edi.services.UrlRawDataAccessService"
- init-method="init">
- <property name="rawDataStoreDir" value="${metrix.url.rawdata.store.dir}"/>
- </bean>
- <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <property name="sessionFactory">
- <ref local="sessionFactory"/>
- </property>
- </bean>
- <bean id="transactionInterceptor"
- class="org.springframework.transaction.interceptor.TransactionInterceptor">
- <property name="transactionManager" ref="transactionManager"/>
- <property name="transactionAttributes">
- <props>
- <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
- <prop key="delete*">PROPAGATION_REQUIRED,-Exception</prop>
- <prop key="batchInsert*">PROPAGATION_REQUIRED,-Exception</prop>
- <prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
- <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
- </props>
- </property>
- </bean>
- <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
- <property name="beanNames">
- <list>
- <value>*Dao</value>
- </list>
- </property>
- <property name="interceptorNames">
- <list>
- <value>transactionInterceptor</value>
- </list>
- </property>
- </bean>
- </beans>
4. 由于java在编译期进行了类型擦除,当前我们的业务逻辑中可以直接调用Dao接口,但spring不支持泛型Dao配置,这里做了点猥琐的事情,继承spring的FactoryBean,通过这个类将Dao注入到spring中,并对Dao接口进行了事务配置
- package com.alibaba.corp.metrix.admin.biz.edi.meta;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.springframework.beans.factory.FactoryBean;
- import com.alibaba.corp.metrix.admin.biz.dataprocess.job.base.DefaultMetrixJob;
- import com.alibaba.corp.metrix.admin.biz.edi.dao.generic.MetrixGenericDao;
- import com.alibaba.corp.metrix.admin.biz.edi.dao.generic.MetrixGenericDaoImpl;
- import com.alibaba.corp.metrix.admin.biz.edi.model.domain.taobao.*;
- public class MetrixDaoFactoryBean implements FactoryBean {
- private String daoName;
- private static Map<String, MetrixGenericDaoImpl<?, ?>> daoContainer = new HashMap<String, MetrixGenericDaoImpl<?, ?>>();
- // 用于扩展特殊的保存逻辑
- private static Map<String, DefaultMetrixJob.DomainObjectSaver> savers = new HashMap<String, DefaultMetrixJob.DomainObjectSaver>();
- static {
- // 初始化特定的Dao
- daoContainer.put("securityFlawDao", new MetrixGenericDaoImpl<SecurityFlaw, String>());
- daoContainer.put("ifreeAvailableResourceDao",
- new MetrixGenericDaoImpl<IfreeAvailableResource, String>());
- daoContainer.put("ifreeProjectDao", new MetrixGenericDaoImpl<IfreeProject, String>());
- daoContainer.put("ifreeRequirementDao",
- new MetrixGenericDaoImpl<IfreeRequirement, String>());
- daoContainer.put("ifreeOrderDao", new MetrixGenericDaoImpl<IfreeOrder, String>());
- daoContainer.put("wfFaultDao", new MetrixGenericDaoImpl<WfFault, String>());
- }
- public String getDaoName() {
- return daoName;
- }
- public void setDaoName(String daoName) {
- this.daoName = daoName;
- }
- public Object getObject() throws Exception {
- if (daoContainer.keySet().contains(daoName)) {
- return daoContainer.get(daoName);
- } else {
- throw new RuntimeException(daoName + " has no corresponding Object!");
- }
- }
- public Class getObjectType() {
- return MetrixGenericDao.class;
- }
- public boolean isSingleton() {
- return true;
- }
- private static MetrixGenericDao getDao(String daoName) {
- return daoContainer.get(daoName);
- }
- }