Spring的数据访问---------------事务管理

ThreadLocal

  ThreadLocal为每一个使用该变量的线程分配一个变量副本,所以每一个线程在改变自己的副本时,不会改变其他线程的副本信息。该类主要包含四个方法:

  public void set(Object obj)

  public Object get()

  public void remove()

  protected Object InitialValue()

package thread;

public class ThreadLocalTest {
	private static final ThreadLocal<Integer> local = ThreadLocal.withInitial(()->0);
	public static void main(String[] args) throws InterruptedException {
	        for(int i = 0; i < 10;i++){
	            new MyThread(i).start();
	        }
	    }
	static class MyThread extends Thread{
		private int end;
		public MyThread(int end) {
			this.end = end;
			}
		@Override
		public void run() {
			System.out.println(Thread.currentThread().getName() + " start, local = " + local.get());
			for(int i = 0; i <= end;i++){
				local.set(local.get() + i); //计算(end+1)*end/2的值
				}
			System.out.println(Thread.currentThread().getName() + " end, local = " + local.get());
			}
		}
}

JDBC对事务的支持

  JDBC在进行数据库连接时,可以通过DataSource连接数据库,并将PreparedStatement预处理关闭,并将数据库连接关闭。实例如下: 

package com.kingdee.opensys.common.base.imp;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.support.JdbcUtils;

public class CommonDao {
private IPage page;
public IPage getPage() {
	return page;
}
public void setPage(IPage page) {
	this.page = page;
}

//创建数据库连接池
private  static ConnectionProvider connectionProvider;
//创建线程池
private static ThreadLocal<Connection> conWrapper = new ThreadLocal<Connection>();
//打开连接
private static Connection getConnection() throws SQLException{
	Connection con = connectionProvider.getConnection();
	if(con != null || !con.isClosed()){
		return con;
	}
	//从线程池中获取数据库连接
	con = connectionProvider.getConnection();
	if(con == null){
		throw new SQLException("??????????????");
	}
	//对新创建的数据库连接放到线程池中
	conWrapper.set(con);
	return con;
}
//关闭连接
public static void closeConnection() throws SQLException{
	//从线程池中获取连接池
	Connection con = conWrapper.get();
	if(con != null){
		con.close();
	}
	conWrapper.remove();
}
//关闭ResultSet和Statement
private void cleanup(ResultSet resultSet,PreparedStatement pre){
	if(resultSet != null){
		try {
			resultSet.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	if(pre != null){
		try {
			pre.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
/**
 * 关闭PreparedStatement
 * @param pre
 */
private void cleanup(PreparedStatement pre){
	if(pre != null){
		try {
			pre.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
}

Spring对事务管理的支持

  事务管理关键抽象

    TransactionDefinition:主要用来定义事务的属性,例如:事务隔离级别、超时时间、是否为只读事务等。

    PlatformTransactionManager:根据事务指定的属性,创建事务。

    TransactionStatus:事务状态。

  事务管理器实现类

    Spring在不同的框架实现了事务管理器接口PlatformTransactionManager,其中Spring为基于DataSource数据源的持久化技术例如SpringJDBC和iBats的事务管理器类为DataSourceTransactionManager。

    基于DataSource数据源的事务管理器  

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
	<property name="driverClassName">
		<value>oracle.jdbc.driver.OracleDriver</value>
    </property>
    <property name="url">
        <value>jdbc:oracle:thin:@localhost:1521:orcl</value>
    </property>
    <property name="username">
        <value>test</value>
    </property>
    <property name="password">
        <value>test</value>
    </property>
    <property name="maxActive">
        <value>255</value>
    </property>
    <property name="maxIdle">
        <value>2</value>
    </property>
    <property name="maxWait">
        <value>120000</value>
    </property>
</bean>
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="datasource" ref="dataSource"/>
</bean>

  DataSourceTransactionManager使用DataSource的Connect的commit()和rollBack()等方法管理事务。

  事务同步管理器

    在访问数据库时建立的连接或者会话统称为资源,该资源在同一时间无法实现多线程共享,Spring的事务同步管理器TransactionSynchronizationManager通过ThreadLocal为不同的事务线程提供独立的资源副本。无论声明式事务还是编程式事务都需要事务同步管理器。

编程式事务管理

  Spring为编程式事务管理提供模板类TransactionTemplate,可以在多个业务类中共享TransactionTemplate实例进行事务管理。由于Spring事务管理是基于TransactionSynchronizationManager进行工作的,所以如果在回调接口方法显示访问底层数据连接,必须通过资源工具类得到线程绑定的数据连接。

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!-- Connection Info -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- Connection Pooling Info -->
        <property name="maxActive" value="3"/>
        <property name="defaultAutoCommit" value="false"/>
        <!-- 连接Idle一个小时后超时 -->
        <property name="timeBetweenEvictionRunsMillis" value="3600000"/>
        <property name="minEvictableIdleTimeMillis" value="3600000"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

  PlatformTransactionManager编程式事务管理的实例:

public void testPlatformTransactionManager() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = txManager.getTransaction(def);
        Connection connection = DataSourceUtils.getConnection(dataSource);
        try{
              connection.prepareStatement(CREATE_TABLE_SQL).execute();
              PreparedStatement pstmt = connection.prepareStatement(INSERT_SQL);
              pstmt.setString(1, "test");
              pstmt.execute();
              connection.prepareStatement(DROP_TABLE_SQL).execute();
              txManager.commit(status);
        }catch(Exception ex){
            status.setRollbackOnly();
            txManager.rollback(status);
        }finally{
            DataSourceUtils.releaseConnection(connection, dataSource);
        }
    }

  TransactionTemplate编程式事务管理的实例:

  创建TransactionTemplate类

public class TransactionTemplateUtils {
    private static TransactionTemplate getTransactionTemplate(
            PlatformTransactionManager txManager, int propagationBehavior,
            int isolationLevel) {
        TransactionTemplate transactionTemplate = new TransactionTemplate(txManager);
        transactionTemplate.setPropagationBehavior(propagationBehavior);
        transactionTemplate.setIsolationLevel(isolationLevel);
        return transactionTemplate;
    }
    public static TransactionTemplate getDefaultTransactionTemplate(PlatformTransactionManager txManager) {
        return getTransactionTemplate(txManager,
                TransactionDefinition.PROPAGATION_REQUIRED,
                TransactionDefinition.ISOLATION_READ_COMMITTED);
    }
}

  通过TransactionTemplate类设置事务管理

public void save(final User user){
        TransactionTemplate transactionTemplate = TransactionTemplateUtils.getDefaultTransactionTemplate(txManager);
        transactionTemplate.execute(new TransactionCallbackWithoutResult(){
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus arg0) {
                userDao.save(user);
                user.getAddress().setUserId(user.getId());
                try {
                    addressService.save(user.getAddress());
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }

XML配置声明式事务管理

  Spring的声明式事务管理是通过SpringAOP实现的,Spring负责将事务管理器增强逻辑织入到业务方法连接点。

  声明式事务管理的过程:

    1、创建目标类。

    2、在xml中配置数据源。

    3、声明事务管理器。

    4、使用事务代理工厂类目标业务类织入增强。

  实例:

<!-- 配置JDBC数据源的局部事务管理器,使用DataSourceTransactionManager类,该类实现了PlatformTransactionManager接口,是针对采用数据源连接的特定实现 -->
<bean id="transactionManager"   class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 配置TransactionManager时需要注入数据源引用 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 下面这个是前面定义的业务Bean -->
<bean id="newsDao" class="com.abc.dao.impl.NewsDaoImpl">
<!-- 为业务Bean注入属性 -->
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="newsDaoTransProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 为事务代理工厂Bean注入事务管理器 -->
<property name="transactionManager" ref="transactionManager" />
<!-- 要在哪个Bean上面创建事务代理对象 -->
<property name="target" ref="newsDao" />
<!-- 指定事务属性 -->
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

  业务逻辑中使用事务

package com.abc.dao.impl;
public class NewsDaoImpl implements NewsDao {
    private DataSource dataSource;
    public void setDataSource(DataSrouce dataSource) {
        this.dataSource = dataSource;
    }
    public void insert(String title, String content) {
        JdbcTemplate template = new JdbcTemplate(dataSource);
        template.update("insert into news_table values (....)");
        //两次相同的操作,将违反主键约束
        template.update("insert into news_table values (....)");
    }
}

注解配置声明式事务管理

  注解事务管理器的过程

    1、在目标类注解事务@Transaction。

    2、在xml中配置数据源。

    3、配置事务管理器。

    4、通过<tx:annotation-driven>织入标注@Transaction注解的Bean进行加工处理事务管理器切面。

  @Transaction属性

    ioslation:事务隔离级别

    readOnly:事务读写属性

    timeOut:超时属性

    rollbackFor:遇到一组异常,需要回滚。

  @Transaction标注位置

   @Transaction可以标注在类上或者方法上,如果只标注在类上表示整个类中的方法都会使用该事务。如果只标注在方法上表示该事务只对单独的方法起作用。如果在类上或者方法上都存在事务,方法上的事务会覆盖类上的事务。

  使用不同事务管理器

    在同一个类中不同的方法上会标注不同的事务管理器,不同的事务管理器所嵌入的数据源不同。

  实例:

<!-- PlatformTransactionMnager1-->
<bean id="txManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource1" /><qualifier value="transaction1"/>
</bean>
<!-- enable transaction annotation support -->
<tx:annotation-driven transaction-manager="txManager1" />
<!-- PlatformTransactionMnager2 -->
<bean id="txManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource2" /><qualifier value="transaction2"/>
</bean>
<!-- enable transaction annotation support -->
<tx:annotation-driven transaction-manager="txManager2" />

  对业务处理进行事务注解 

@Transactional (value="transaction1")
public class TestServiceBean implements TestService {
     private TestDao dao;
     public void setDao(TestDao dao) {
         this.dao = dao;
}
@Transactional(value="transaction2",propagation =Propagation.NOT_SUPPORTED)
public List getAll() {
      return null;
     }
}

原文地址:https://www.cnblogs.com/youzhongmin/p/9865664.html

时间: 2024-10-08 23:00:52

Spring的数据访问---------------事务管理的相关文章

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

开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本教程假定您已经掌握了 Java 基础知识,并对 Spring 有一定了解.您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等.本文将直接使用这些概念而不做详细解释.另外,您最好掌握数据库的基础知识,虽然这不是必须. 系统需求 要试验这份教程中的工具和示例,硬件配置需求为:至少带

分析 Spring 的编程式事务管理及声明式事务管理(转)

开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本教程假定您已经掌握了 Java 基础知识,并对 Spring 有一定了解.您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等.本文将直接使用这些概念而不做详细解释.另外,您最好掌握数据库的基础知识,虽然这不是必须. 系统需求 要试验这份教程中的工具和示例,硬件配置需求为:至少带

Spring 的编程式事务管理及声明式事务管理

本文将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. Spring 事务属性分析 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保

Spring整合hibernate4:事务管理

Spring和Hibernate整合后,通过Hibernate API进行数据库操作时发现每次都要opensession,close,beginTransaction,commit,这些都是重复的工作,我们可以把事务管理部分交给spring框架完成. 配置事务(xml方式) 使用spring管理事务后在dao中不再需要调用beginTransaction和commit,也不需要调用session.close(),使用API  sessionFactory.getCurrentSession()来

Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis

项目进行读写分离及分库分表,在一个业务中,在一个事务中处理时候将切换多个数据源,需要保证同一事务多个数据源数据的一致性.此处使用atomikos来实现:最后附源码: 1:spring3.0之后不再支持jtom[jta]了,第三方开源软件atomikos(http://www.atomikos.com/)来实现. 2:org.springframework.transaction.jta.JotmFactoryBean类,spring-tx-2.5.6.jar中有此类,spring-tx-3.0.

Spring 注解方式实现 事务管理

使用步骤: 步骤一.在spring配置文件中引入<tx:>命名空间<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation

spring的annotation-driven配置事务管理器详解

http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html 好吧,这个作者也是转载的 ———————————————————————————————————————————————————————————————————————————————————— 这篇文章是我从ITeye上复制来的,看了一遍,觉得很深刻,决定把他复制来,对原作者表示感谢. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Spring04-SpringEL&amp;Spring JDBC数据访问

一. SpringEL入门 Spring动态语言(简称SpEL) 是一个支持运行时查询和操作对象图的强大的动态语言,语法类似于EL表达式,具有诸如显示方法和基本字符串模板函数等特性. 1. 准备工作 项目:spring-el 2. 需要导入jar包 spring-expression.jar maven项目pom文件添加: 1 <dependency> 2 <groupId>org.springframework</groupId> 3 <artifactId&g

[JavaEE - JPA] 3. Spring Framework中的事务管理

前文讨论了事务划分(Transaction Demarcation)在EJB中是如何实现的,本文继续介绍在Spring Framework中是如何完成事务划分的. 我们已经知道了当采用Container事务类型的时候,事务划分主要有以下两种方案(参考这里): 使用JTA接口在应用中编码完成显式划分 在容器的帮助下完成自动划分 在使用JavaEE的EJB规范时,这两种方案分别被实现为BMT以及CMT,关于BMT和CMT在上一篇文章中有比较详尽的讨论(参考这里). 那么对于Spring Framew