Spring中的数据库操作事务

一、 Spring 中的事务

Spring 为什么提供对事务的支持?还记得我们在编写 OA 项目时,为了统一处理一类事务的多个 Dao 方法对数据库的操作是在一个事务中进行的,我们添加了一个“ *.do” 的过滤器,在过滤器中使用当前线程( ThreadLocal )的 Session 来处理事务。

 

其中我们也曾提到过将事务统一在过滤器中只是为解决一时之需,将事务统一放在 Service 的方法中才是优雅的做法。我们使用 Spring 就可以实现将事务统一放在 Service 的方法上。

 

1. Spring 中引入事务

通过外部 Bean 引入数据源我就不再做总结了,这里直接列出引入 Spring 中事务类的方法。下面为引入 Jdbc 的事务管理:

<bean name="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource" />

</bean>


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

tx” 元素指定使用注解进行事务处理的 Bean

 

引入 Hibernate 的事务管理:

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

</bean>


<bean id="transactionManager"

class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<property name="sessionFactory" ref="sessionFactory" />

</bean>


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

2. 使用 Spring 的事务

Service 方法上添加事务注解“ @Transactional ,此时的 Service 方法便具有了事务管理。这正是使用 AOP 的编程思想,在过滤器上添加事务统一管理,也正是 AOP 的思想。

 

事务的传播性,当一个具有 事务的方法调用另一个具有事务的方法时。此时可以设置事务的传播属性,实现不同的需求。事务的传播性有:

传播属性

描 述

REQUIRED

如 果有事务在运行,当前的方法就在这个事务内运行,否则启动一个新的事务,并在自己的事务内运行。

REQUIRED_NEW

当前的方法必须启动新的事务,并在它自己的事务内运行。如果有事务正在运行,则将它挂起。

SUPPORTS

如果有事务在运行,当前的 方法就在这个事务内运行。否则它可以不运行在事务中。

NOT_SUPPORTED

当前的方法 不运行在事务中。如果有运行的事务,将它挂起。

MANDATORY

当前的方法运行在事务内容,如果没有 正在运行的事务,则抛异常。

NEVER

当前的方法不应该运行在事 务中。如果有运行的事务,则抛异常。

NESTED

如果有事务在运行,当前的方法在这个事务的嵌套事务内运行。否则,启动一个新的事 务,并在它自己的事务内运行。

前两项是常用的。

 

Transactional 注解所具有的属性:

 

 

@Transactional(propagation=Propagation.REQUIRES_NEW, // 事务传播属性

isolation=Isolation.READ_COMMITTED,// 事务隔离级别

rollbackFor=Exception.class,// 异常回滚

unrollbackFor=IOException.class,// 异常不回滚

timeout=2, // 超时事务

readOnly=false)// 只读事务
 

 

 

属性

类型

描述

propagation

枚举型: Propagation

可选的传播性设置

isolation

枚举型: Isolation

可选的隔离性级别(默认值: ISOLATION_DEFAULT

readOnly

布尔型

读写型事务 vs. 只读型事务。只读型事务一般用于查询。

timeout

int 型(以秒为单位)

事务超时,如果在指定时间内没有完成 事务,事务则回滚。

rollbackFor

一组 Class 类的实例,必须是 Throwable 的子类

一组异常类,遇到时 必须 进行回滚。默认情况下 checked exceptions 不进行回滚,仅 unchecked exceptions (即 RuntimeException 的子类)才进行事务回滚。

rollbackForClassname

一组 Class 类的名字,必须是 Throwable 的子类

一组异常类名,遇到时 必须 进行回滚

noRollbackFor

一组 Class 类的实例,必须是 Throwable 的子类

一组异常类,遇到时 必须不 回滚。

noRollbackForClassname

一组 Class 类的名字,必须是 Throwable 的子类

一组异常类,遇到时 必须不 回滚

 

使用 XML 文件配置 Spring 事务:

<tx:advice id="testTransaction" transaction-manager="transactionManager">

<tx:attributes>

<tx:method name="methodName" propagation="REQUIRED"

read-only="false" rollback-for="Expetion" timeout="2" isolation="READ_COMMITTED" />

</tx:attributes>

</tx:advice>


<aop:config>

<aop:pointcut expression="execution(* cn.itcast.cc.spring.transaction.*.*(..))"

id="aopTransaction" />

<aop:advisor advice-ref="testTransaction" pointcut-ref="aopTransaction" />

</aop:config>
 

二、 Spring 整 合 Hibernate

Spring 支持大多数流行的 ORM 框架,包括 HibernateJDO TopLink Ibatis JPA 。它这些 ORM 框架的支持是一致的,因此可以把和 Hibernate 整合技术应用到其他 ORM 框架上。 Spring2.0 同时支持 Hibernate2.x 3.x 。但 Spring2.5 只支持 Hibernate3.1 或更高版本

 

1. Spring 中配置 SessionFactory

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

</bean>
 

其中的 DataSource 是我们在第一天就讲到的使用外部 Bean 配置数据源。

 

虽然我们使用的数据源是一个 Bean ,它涉及到 Hibernate 私有配置的信息被声明在“ hibernate.cfg.xml” 文件中。但现在我们可以这个外在的“ hibernate.cfg.xml” 文件,我们需要在上面的 baen 中添加:


<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

<prop key="hibernate.show_sql">true</prop>

<prop key="hibernate.hbm2ddl.auto">update</prop>

</props>

</property>

<property name="mappingResources">

<list>

<value>cn/itcast/spring/hibernate/Customer.hbm.xml</value>

</list>

</property>

</bean>
 

OK SessionFactory 已经被我们整合进来了!十分简单,跟其他的类一样。

 

还记得我们昨天使用的 JdbcTemplate 吗?那是 Spring JDBC 提供的支持, Spring 也有为 Hibernate 提供支持:

支持类

JDBC

Hibernate

模板类

JdbcTemplate

HibernateTemplate

DAO 支持类

JdbcDaoSupport

HibernateDaoSupport

事务管理类

DataSourceTransactionManager

HibernateTransactionManager

 

使用 HibernateTemplate ,需要声明一个 Bean

< bean id = "hibernateTemplate" class = "org.springframework.orm.hibernate3.HibernateTemplate" >

< property name = "sessionFactory" ref = "sessionFactory" />

</ bean >

 

 

DAO 支持类对我们来说比较陌生, HibernateDAO 可以通过继承 HibernateDaoSupport 来继承 setSessionFactory() setHibernateTemplate() 方法。然后,只要在 DAO 方法中调用 getHibernateTemplate() 方法就可以获取到模板实例。

 

三、 Spring 整 合 Struts1.x

 

1 . 通过注册 Servlet 监听器 ContextLoaderListener Web 应用程序可以加载 Spring ApplicationContext 对象。这个监听器会将加载好的 ApplicationContext 对象保存到 Web 应用程序的 ServletContext 中。随后, Servlet 或可以访问 ServletContext 的任意对象就能通过一个辅助方法来访问 Spring 的应用程序上下文了。

 

<context-param>

<param-name>contextConfigFile</param-name>

<param-value>beans.xml</param-value>

</context-param>

<listener>

<listener-class>cn.itcast.cc.spring.SpringServletContextListener</listener-class>

</listener>
 

SpringServletContextListener contextInitialized 方法中

public void contextInitialized(ServletContextEvent arg0) {

String cfgFile = arg0.getServletContext().getInitParameter("contextConfigFile");

ApplicationContext ac = new ClassPathXmlApplicationContext(cfgFile);

arg0.getServletContext().setAttribute("applicationContext", ac);

}
 

以后在 Action 中需要使用 SpringIOC 容器中的 Bean 时,就可以先到 ServletContext 中去获取 ApplicationContext ,然后再获取相应的 Bean

 

2 . web.xml 文件中注册 Spring 提供的 Servlet 监听器 ContextLoaderListener ,它会在当前 web 应用被加载时将 Spring ApplicationContext 保存到 ServletContext 对象中。

 

ContextLoaderListener 监听器通过查找 web 应用初始化参数 contextConfigLocation 来获取 Bean 配置文件的位置。如果有多个 Bean 配置文件,可以通过逗号或空格进行分隔。 contextConfigLocation 的默认值为 /WEB-INF/applicationContext.xml 。若实际的文件和默认值一致则可以省略这个 web 应用的初始化参数。

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:beans.xml</param-value>

</context-param>


<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>


 

在需要 Bean Action Servlet 中获取 Bean 的方法:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());

ac.getBean("beanName");

}
 

3 . 通过注册 Servlet 监听器 ContextLoaderListener Struts 应用程序能够加载 Spring ApplicationContext 对象,并像在通用的 Web 应用程序中那样在 Servlet 上下文中对它进行访问。然而, Spring 还提供了更好的,特定于 Struts 的解决方案。

  1. struts 配置文件中注册 Struts 插件来加载应用程序上下文,它会自动引用 Servlet 监听器加载的应用程序上下文作为它的父上下文,以便可以引用其中声明的 Bean

  2. <plug-in  className="org.springframework.web.struts.ContextLoaderPlugIn">
    
    <set-property property="contextConfigLocation"
    
    value="classpath:struts-config.xml,classpath:beans.xml" />
    
    </plug-in>
     
  3. Spring 提供了一个 ActionSupport 对象,这是 Action 类的一个子类,通过它的 getWebApplicationContext() 方法可以获取到 Spring 的应用程序上下文。

public  class LoginAction extends ActionSupport {


@Override

public ActionForward execute(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response)

throws Exception {

ApplicationContext ac = this.getWebApplicationContext();

HelloSpring hs = (HelloSpring) ac.getBean("helloSpring");

request.setAttribute("message", hs.hello("changcheng"));

return mapping.findForward("success");

}

}
 
  1. spring 的应用程序上下文中声明 Struts Action 对象,使用 Spring 的依赖注入来注入 Spring 应用程序上下文的其他 Bean

 

我们的 Action 类:

public  class LoginAction extends Action {

private HelloSpring helloSpring;

public void setHelloSpring(HelloSpring hs) {

this.helloSpring = hs;

System.out.println("*****注入*****:" + this.helloSpring);

}


@Override

public ActionForward execute(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response)

throws Exception {

request.setAttribute("message", this.helloSpring.hello("changcheng"));

return mapping.findForward("success");

}

}
 

struts-config.xml 中将的 Action 配置为:

<action-mappings>

<action path="/login">

<forward name="success" path="/success.jsp" />

</action>

</action-mappings>


<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor" />
 

beans.xml 中配置:

<bean  id="helloSpring"  class="cn.itcast.cc.spring.struts.hello.HelloSpring"  />

<bean name="/login" class="cn.itcast.cc.spring.struts.action.LoginAction">

<property name="helloSpring" ref="helloSpring"/>

</bean>
 

这种方法也需要“ 1)” plug-in

 

四、 SSH 整合( Spring Struts1.x Hibernate

将上面的二和三放到一起就是 SSH 整合,佟老师使用一个使用注册的例子演示 SSH 整合。我只简单说一下思想吧!

 

1). 创建动态 WEB 工程。

2). web.xml 添加 spring 的“ ContextLoaderListener 监听器和 Struts ActionServlet

3). Spring 的配置文件中引入数据源和 Hibernate SessionFactory HibernateTransactionManager

4). struts 添加 spring 的“ DelegatingRequestProcessor 制器。

5). Action Service Dao 添加 Spring AOP 注解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值