码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-11-20 00:08:20      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:rgs   rop   led   abc   name   date   基于   status   data   

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; 
     } 
}

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

标签:rgs   rop   led   abc   name   date   基于   status   data   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!