Spring 事务入门

Posted 囧雪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 事务入门相关的知识,希望对你有一定的参考价值。

定义:

一系列的动作,被当成一个单独的工作单元,要么都完成,要么全部不起作用(失败回滚)。

之前的事务处理:JDBC与Hibernate中的事务处理——与try...catch...finally...一起用。
Spring中的事务处理:编程式,声明式。
Spring从事务管理的API中抽象出一套独立事务机制。事务管理代码能独立于特点的具体技术。

 

使用方法:

建立beans.xml

 

准备工作:配置数据源对象。

<!-- 生成数据连接池 -->
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
    <property name="driverClass" value="${driverClass}"></property>
    <property name="jdbcUrl" value="${jdbcUrl}"></property>
    <property name="user" value="${user}"></property>
    <property name="password" value="${password}"></property>
    <property name="minPoolSize" value="${minPoolSize}"></property>
    <property name="maxPoolSize" value="${maxPoolSize}"></property>
    <property name="initialPoolSize" value="${initialPoolSize}"></property>
</bean>

<!-- 生成jdbcTemplate -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
</bean>

1.配置事务管理器。

DataSourceTransactionManager类
dataSource属性注入

<!-- 配置事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

2.在配置文件中启用事务注解 

把tx命名空间加进来。

 

<!-- 启动事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

 3.添加事务注解。在类中使用的方法上添加这个注解:@Transactional 

  @Transactional//事务注解    
    @Override
    public void delete(String code) {
        workDao.deleteByInfoCode(code);
        infoDao.delete(code);        
    }

 

下面看一个实例:

准备工作:导入c3p0、Spring框架、mysql的jar包,并配置好

db.properties

 

driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/mydb
user=root
password=
minPoolSize=5
maxPoolSize=20
initialPoolSize=5

 

beans.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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

<!--加载数据库配置文件 db.properties-->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 生成连接池 -->
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
    <property name="driverClass" value="${driverClass}"></property>
    <property name="jdbcUrl" value="${jdbcUrl}"></property>
    <property name="user" value="${user}"></property>
    <property name="password" value="${password}"></property>
    <property name="minPoolSize" value="${minPoolSize}"></property>
    <property name="maxPoolSize" value="${maxPoolSize}"></property>
    <property name="initialPoolSize" value="${initialPoolSize}"></property>
</bean>

<!-- 生成jdbcTemplate -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
</bean>

</beans>

 

 

1.做两个接口IInfoDao和IWorkDao

package maya.dao;

public interface IInfoDao {
    public void delete(String code);
}
package maya.dao;

public interface IWorkDao {
    public void deleteByInfoCode(String code);
}

2.做两个类继承以上两个接口:InfoDao和WorkDao

package maya.daolmpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import maya.dao.IInfoDao;
@Repository
public class InfoDao implements IInfoDao {
   
  @Autowired
//自动装配beans.xml中的jdbcTemplate private JdbcTemplate jdbcTemplate;
  @Override
public void delete(String code) { String sql = "delete from info where code=?"; jdbcTemplate.update(sql,code); //故意写一个错误代码 int n = 5/0; } }
package maya.daolmpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import maya.dao.IWorkDao;
@Repository
public class WorkDao implements IWorkDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void deleteByInfoCode(String code) {
        String sql = "delete from work where infoCode=?";
        jdbcTemplate.update(sql,code);        
    }

}

3.向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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

<!--扫描以下包里的类,以备使用--> <context:component-scan base-package="maya.daolmpl,maya.servicelmpl"></context:component-scan> <context:property-placeholder location="classpath:db.properties"/> <!-- 生成连接池 --> <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource"> <property name="driverClass" value="${driverClass}"></property> <property name="jdbcUrl" value="${jdbcUrl}"></property> <property name="user" value="${user}"></property> <property name="password" value="${password}"></property> <property name="minPoolSize" value="${minPoolSize}"></property> <property name="maxPoolSize" value="${maxPoolSize}"></property> <property name="initialPoolSize" value="${initialPoolSize}"></property> </bean> <!-- 生成jdbcTemplate --> <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事务管理器 --> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 启动事务注解 --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>

4.建立业务接口并用类继承

IInfoService接口

package maya.service;

public interface IInfoService {
    public void delete(String code);
}

InfoService类

package maya.servicelmpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import maya.dao.IInfoDao;
import maya.dao.IWorkDao;
import maya.daolmpl.WorkDao;
import maya.service.IInfoService;
@Service
public class InfoService implements IInfoService {
    @Autowired
    private IWorkDao workDao;
    @Autowired
    private IInfoDao infoDao;
    
    @Transactional//为以下方法添加事务注解    
    @Override
    public void delete(String code) {
        workDao.deleteByInfoCode(code);
        infoDao.delete(code);        
    }
}

5.创建测试类并运行

package maya.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import maya.dao.IInfoDao;
import maya.dao.IWorkDao;
import maya.service.IInfoService;

public class Test {
    private static ApplicationContext context = null;
    private static IInfoDao infoDao = null;
    private static IWorkDao workDao = null;
    private static IInfoService infoService = null;

    static {
        context = new ClassPathXmlApplicationContext("beans.xml");
        infoDao = (IInfoDao)context.getBean("infoDao");
        workDao = (IWorkDao)context.getBean("workDao");
        infoService = (IInfoService)context.getBean("infoService");        
    }    
    
    public static void main(String[] args) {
        infoService.delete("a004");
    }
}

结果(报错,由于除数为0):

Exception in thread "main" java.lang.ArithmeticException: / by zero

查看数据库表,并未删除成功

 

把事务取消掉,比如删除事务注解

package maya.servicelmpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import maya.dao.IInfoDao;
import maya.dao.IWorkDao;
import maya.daolmpl.WorkDao;
import maya.service.IInfoService;
@Service
public class InfoService implements IInfoService {
    @Autowired
    private IWorkDao workDao;
    @Autowired
    private IInfoDao infoDao;
    
    //@Transactional,事务注解注销掉
    @Override
    public void delete(String code) {
        workDao.deleteByInfoCode(code);
        infoDao.delete(code);        
    }
}

再次运行查看结果:依然报错

Exception in thread "main" java.lang.ArithmeticException: / by zero

查看数据库,“a004”已被删除

 

以上是关于Spring 事务入门的主要内容,如果未能解决你的问题,请参考以下文章

Spring 事务入门

深入理解 Spring 事务:入门使用原理

(入门SpringBoot)SpringBoot项目事务

Spring 从入门到精通系列 09——转账方法的事务问题与动态代理

Spring事务管理的另一种方式--TransactionTemplate编程式事务管理简单入门

Spring针对事务处理提供哪两种事务编程模式。