[Hibernate] - Generic Dao

使用泛型写了一个通用的Hibernate DAO类。

 


GenericDao接口

package com.my.dao;

import java.io.Serializable;
import java.util.List;

/**
 * Generic DAO interface
 * @author Robin
 *
 * @param <T>
 * @param <PK>
 */
public interface GenericDao<T extends Serializable, PK extends Serializable> {
    /**
     * Create entity
     * @param entity
     */
    void create(T entity);
    
    /**
     * Update entity
     * @param entity
     */
    void update(T entity);
    
    /**
     * Create or Update entity
     * @param entity POJO
     */
    void saveOrUpdate(T entity);
    
    /**
     * Delete entity
     * @param entity
     */
    void delete(T entity);
    
    /**
     * Find entity by id
     * @param id ID
     * @return Entity
     */
    T find(PK id);
    
    /**
     * Find all entities
     * @return
     */
    List<T> findAll();
    
    /**
     * Find all entities by paging
     * @param pageNumber
     * @param pageSize
     * @return
     */
    List<T> findList(int pageNumber, int pageSize);
    
    /**
     * All row count
     * @return
     */
    Long count();
}

 

GenericDaoSupport主类:

package com.my.dao;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

/**
 * Generic Dao Base Class
 * @author Robin
 *
 */
public abstract class GenericDaoSupport {
    @Resource
    protected SessionFactory sessionFactory;
    
    /**
     * Get Hibernate Session
     * @return
     */
    public Session getSession() {
        return this.sessionFactory.getCurrentSession();
    }
}

 

通用DAO类实现:

package com.my.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.hibernate.criterion.Projections;

import com.my.dao.GenericDao;
import com.my.dao.GenericDaoSupport;

/**
 * Generic DAO class
 * @author Robin
 *
 * @param <T>
 * @param <PK>
 */
@SuppressWarnings("all")
public class GenericDaoImpl<T extends Serializable, PK extends Serializable>
        extends GenericDaoSupport implements GenericDao<T, PK> {
    // Entity class
    private Class<T> entityClass;

    /**
     * Constructor
     */
    public GenericDaoImpl() {
        // 通过反射获取T的类型信息实例
        this.entityClass = (Class<T>) ((ParameterizedType) this.getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
    }
    
    /**
     * Create entity
     * @param entity
     */
    @Override
    public void create(T entity) {
        getSession().save(entity);
    }

    /**
     * Update entity
     * @param entity
     */
    @Override
    public void update(T entity) {
        getSession().update(entity);
    }

    /**
     * Create or Update entity
     * @param entity
     */
    @Override
    public void saveOrUpdate(T entity) {
        getSession().saveOrUpdate(entity);
    }
    
    /**
     * Delete entity
     * @param entity
     */
    public void delete(T entity){
        getSession().delete(entity);
    }

    /**
     * Find entity by id
     * @param id
     * @return Entity
     */
    @Override
    public T find(PK id) {
        return (T) getSession().get(entityClass, id);
    }

    /**
     * Find all entities
     * @return
     */
    @Override
    public List<T> findAll() {
        return getSession().createCriteria(entityClass).list();
    }
    
    /**
     * Find all entities by paging
     * @param pageNumber
     * @param pageSize
     * @return
     */
    public List<T> findList(int pageNumber, int pageSize) {
        return getSession().createCriteria(entityClass)
                .setFirstResult((pageNumber - 1) * pageSize)
                .setMaxResults(pageSize)
                .list();
    }
    
    /**
     * All row count
     * @return
     */
    public Long count() {
        Long count = (Long)getSession().createCriteria(entityClass)
                .setProjection(Projections.rowCount())
                .uniqueResult();
        if(count == null) {
            return (long)0;
        }
        else {
            return count;
        }
    }
}

 

Hibernate实体:

package com.my.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name = "account")
public class Account implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long id;

    @Column(name = "name", length = 200)
    private String name;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

实体类必需继承Serializable接口。


 

使用方法例子:

写一个AccountDao接口

package com.my.dao;

import org.springframework.stereotype.Repository;

import com.my.entity.Account;

@Repository
public interface AccountDao extends GenericDao<Account, Long> {
}

AccountDao接口的实现:

package com.my.dao.impl;

import org.springframework.stereotype.Repository;
import com.my.dao.AccountDao;
import com.my.entity.Account;

@Repository(value = "accountDao")
public class AccountDaoImpl extends GenericDaoImpl<Account, Long> implements AccountDao {
}

 

Service的实现和使用:

package com.my.service;

import java.util.List;

import com.my.entity.Account;

public abstract class AccountService {
    /**
     * Add new account
     * @param account Account
     */
    public abstract void add(Account account);
    
    /**
     * Find entity by id
     * @param id
     * @return
     */
    public abstract Account find(long id);
    
    /**
     * Find all entities
     * @return
     */
    public abstract List<Account> findAll();
    
    /**
     * Find all entities by paging
     * @param pageNumber
     * @param pageSize
     * @return
     */
    public abstract List<Account> findList(int pageNumber, int pageSize);
    
    /**
     * All row count
     * @return
     */
    public abstract long count();
}
package com.my.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.my.dao.AccountDao;
import com.my.entity.Account;
import com.my.service.AccountService;

@Service(value = "accountService")
public class AccountServiceImpl extends AccountService {
    @Resource(name = "accountDao")
    private AccountDao accountDao;
    
    public void add(Account account) {
        accountDao.saveOrUpdate(account);
    }

    @Override
    public Account find(long id) {
        return accountDao.find(id);
    }
    
    @Override
    public List<Account> findAll(){
        return accountDao.findAll();
    }

    @Override
    public List<Account> findList(int pageNumber, int pageSize) {
        return accountDao.findList(pageNumber, pageSize);
    }

    @Override
    public long count() {
        return accountDao.count();
    }
}

 

可以看到上面Service的调用对应的AccountDao中,不需要再写其它方法。因为在通用DAO中已经实现了。AccountDao只需要加入其它额外的方法即可,比如说特例的查询。

当然可以把通用DAO封装得更加“完美”,比如把查询条件都写上。

网上有一些通用的DAO写法,会把HQL写在Service层,这种破坏了BLL和DAO的分离。

 

附上Spring的xml配置:

<?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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://127.0.0.1/test" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
            <list>
                <value>com.my.entity</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
                hibernate.hbm2ddl.auto=update
                hibernate.show_sql=true
                hibernate.format_sql=false
                hibernate.cache.use_second_level_cache=true
                hibernate.cache.use_query_cache=false
                hibernate.cache.provider_class=org.hibernate.cache.internal.NoCacheProvider
                hibernate.current_session_context_class= org.springframework.orm.hibernate4.SpringSessionContext
            </value>
        </property>
    </bean>
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    <context:component-scan base-package="com.my" />
    
    <tx:annotation-driven transaction-manager="txManager" />
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="*" read-only="true"/>
            <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="change*" propagation="REQUIRED" rollback-for="Exception"/>
        </tx:attributes>
    </tx:advice>
    
    <aop:config>
      <aop:pointcut id="allServiceMethods" expression="execution(* com.my.service.*.*(..))"/>
      <aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"/>
    </aop:config>

</beans>

 

posted @ 2014-09-16 16:43  横渡  阅读(1969)  评论(0编辑  收藏  举报