`
ll_feng
  • 浏览: 382024 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

浅析泛型DAO在SSH构架中的应用

阅读更多
自JDK1.5后,泛型在很多方面开始应用。DAO层也开始有了基于泛型的开发模式.可能也正因为如此,有不少人认为DAO作为企业级开发的一层可以去掉了,理由就是只要有一个泛型DAO就可以搞定了!而我认为哪怕只有一个DAO,也应算是一个层,层的定义不是由它下面的组件多少决定的,而是由它扮演的角色来决定的。
这里主要就泛型DAO的开发举个例子:

一、泛型DAO的接口
/**
 * Generic DAO (Data Access Object) with common methods to CRUD POJOs.
 *
 * <p>Extend this interface if you want typesafe (no casting necessary) DAO's for your
 * domain objects.
 *
 * @author llf
 */
public interface GenericDao <T, PK extends Serializable> {

    public List<T> findByHsql(String hsql);
    
    //为了突出上面的例子方法,以下省掉N多方法,可以在用时再扩展
    
}


二、定义泛型DAO的实现(这里为Hibernate实现)
/**
 * 本dao类基于hibernate,所以需要在applicationContext.xml中定义SessionFacotry
 * @author llf
 */
public class BaseDaoHibernate<T, PK extends Serializable> implements GenericDao<T, PK> {

	private SessionFactory sessionFactory;
	private Class<T> clazz;

	@SuppressWarnings("unchecked") 
	public BaseDaoHibernate() {
		//以下代码无法实现,类型转换有错,以后再分析
		/*Type type = this.getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
        	clazz = (Class)((ParameterizedType)type).getActualTypeArguments()[0];
        } else {
            throw new RuntimeException(this.getClass().getName()+ "没有指定继承的po类型");
        }*/
	}
	
    /**
     * 上面无参数构造方法的替代
     * 以便在sevice中通过构造为dao指定实体类的类型。不然就无法实现泛型的效果了
     */
	@SuppressWarnings("unchecked") 
	public BaseDaoHibernate(SessionFactory sessionFactory,Class clazz) {
		this.sessionFactory = sessionFactory;
		this.clazz = clazz;
	}

	public Class<T> getClazz() {
		return clazz;
	}


	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}


	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}


    /**
     * 从sessionFactory中取得hibernate的session对象,这是dao的关键因素
     */
	public Session getSession() {
        
        return sessionFactory.openSession();
    }


    /**
     * 实现接口中的例子方法
     */
	public List<T> findByHsql(String hsql) {
		Query queryObject = getSession().createQuery(hsql);
		return queryObject.list();
	}

}


注:这里的无参数构造方法在很多文章中都看到了,但我无法成功运用,很遗憾!如果能成功那么就勿须在service中用用那种怪异的构造方法了。另,听说spring3.0已提供了支持泛型的HibernateTemplate,希望能早点看到。


三、在Service层注入并应用泛型DAO
/**
 * 
 * @author Administrator
 */
@Service("userManager")
public class UserManagerImpl implements UserManager {
	
	private GenericDao<User, String> baseDao;
	
	/**
	 * 将sessionFactory注入到dao,并为泛型dao指定实体类型
	 * @param sessionFactory
	 */
	@Autowired
	private void setSessionFactory(SessionFactory sessionFactory){
		baseDao = new BaseDaoHibernate<User,String>(sessionFactory,User.class);
	}
	

	/**
	 * 用这个方法作一个查询操作的例子
	 */
	public List<User> getAllUsers() {
		List<User> users = baseDao.findByHsql("from User user");
		return users;
	}
        
    //以下省掉N多业务方法……
}



附、Spring框架配置文件(applicationContext.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:aop="http://www.springframework.org/schema/aop"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xmlns:context="http://www.springframework.org/schema/context"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
    <!--组件的自动扫描,主动加载-->
    <context:component-scan base-package="cn.lvlf">
    	<context:include-filter type="regex" expression=".ssh.demo.service.*.*Manager"/>
    	<context:include-filter type="regex" expression=".ssh.demo.dao.*.*Hibernate"/>
    	<context:include-filter type="regex" expression=".ssh.demo.web.action.*Action"/>
    </context:component-scan>
	
    <!--数据源-->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"	destroy-method="close">
		<property name="driverClass" value="${jdbc.driverClassName}"/>
		<property name="jdbcUrl" value="${jdbc.url}"/>  
        <property name="user" value="${jdbc.username}"/>  
        <property name="password" value="${jdbc.password}"/>  
        <property name="minPoolSize" value="5"/>  
        <property name="maxPoolSize" value="30"/>  
    </bean>
    
    <!--Hibernate的session工厂-->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">   
        <property name="dataSource" ref="dataSource"/>
        <property name="namingStrategy">
			<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
		</property>     
        <property name="hibernateProperties">
            <props>   
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>   
                <prop key="hibernate.cache.use_second_level_cache">false</prop>   
                 <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                <prop key="show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">none</prop>
            </props>   
        </property>
        <property name="packagesToScan" >
			<list>
				<value>cn.lvlf.ssh.demo.model</value>
			</list>
		</property>   
    </bean>
    
    <!--定义事务管理组件-->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	
    <!--基于注解的事务声明-->
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>


小结:
虽然我们可以用泛型DAO减少许多代码,但是Dao作为一个层,建议在必要时还是要写各自模块的dao(可以让它继承自泛型dao),这样可以保证逻辑的清晰,方便代码重构!
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics