Spring整合Hibernate

 

DataSource

   标准化的取得连接的方式

    spring连接池    

        dbcp配置

 

 

Hibernate使用Annotation的方式

 

简单整合

  •   1. 先在spring容器里面初始化一个SessionFactory
  •   2. 注入需要的连接信息
    <bean id="dataSource" destroy-method="close"
        class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName"
            value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    <bean id="sessionFactory"   class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="annotatedClasses">
            <list>
                <value>com.bjsxt.model.User</value>
<value>com.bjsxt.model.Log</value>
</list>
</property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQLDialect
                </prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

 

       sessionFactory的class并不是hibernate自己的,而是使用的Spring的AnnotationSessionFactoryBean

     

      它里面有很多的属性:

     

      

      他需要注入的信息有:(也就是这个类中含有的set方法)

           1. dataSource  数据源

           2. annotateClasses

               它需要注入的信息是一个集合,表示哪些实体类上加了注解,需要用到hibernate

           3.  hibernateProperties

               这是一个Properties类型的对象,表示Hibernate的一些属性,比如Hibernate方言等。

 

         上面的例子中是用的注入 annotateClasses这个属性,但是如果类非常多,这个就非常不方便了

         我们可以注入 packagesToScan这个属性

         

      <property name="packagesToScan">
            <list>
                <value>com.bjabc.model</value>                
            </list>
        </property>

 

         

        然后再在需要的实体类上加上Hibernate需要的注解即可,比如@Entity之类的

               

        这种方式是Annotation的方式,不需要hibernate的配置文件

       如果使用xml方式   class="org.springframework.orm.hibernate3.annotation.SessionFactoryBean

       而且还有加入一个name = mappingResources value=....hbm.xml的子属性,表示hibernate的配置文件

事务管理

  

       首先要搞清事务的开始和结束

       有两种管理方式

  •    Annotation
  •    XML

         

          先说说Annotation

 

       首先要在spring的bean.xml中引入annotation驱动

       然后把sessionFactory交给事务的txManager管理

<bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
 </bean>
    
 <tx:annotation-driven transaction-manager="txManager"/>

 

       接下来就是配置需要添加事务管理的类了

       比如是加在管理层上

       

@Transactional(readOnly = true)
public class UserServiceImpl  implements UserService {

    public Foo getFoo(String name) {
        // do something
    }

   
    @Transactional(propagation = Propagation.REQUIRED)
    public void add(User user) {
        userDAO.save(user);      
} }

 

那么对于DAO层

public class UserDAOimpl  implements UserDAO {

    private SessionFactory sessionFactory;

   
    public void save(User user) {
        
       session s = sessionFactory.getCurrentSession();
       s.save(user);      

    }
}

         这里必须要getCurrentSession,就是说这个时候连接已经创建了,不可以再重新create了。

 

 

         类或者方法上上只需要加入@Transactional 就可以了

 

      但是有很多属性

      最要的属性必须要加上的 (不加也一样,默认就是)

        propagation = Propagation.REQUIRED

      其他的

       readOnly = false   

      表示建立一个readOnly的连接,对于不需要增删改只需要查的动作

      有两个好处, 1。 提高性能, 2,防止意外的修改操作

                roolBackFor

       默认下都是对于runtimeException

 

       

        XML方式

 

        也就是spring 的AOP方式

      

    <bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>


    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="getUser" read-only="true" />
            <tx:method name="add*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

   
定义一个切面,表示事务,并且加入到相应方法
<aop:config> <aop:pointcut id="bussinessService" expression="execution(public * com.bjsxt.service..*.*(..))" /> <aop:advisor pointcut-ref="bussinessService" advice-ref="txAdvice" /> </aop:config>

 

     然后在类上就不用加那些标记了

 

     实际开发过程中,用的xml方法比较多

     因为不用在每个方法上加标记

 

 

 

HibernateTemplate

 

         里面有一种设计模式:Template Method 模板方法

   

   把对sessionFactory的管理交给hibernateTempate

   spring的容器里

<bean id="sessionFactory">
...
</bean>


<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"></property>
</bean>

 

   看一下HibernateTempate这个类的源码,可以看到里面有几个属性,需要注入

   比如有一个setSessionFactory()方法

 

   而这个类也已经把sessionFactory里的很多方法都封装好了

   比如load()方法,save()方法等。

     

 

 

     所以在程序里直接调用这些方法就行了

 

     那么在UserDAOimpl里面

     就不需要像以前那样有一个sessionFactory对象了

     只需要有一个HibernateTemplate对象就可以了,然后通过注入获得这个对象

    然后调用这个对象的save()方法等等。

    

     

 

    那么它内部的原理是什么呢?

    可以看一下 hibernateTemplate.save方法的源码

 

     

 

        这个方法的实现过程可以这么理解

     所谓模板方法,其实就是说我们之前用sessionFactory在各个DAO中建立连接和断开连接的操作都是一样的,所以每个DAO的开始和结束都差不多i,所以我们定义一个方法,他的开始和结束一样,然后再在中间插入我们自定义的操作就行了。

     

     

 

 

 

     

        hibernate可以封装jdbc,jdo,orm等很多中间层的产品

        但是有两个相同的封装过程

 

        1. 提供特定的Template

      2. 所有的异常会封装从成DataAcessExceptin

           这是一个runtime异常,会回滚

 

 

       callback 回调/钩子

 

      

 

posted on 2014-12-17 16:11  飞鸟快跑  阅读(477)  评论(0编辑  收藏  举报