Spring+Hibernate的典型配置

Spring 框架提供了对 Hibernate、JDO 和 iBATIS SQL Maps 的集成支持。Spring 对 Hibernate 的支持是第一级的,整合了许多 IOC 的方便特性,解决了许多典型的 Hibernate 集成问题。框架对 Hibernate 的支持符合 Spring 通用的事务和数据访问对象(DAO)异常层次结构。

1、配置datasource

现在常用的开源数据连接池主要有c3p0、dbcp和proxool三种,其中:hibernate开发组推荐使用c3p0;spring开发组推荐使用dbcp(dbcp连接池有weblogic连接池同样的问题,就是强行关闭连接或数据库重启后,无法reconnect ,告诉连接被重置,这个设置可以解决);hibernate in action推荐使用c3p0和proxool。

使用dbcp的配置片段例子:

1     <bean id="exampleDataSource" class="org.apache.commons.dbcp.BasicDataSource">
2         <property name="driverClassName" value="com.mysql.jdbc.Driver" />
3         <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=UTF-8" />
4         <property name="username" value="root" />
5         <property name="password" value="" />
6         <property name="initialSize" value="5" />
7         <property name="maxActive" value="10" />
8     </bean>

使用proxool的配置片段例子:

 1     <bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
 2         <property name="alias" value="proxoolDataSource"/>
 3         <property name="driver" value="com.mysql.jdbc.Driver" />
 4         <property name="driverUrl" value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=UTF-8" />
 5         <property name="user" value="root" />
 6         <property name="password" value="" />
 7         <property name="statistics" value="1m,15m,1h,1d" />
 8         <property name="maximumConnectionCount" value="40"/>
 9         <property name="minimumConnectionCount" value="5"/>        
10         <property name="simultaneousBuildThrottle" value="30"/>
11     </bean>

读配置文件的方式引用属性: 

1     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
2         <property name="location" value="/WEB-INF/jdbc.properties"/>
3     </bean>
4     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
5         <property name="driverClassName" value="${jdbc.driverClassName}"/>
6         <property name="url" value="${jdbc.url}"/>
7         <property name="username" value="${jdbc.username}"/>
8         <property name="password" value="${jdbc.password}"/>
9     </bean>

配置文件“jdbc.properties”内容为:

jdbc.driverClassName= com.mysql.jdbc.Driver 
jdbc.url= jdbc:mysql://localhost:3309/sampledb 
jdbc.username=root 
jdbc.password=1234 

2、配置sessionFactory

使用Hibernate的主要接口是org.hibernate.Session。Session接口提供了基本的CRUD数据访问功能,获取Hibernate Session是通过Hibernate的SessionFactory接口,负责Session的打开、管理和关闭。Spring提供了Hibernate Session工厂Bean来获取Hibernate的SessionFactory。

如果使用XML文件配置持久化域的对象,那么需要使用Spring提供的LocalSessionFactoryBean:

 1     <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
 2         <property name="dataSource" ref="dataSource"/>
 3         <property name="mappingDirectoryLocations">
 4             <list>
 5                 <value>classpath:com/demo/model/mappings</value>
 6             </list>
 7         </property>
 8         <property name="hibernateProperties">
 9             <props>
10                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
11             </props>
12         </property>
13     </bean>

如果使用Annotation注解方式来定义持久化,那么需要使用AnnotationSessionFactoryBean:

1     <bean id="sessionFactory" class="org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean">
2         <property name="dataSource" value="dataSource" />
3         <property name="packageToScan" value="com.habuma.spitter.domain" />
4         <property name="hibernateProperties">
5             <props>
6                 <prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
7             </props>
8         </property>
9     </bean>

声明了sessionFactory后,在DAO中可以使用@Autowired和@Qualifier("sessionFactory")注入属性访问sessionFactory。

Hibernate3之后,引入了上下文session,以保证每个事物使用同一session。Hibernate的SessionFactory提供获取session的方法是getCurrentSession (获得与当前线程绑定的session)。内部通过代理封装,此方式得到的session不仅和当前线程绑定,也无需手动开关。默认在事务提交之后,session自动关闭。引入Spring之后,sessionfactory的创建等都交给Spring管理,用户可以不再考虑session的管理,事务的开启关闭,只需配置事务即可。

另外在Web应用中,session关闭后,因延迟加载导致前台无法显示的问题以往解决方式为强制全部加载,现在也可通过在web.xml中配OpenSessionInViewFilter来解决。如果担心OpenSessionInViewFilter会使系统出现数据库资源的性能瓶颈,则要设计好Service层的服务接口,使延迟加载在Service层内完成。

当Session出现异常时,如果需要Spring自动回滚事务,必须使异常以Spring非检查型异常的形式重新抛出。这需要在Spring应用上下文中添加一个Bean:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

 3、配置Hibernate事务

Spring并不直接管理事物,而是提供了多种事物管理器,它们将事务管理的职责委托给JTA或其他持久化机制所提供的平台相关的事务实现。如果程序的持久化通过Hibernate实现,那么需要使用HibernateTransactionManager,需要在Spring上下文定义中添加如下的<bean>声明,sessionFactory属性需要装配Hibernate SessionFactory。Spring提供了一个tx配置命名空间,借助它可以简化Spring中的声明式事务。:

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3   xmlns:aop="http://www.springframework.org/schema/aop"
 4   xmlns:tx="http://www.springframework.org/schema/tx"
 5   xsi:schemaLocation="
 6   http://www.springframework.org/schema/beans
 7   http://www.springframework.org/schema/beans/spring-beans.xsd
 8   http://www.springframework.org/schema/tx
 9   http://www.springframework.org/schema/tx/spring-tx.xsd
10   http://www.springframework.org/schema/aop
11   http://www.springframework.org/schema/aop/spring-aop.xsd">
12 
13 <!-- 声明事务管理器开始 -->
14     <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
15         <property name="sessionFactory" ref="sessionFactory"/>
16     </bean>
17 <!-- 声明事务 -->
18     <tx:advice id="txAdvice" transaction-manager="txManager">
19         <tx:attributes>
20             <tx:method name="save*" propagation="REQUIRED" />
21             <tx:method name="update*" propagation="REQUIRED" />
22             <tx:method name="merge*" propagation="REQUIRED" />
23             <tx:method name="delete*" propagation="REQUIRED" />
24             <tx:method name="enable*" propagation="REQUIRED" />
25             <tx:method name="disable*" propagation="REQUIRED" />
26             <tx:method name="get*" propagation="REQUIRED" read-only="true" />
27             <tx:method name="count*" propagation="REQUIRED" read-only="true" />
28             <tx:method name="find*" propagation="REQUIRED" read-only="true" />
29             <tx:method name="list*" propagation="REQUIRED" read-only="true" />
30             <tx:method name="*" propagation="REQUIRED" read-only="true" />
31         </tx:attributes>
32     </tx:advice> 

其中,<tx:method>有多个属性,propagation="REQUIRED”表示该方法需要事务,read-only="true”指定该方法事务为只读。

声明完毕事务之后,就可以通过Spring的AOP技术将配置好的事务织入Service方法中去:

1     <aop:config>
2         <!-- 通过aop定义事务增强切面 -->
3         <aop:pointcut id="txPointcut" expression="execution(* com.infrastructure.project.base.service..*.*(..))" />
4         <!-- 引用事务增强 -->
5         <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
6     </aop:config>

如果使用注解配置声明式事务,即通过@Transactional对需要事务增强的Bean接口实现类或方法进行标注,则需要在Spring容器中配置基于注解的事务增强驱动:

1 <tx:annotation-driven transaction-manager="txManager"/>

然后即可在Service中使用@Transactional注解声明事务:

1 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
2 public class SpitterServiceImpl implements SpitterService{
3     ...
4     @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
5     public void addSpitter(Spitter spitter){
6         ...
7     }
8     ...
9 }

 4、将以上整合,典型的配置文件如下:

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:aop="http://www.springframework.org/schema/aop"
 4        xmlns:tx="http://www.springframework.org/schema/tx"
 5        xsi:schemaLocation="
 6   http://www.springframework.org/schema/beans
 7   http://www.springframework.org/schema/beans/spring-beans.xsd
 8   http://www.springframework.org/schema/tx
 9   http://www.springframework.org/schema/tx/spring-tx.xsd
10   http://www.springframework.org/schema/aop
11   http://www.springframework.org/schema/aop/spring-aop.xsd">
12 
13 <!-- 配置dataSource -->
14 <bean id="exampleDataSource" class="org.apache.commons.dbcp.BasicDataSource">
15     <property name="driverClassName" value="com.mysql.jdbc.Driver" />
16     <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=UTF-8" />
17     <property name="username" value="root" />
18     <property name="password" value="" />
19     <property name="initialSize" value="5" />
20     <property name="maxActive" value="10" />
21 </bean>
22 
23 <!-- 声明sessionFactory -->
24 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
25     <property name="dataSource" ref="dataSource"/>
26     <property name="mappingDirectoryLocations">
27         <list>
28             <value>classpath:com/demo/model/mappings</value>
29         </list>
30     </property>
31     <property name="hibernateProperties">
32         <props>
33             <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
34         </props>
35     </property>
36 </bean>
37 
38 <!-- 声明事务管理器开始 -->
39 <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
40     <property name="sessionFactory" ref="sessionFactory"/>
41 </bean>
42 
43 <!-- 声明事务 -->
44 <tx:advice id="txAdvice" transaction-manager="txManager">
45     <tx:attributes>
46         <tx:method name="save*" propagation="REQUIRED" />
47         <tx:method name="update*" propagation="REQUIRED" />
48         <tx:method name="merge*" propagation="REQUIRED" />
49         <tx:method name="delete*" propagation="REQUIRED" />
50         <tx:method name="enable*" propagation="REQUIRED" />
51         <tx:method name="disable*" propagation="REQUIRED" />
52         <tx:method name="get*" propagation="REQUIRED" read-only="true" />
53         <tx:method name="count*" propagation="REQUIRED" read-only="true" />
54         <tx:method name="find*" propagation="REQUIRED" read-only="true" />
55         <tx:method name="list*" propagation="REQUIRED" read-only="true" />
56         <tx:method name="*" propagation="REQUIRED" read-only="true" />
57     </tx:attributes>
58 </tx:advice>
59 
60 <!-- 织入事务 -->
61 <aop:config>
62     <aop:pointcut id="txPointcut" expression="execution(* com.infrastructure.project.base.service..*.*(..))" />
63     <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
64 </aop:config>

 

posted @ 2015-02-23 23:30  添哥  阅读(354)  评论(0编辑  收藏  举报