首页 > 代码库 > 编程式事务--使用PlatformTransactionManager接口实现事务

编程式事务--使用PlatformTransactionManager接口实现事务

软件152 彭梦月

在spring里事务管理有两种实现方式,一个是编程式事务,一个是声明式事务。先从编程式事务开始讲起。

1.java工程的目录结构:

技术分享

2.首先是applicationContext.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: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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

<!-- 扫描该路径下的spring组件 -->
<context:component-scan base-package="cn.com.sharpxiajun" />

<!-- 读取资源文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:conf/constants.properties</value>
</list>
</property>
</bean>

<!-- 配置数据源 -->
<!-- <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="http://www.mamicode.com/${db.driverClass}"/>
<property name="jdbcUrl" value="http://www.mamicode.com/${db.jdbcUrl}"/>
<property name="user" value="http://www.mamicode.com/${db.user}"/>
<property name="password" value="http://www.mamicode.com/${db.password}"/>
</bean>-->

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="http://www.mamicode.com/${db.driverClass}"/>
<property name="url" value="http://www.mamicode.com/${db.jdbcUrl}"/>
<property name="username" value="http://www.mamicode.com/${db.user}"/>
<property name="password" value="http://www.mamicode.com/${db.password}"/>
</bean>

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>classpath:conf/SqlMapConfig.xml</value>
</property>
<property name="dataSource" ref="myDataSource"/>
</bean>

<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="myDataSource"/>
</property>
</bean>

<!-- 将我自己定义的拦截器生成bean -->
<bean id="methodServiceAdvisor" class="cn.com.sharpxiajun.common.aop.MethodServiceAdvisor"/>

<aop:config>
<!--配置规则,满足以下规则的将拦截,第一个*表示所有返回类型,第二个表示service包下的所有class,第三个表示所有方法-->
<aop:pointcut id="baseServiceMethods" expression="execution(* cn.com.sharpxiajun.service.*.*(..))"/>
<!-- 符合上面规则的拦截器都会调用到methodServiceAdvisor -->
<aop:advisor advice-ref="methodServiceAdvisor" pointcut-ref="baseServiceMethods"/>
</aop:config>

</beans>配置文件里添加了<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">。。。事务管理的spring bean。
3.在cn.com.sharpxiajun.transactionstudy包下建接口SpringTransaction,代码如下:

技术分享

4.在包cn.com.sharpxiajun.transactionstudy.impl下实现SpringTransaction接口,代码如下:

package cn.com.sharpxiajun.transactionstudy.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import cn.com.sharpxiajun.transactionstudy.SpringTransaction;

@SuppressWarnings("unchecked")
@Scope("prototype")
@Service("springTransaction")
public class SpringTransactionImpl implements SpringTransaction {

private final static Log log = LogFactory.getLog(SpringTransactionImpl.class);

@Autowired
@Qualifier("myDataSource")
private BasicDataSource myDataSource = null;

@Autowired
@Qualifier("transactionManager")
private PlatformTransactionManager transactionManager = null;

public void transactionInsert()
{
DefaultTransactionDefinition dtd = new DefaultTransactionDefinition();
dtd.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus ts = transactionManager.getTransaction(dtd);
Connection conn = DataSourceUtils.getConnection(myDataSource);

try {
Statement stmt = conn.createStatement();
stmt.execute("insert into users values(‘sharpxiajun‘,‘sharpxiajun‘,true)");
stmt.execute("insert into users values(‘java‘,‘java‘,true)");
transactionManager.commit(ts);
log.info("事务成功完成!");
} catch (SQLException e) {
transactionManager.rollback(ts);
log.info("事务执行失败");
System.out.println("原因:" + e.getMessage());
}
}

}

5.在cn.com.sharpxiajun.junittest.transactionstudy包下建立测试类SpringTransactionImplTest,代码如下:
package cn.com.sharpxiajun.junittest.transactionstudy;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;

import cn.com.sharpxiajun.transactionstudy.SpringTransaction;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:conf/applicationContext.xml" })
@TransactionConfiguration(defaultRollback = false)
public class SpringTransactionImplTest extends
AbstractTransactionalJUnit4SpringContextTests {

@Autowired
private SpringTransaction springTransaction = null;

public SpringTransactionImplTest()
{
System.out.println("初始化测试类....");
}

@Before
public void setUp() throws Exception
{
System.out.println("测试开始....");
}

@After
public void tearDown() throws Exception
{
System.out.println("测试结束!!");
}

@Test
public void testTransactionInsert()
{
springTransaction.transactionInsert();
}

}

运行测试类,结果如下:
log4j: Parsing for [root] with value=http://www.mamicode.com/[INFO,CONSOLE,STDOUT].
log4j: Level token is [INFO].
log4j: Category root set to INFO
log4j: Parsing appender named "CONSOLE".
log4j: Parsing layout options for "CONSOLE".
log4j: Setting property [conversionPattern] to [%d{yyyy-MM-dd HH:mm:ss} %c{1} - %m%n].
log4j: End of parsing for "CONSOLE".
log4j: Parsed "CONSOLE" options.
log4j: Parsing appender named "STDOUT".
log4j:ERROR Could not find value for key log4j.appender.STDOUT
log4j: Parsing for [com.ibatis.common.jdbc.SimpleDataSource] with value=http://www.mamicode.com/[debug].
log4j: Level token is [debug].
log4j: Category com.ibatis.common.jdbc.SimpleDataSource set to DEBUG
log4j: Handling log4j.additivity.com.ibatis.common.jdbc.SimpleDataSource=[null]
log4j: Parsing for [java.sql.Connection] with value=http://www.mamicode.com/[DEBUG].
log4j: Level token is [DEBUG].
log4j: Category java.sql.Connection set to DEBUG
log4j: Handling log4j.additivity.java.sql.Connection=[null]
log4j: Parsing for [com.ibatis] with value=http://www.mamicode.com/[debug].
log4j: Level token is [debug].
log4j: Category com.ibatis set to DEBUG
log4j: Handling log4j.additivity.com.ibatis=[null]
log4j: Parsing for [java.sql.Statement] with value=http://www.mamicode.com/[DEBUG].
log4j: Level token is [DEBUG].
log4j: Category java.sql.Statement set to DEBUG
log4j: Handling log4j.additivity.java.sql.Statement=[null]
log4j: Parsing for [com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate] with value=http://www.mamicode.com/[debug].
log4j: Level token is [debug].
log4j: Category com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate set to DEBUG
log4j: Handling log4j.additivity.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=[null]
log4j: Parsing for [com.ibatis.common.jdbc.ScriptRunner] with value=http://www.mamicode.com/[debug].
log4j: Level token is [debug].
log4j: Category com.ibatis.common.jdbc.ScriptRunner set to DEBUG
log4j: Handling log4j.additivity.com.ibatis.common.jdbc.ScriptRunner=[null]
log4j: Parsing for [java.sql.PreparedStatement] with value=http://www.mamicode.com/[DEBUG].
log4j: Level token is [DEBUG].
log4j: Category java.sql.PreparedStatement set to DEBUG
log4j: Handling log4j.additivity.java.sql.PreparedStatement=[null]
log4j: Finished configuring.
log4j:ERROR Could not instantiate appender named "STDOUT".
初始化测试类....
2011-10-19 22:35:11 XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [conf/applicationContext.xml]
2011-10-19 22:35:11 GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@2bc3f5: startup date [Wed Oct 19 22:35:11 CST 2011]; root of context hierarchy
2011-10-19 22:35:11 PropertyPlaceholderConfigurer - Loading properties file from class path resource [conf/constants.properties]
2011-10-19 22:35:11 DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@19ba640: defining beans [usersDao,springTransaction,
userService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,
org.springframework.context.annotation.internalCommonAnnotationProcessor,propertyConfigurer,myDataSource,sqlMapClient,sqlMapClientTemplate,transactionManager,methodServiceAdvisor,org.springframework.aop.config.internalAutoProxyCreator,baseServiceMethods,
org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0]; root of factory hierarchy
2011-10-19 22:35:13 TransactionalTestExecutionListener - Began transaction (1): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@171194d]; rollback [false]
测试开始....
2011-10-19 22:35:13 SpringTransactionImpl - 事务成功完成!
测试结束!!
2011-10-19 22:35:13 TransactionalTestExecutionListener - Committed transaction after test execution for test context [[TestContext@1c5af2e testClass = SpringTransactionImplTest, locations = array<String>[‘classpath:conf/applicationContext.xml‘],
testInstance = cn.com.sharpxiajun.junittest.transactionstudy.SpringTransactionImplTest@1702c48, testMethod = testTransactionInsert@SpringTransactionImplTest, testException = [null]]]
2011-10-19 22:35:13 GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@2bc3f5: startup date [Wed Oct 19 22:35:11 CST 2011]; root of context hierarchy
2011-10-19 22:35:13 DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@19ba640: defining beans [usersDao,springTransaction,userService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,
org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,propertyConfigurer,myDataSource,sqlMapClient,sqlMapClientTemplate,transactionManager,methodServiceAdvisor,
org.springframework.aop.config.internalAutoProxyCreator,baseServiceMethods,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0]; root of factory hierarchy
数据库结果如下:

技术分享

 

操作成功了!!!

编程式事务--使用PlatformTransactionManager接口实现事务