Spring事务管理

一、解数据库事务

理解数据库事务

二、全面分析 Spring 的编程式事务管理及声明式事务管理

添全面分析 Spring 的编程式事务管理及声明式事务管理

三、Spring事务管理自我理解的补充

1. 编程式事务管理
  • 模板事务(TransactionTemplate)案例–步骤:获取模板对象;选择事务结果类型;业务数据操作处理。
  • 平台事务管理器(PlatformTransactionManager)案例–步骤:获取事务管理器;获取事务属性对象;获取事务状态对象;创建JDBC模板对象;业务数据操作处理。

工具类TemplateUtils:

package com.mooc.utils;

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * Spring数据库操作工具类
 */
public class TemplateUtils {
	private final static  String dbDriver = "com.mysql.jdbc.Driver" ;
	private final static  String dbUrl = "jdbc:mysql://127.0.0.1:3306/mytest?useSSL=false" ;
	private final static  String dbUser = "root";
	private final static  String dbPwd = "wenang++";
	
	private static BasicDataSource dataSource ;
	//静态初识:创建连接数据源
	static {
	//创建DBCP简单数据源并初始化相关数据源属性
	//private void createSimpleDataSource(){
		dataSource = new  BasicDataSource() ;
		dataSource.setDriverClassName(dbDriver);
		dataSource.setUrl(dbUrl);
		dataSource.setUsername(dbUser);
		dataSource.setPassword(dbPwd);
		//指定数据库连接池初始连接数
		dataSource.setInitialSize(10);
		//设定同时向数据库申请的最大连接数
		dataSource.setMaxTotal(50);
		//设置连接池中保持的最少连接数量
		dataSource.setMinIdle(5);
	//}
	}
	public static TransactionTemplate getTransactionTemplate() {  
        PlatformTransactionManager txManager = new DataSourceTransactionManager(  
                dataSource);  
        return new TransactionTemplate(txManager);  
    }  
  
    public static JdbcTemplate getJdbcTemplate() {  
        return new JdbcTemplate(dataSource);  
    }  
  
    public static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {  
        return new NamedParameterJdbcTemplate(dataSource);  
    }  
  
    public static SimpleJdbcInsert getSimpleJdbcTemplate() {  
        return new SimpleJdbcInsert(dataSource);  
    }  
    
    /**
     * //获取事务管理器:TransactionManager
     * 根据需要,可以是如JDBC、Hibernate,这里定义JDBC事务管理其
     * @return DataSourceTransactionManager
     */
    public static DataSourceTransactionManager getDataSourceTransactionManager(){
    	 DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
    	 // 设置数据源:此事务数据源须和正式事务管理器的数据源一致
    	 dataSourceTransactionManager.setDataSource(dataSource);
    	 return dataSourceTransactionManager;
    }
}

模板事务(TransactionTemplate)案例:

package com.mooc.springtransactions;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.mooc.utils.TemplateUtils;

public class TransManagerExample {

	public static void main(String[] args) {
		DataSourceTransactionManager dtm = TemplateUtils.getDataSourceTransactionManager();
		// 创建事务管理器属性对象
		DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // 定义事务属性
		// 根据需要,设置事务管理器的相关属性
		transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // 设置传播行为属性
		// 获得事务状态对象
		TransactionStatus ts = dtm.getTransaction(transDef); 
		//基于当前事务管理器,获取操作数据库的JDBC模板对象
		JdbcTemplate jt = new JdbcTemplate(  dtm.getDataSource());  
	try{
		jt.update("update books set price=112.5,name='炎黄传奇222'  where isbn='128-166-890-China' ");
		//其它数据操作如增删
		dtm.commit(ts); //如果不commit,则更新无效果
	} catch (Exception e) {
        dtm.rollback(ts);  
        e.printStackTrace();  
    } 
		
	}

}

平台事务管理器(PlatformTransactionManager)案例:

// 1、编程式事务管理:事务管理器PlatformTransactionManager方式实现
	public void updateBookByIsbn(Book book) {
		//第一步:获取JDBC事务管理器
		DataSourceTransactionManager dtm = TemplateUtils.getDataSourceTransactionManager();
		// 第二步:创建事务管理器属性对象
		DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // 定义事务属性
		// 根据需要,设置事务管理器的相关属性
		// 设置传播行为属性
		transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
		// 第三步:获得事务状态对象
		TransactionStatus ts = dtm.getTransaction(transDef);
		// 第四步:基于当前事务管理器,获取数据源,创建操作数据库的JDBC模板对象
		JdbcTemplate jt = new JdbcTemplate(dtm.getDataSource());
		try {//第五步:业务操作
			jt.update("update books set price="+book.getPrice()+",name='"+book.getName()
			              +"'  where isbn='"+book.getIsbn()+"' ");
			// 其它数据操作如增删
			//第六步:提交事务
			dtm.commit(ts); // 如果不commit,则更新无效果
		} catch (Exception e) {
			dtm.rollback(ts);
			e.printStackTrace();
		}
	}
2. 声明式事务管理

两种方式:tx拦截器;全注释(注解方式)。

POJO服务类:BookServiceImpl:

package com.mooc.service;

import com.mooc.beans.Book;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.transaction.annotation.Transactional;


import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * POJO服务类
 */
//使用全注释就使用@Transactional()
@Transactional()
public class BookServiceImpl extends JdbcDaoSupport implements BookService {

    //r若不继承JdbcDaoSupport,则可按下面方式进行数据源的注入
    private JdbcTemplate jdbcTemplate;
//    public void setDataSource(DataSource dataSource) {
//        this.jdbcTemplate = new JdbcTemplate((javax.sql.DataSource) dataSource);
//    }
    @Override
    public void insertBook(Book book) {
            String sql= "insert books(isbn,name,price,pubdate) values"
                    +"('"+book.getIsbn()+"','"+book.getName()+"',"+book.getPrice()+",'"+book.getPubdate()+"')" ;
        this.getJdbcTemplate().update(sql);
    }

    @Override
    public void updateBook(Book book) {
        String sql = "update books set name='"+book.getName()+"' where isbn='"+book.getIsbn()+"' ";
        this.getJdbcTemplate().update(sql);
    }

    @Override
    public Book findBookByIsbn(String isbn) {
        String sql =   "select isbn,name,price,pubdate from books where isbn ='" + isbn + "'" ;
       List<Book> books =  this.getJdbcTemplate().query(sql,new RowMapper<Book>() {
            public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
                Book bk  = new Book();
                bk.setIsbn(rs.getString("isbn"));
                bk.setName(rs.getString("name"));
                bk.setPrice(rs.getFloat("price"));
                bk.setPubdate(rs.getDate("pubdate"));
                return bk;
            }
        });
        return books!=null?books.get(0):null ;
    }
}
  • 继承JdbcDaoSupport 就需要再springContext.xml中配置dataSource(dataSource的配置暂且省略,下方会粘全代码):
<bean id="bookService" class="com.mooc.service.BookServiceImpl">
        <property name="dataSource" ref="dataSource"/>
</bean>
  • 若是采用全注释的方法就需要使用@Transactional(),并需要在springContext.xml声明。
<!-- 2、注释模式事务:启动使用注解实现声明式事务管理的支持   -->
    <tx:annotation-driven transaction-manager="txManager" />
    <!-- 要创建的事务服务对象 -->
    <bean id="bookService" class="com.mooc.service.BookServiceImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>
  • 若是采用tx拦截器
<!-- 1、通过事务通知的(AOP)模式实现事务管理
    事务通知-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!--事务语义定义... -->
        <tx:attributes>
            <!-- 以get开头的所有方法都为只读事务 -->
            <tx:method name="find*"  read-only="true"/>
            <!-- 其它方法使用默认事务设置 -->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
    <!-- 确保上述事务通知对定义在BookService接口中的方法都起作用,
           即对每个方法都开启一个对应的事务 -->
    <aop:config>
        <aop:pointcut id="bookServiceOperation" expression="execution(* com.mooc.service.BookService.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="bookServiceOperation"/>
    </aop:config>

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

    <!-- 引入数据库连接属性配置文件 -->
    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:database.properties" />
    </bean>
	<!-- 配置数据源 -->  
	<!-- #DBCP数据库连接池配置属性详细内容可参考官网描述:
       #http://commons.apache.org/proper/commons-dbcp/configuration.html 
       -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${driver}" />
        <property name="url" value="${url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="${initialSize}"></property>
        <!-- 连接池最大空闲 -->
        <property name="maxIdle" value="${maxIdle}"></property>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="${minIdle}"></property>
    </bean>



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

    <!-- 2、注释模式事务:启动使用注解实现声明式事务管理的支持   -->
    <tx:annotation-driven transaction-manager="txManager" />
    <!-- 要创建的事务服务对象 -->
    <bean id="bookService" class="com.mooc.service.BookServiceImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 1、通过事务通知的(AOP)模式实现事务管理
    事务通知-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!--事务语义定义... -->
        <tx:attributes>
            <!-- 以get开头的所有方法都为只读事务 -->
            <tx:method name="find*"  read-only="true"/>
            <!-- 其它方法使用默认事务设置 -->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
    <!-- 确保上述事务通知对定义在BookService接口中的方法都起作用,
           即对每个方法都开启一个对应的事务 -->
    <aop:config>
        <aop:pointcut id="bookServiceOperation" expression="execution(* com.mooc.service.BookService.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="bookServiceOperation"/>
    </aop:config>


</beans>  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值