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