我正在使用以下测试用例测试我的声明事务配置:
我尝试将2条记录插入到包含4列(id,内容,位置,时间)的表中,而position是一个UNIQUE索引。我使用带有innoDB引擎的mysql 5.5,并使用Spring 3.2.2,Mybatis 3.2.2,Mybatis-Spring 1.2.0开发测试。下面是用于创建插入实验数据的数据库和表的SQL。
CREATE DATABASE `development` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `development`;
CREATE TABLE IF NOT EXISTS `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`content` varchar(256) DEFAULT NULL,
`position` int(10) unsigned NOT NULL,
`time` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `position` (`position`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=97 ;
INSERT INTO `test` (`id`, `content`, `position`, `time`) VALUES (1, 'test', 0, 1368164281),(2, '测试内容', 1, 1368164364),(44, 'bbb', 2, 1368431459),(45, 'ccc', 3, 1368431459),
这是配置xml service.xml:
<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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="testDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClassName" value="${test.driverClass}" />
<property name="url" value="${test.jdbcUrl}" />
<property name="username" value="${test.user}" />
<property name="password" value="${test.password}" />
<property name="minPoolSize" value="${test.miniPoolSize}" />
<property name="maxPoolSize" value="${test.maxPoolSize}" />
<property name="initialPoolSize" value="${test.initialPoolSize}" />
<property name="maxIdleTime" value="${test.maxIdleTime}" />
<property name="acquireIncrement" value="${test.acquireIncrement}" />
<property name="acquireRetryAttempts" value="${test.acquireRetryAttempts}" />
<property name="acquireRetryDelay" value="${test.acquireRetryDelay}" />
<property name="testConnectionOnCheckin" value="${test.testConnectionOnCheckin}" />
<property name="automaticTestTable" value="${test.automaticTestTable}" />
<property name="idleConnectionTestPeriod" value="${test.idleConnectionTestPeriod}" />
<property name="checkoutTimeout" value="${test.checkoutTimeout}" />
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="testDataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="add*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="testServiceOperation" expression="execution(* com.ssports.test.service.TestServiceImpl.addRecords(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="testServiceOperation" />
</aop:config>
<bean id="TestService" class="com.ssports.test.service.TestServiceImpl" />
</beans>
下面是test-mapper-config.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:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd">
<bean id="recordMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="testSqlSessionFactory" />
<property name="mapperInterface" value="com.ssports.test.mapper.RecordMapper" />
</bean>
</beans>
这是serviceImpl类:
package com.ssports.test.service;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.ssports.test.mapper.RecordMapper;
import com.ssports.test.model.Record;
import com.ssports.test.model.RecordExample;
import com.ssports.util.SpringHelper;
public class TestServiceImpl implements TestService {
Logger logger = LoggerFactory.getLogger(TestServiceImpl.class);
private static RecordMapper mapper = SpringHelper.getBean("recordMapper");
public List<Record> getAll() {
return mapper.selectByExample(new RecordExample());
}
public Record getRecordbyId(int id) {
return mapper.selectByPrimaryKey(id);
}
public void addRecords(List<Record> recordList) throws Exception {
for (Record record : recordList) {
logger.info(record.getPosition() + ":" + record.getTime());
mapper.insert(record);
}
}
}
测试代码是: 包com.ssports.db;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.ssports.test.model.Record;
import com.ssports.test.service.TestService;
import com.ssports.util.SpringHelper;
public class TransTest {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger(TransTest.class);
TestService service = SpringHelper.getBean("TestService");
List<Record> records = new ArrayList<Record>();
Record record1 = service.getRecordbyId(1);
Record record4 = new Record();
record4.setContent("ddd");
record4.setPosition(4);
record4.setTime((int) (new Long(System.currentTimeMillis()) / 1000));
records.add(record4);
records.add(record1);
DataSourceTransactionManager txManager = SpringHelper.getBean("txManager");
try {
service.addRecords(records);
} catch (UnsupportedOperationException ex) {
logger.info(ex.getMessage());
}
List<Record> recordlist = service.getAll();
for (Record item : recordlist) {
logger.info(item.getId() + ":" + item.getContent() + ":"
+ new Date((long) item.getTime() * 1000) + ":"
+ item.getPosition());
}
}
}
我运行应用程序,这是日志:
DEBUG: org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource - Adding transactional method [get*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly]
DEBUG: org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource - Adding transactional method [add*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT]
DEBUG: org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource - Adding transactional method [get*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly]
DEBUG: org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource - Adding transactional method [add*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT]
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [com.ssports.test.service.TestServiceImpl.addRecords]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@6650af3b] for JDBC transaction
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@6650af3b] to manual commit
INFO : com.ssports.test.service.TestServiceImpl - 4:1368602606
INFO : com.ssports.test.service.TestServiceImpl - 0:1368164281
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@6650af3b]
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [org.apache.commons.dbcp.PoolableConnection@6650af3b] after transaction
INFO : com.ssports.db.TransTest -
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
### The error may involve com.ssports.test.mapper.RecordMapper.insert-Inline
### The error occurred while setting parameters
### SQL: insert into test (id, content, position, time) values (?, ?, ?, ?)
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
; SQL []; Duplicate entry '1' for key 'PRIMARY'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
INFO : com.ssports.db.TransTest - 1:test:Fri May 10 13:38:01 CST 2013:0
INFO : com.ssports.db.TransTest - 2:测试内容:Fri May 10 13:39:24 CST 2013:1
INFO : com.ssports.db.TransTest - 44:bbb:Mon May 13 15:50:59 CST 2013:2
INFO : com.ssports.db.TransTest - 45:ccc:Mon May 13 15:50:59 CST 2013:3
INFO : com.ssports.db.TransTest - 98:ddd:Wed May 15 15:23:26 CST 2013:4
你可以看到,当异常抛出时,事务管理器会回滚数据库,但仍然会在其中插入一条记录。
有没有人能说出这里有什么问题,或者这是一个错误?
更新
我尝试使用下面的代码进行编程事务,当然注释service.xml中的行以禁用aop和txAdvice。之后,它有效:
package com.ssports.test.service;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import com.ssports.test.mapper.RecordMapper;
import com.ssports.test.model.Record;
import com.ssports.test.model.RecordExample;
import com.ssports.util.SpringHelper;
public class TestServiceImpl implements TestService {
Logger logger = LoggerFactory.getLogger(TestServiceImpl.class);
private static RecordMapper mapper = SpringHelper.getBean("recordMapper");
private static DataSourceTransactionManager txManager = SpringHelper.getBean("txManager");
private static TransactionDefinition def = new DefaultTransactionDefinition();
private static TransactionStatus status = txManager.getTransaction(def);
public List<Record> getAll() {
return mapper.selectByExample(new RecordExample());
}
public Record getRecordbyId(int id) {
Thread t = Thread.currentThread();
logger.debug("Thread Name: "+t.getName());
logger.debug("Thread id: "+t.getId());
return mapper.selectByPrimaryKey(id);
}
public void addRecords(List<Record> recordList) throws Exception {
try {
for (Record record : recordList) {
Thread t = Thread.currentThread();
logger.debug("Thread Name: "+t.getName());
logger.debug("Thread id: "+t.getId());
logger.info(record.getPosition() + ":" + record.getTime());
mapper.insert(record);
}
} catch (Exception ex) {
logger.debug("Exception throw");
logger.debug(ex.getMessage());
txManager.rollback(status);
throw ex;
}
txManager.commit(status);
}
}
这是日志:
2013-05-16 11:23:17 625 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed configuration file: 'class path resource [config/mybatis-config.xml]'
2013-05-16 11:23:17 929 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [/home/zhangzhi/workspace-STS/MultiDb/target/classes/com/ssports/uc/mybatis/mappers/UcMemberMapper.xml]'
2013-05-16 11:23:17 948 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed configuration file: 'class path resource [config/mybatis-config.xml]'
2013-05-16 11:23:18 247 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [/home/zhangzhi/workspace-STS/MultiDb/target/classes/com/ssports/site/mybatis/mappers/adMapper.xml]'
2013-05-16 11:23:18 264 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed configuration file: 'class path resource [config/mybatis-config.xml]'
2013-05-16 11:23:18 316 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [/home/zhangzhi/workspace-STS/MultiDb/target/classes/com/ssports/test/mybatis/mappers/RecordMapper.xml]'
2013-05-16 11:23:18 476 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed configuration file: 'class path resource [config/mybatis-config.xml]'
2013-05-16 11:23:18 546 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [/home/zhangzhi/workspace-STS/MultiDb/target/classes/com/ssports/uc/mybatis/mappers/UcMemberMapper.xml]'
2013-05-16 11:23:18 556 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed configuration file: 'class path resource [config/mybatis-config.xml]'
2013-05-16 11:23:18 680 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [/home/zhangzhi/workspace-STS/MultiDb/target/classes/com/ssports/site/mybatis/mappers/adMapper.xml]'
2013-05-16 11:23:18 690 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed configuration file: 'class path resource [config/mybatis-config.xml]'
2013-05-16 11:23:18 728 DEBUG: org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [/home/zhangzhi/workspace-STS/MultiDb/target/classes/com/ssports/test/mybatis/mappers/RecordMapper.xml]'
2013-05-16 11:23:18 739 DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2013-05-16 11:23:18 740 DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@6188024d] for JDBC transaction
2013-05-16 11:23:18 747 DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@6188024d] to manual commit
2013-05-16 11:23:18 748 DEBUG: com.ssports.db.TransTest - Get record1.
2013-05-16 11:23:18 749 DEBUG: com.ssports.db.TransTest - Thread Name: main
2013-05-16 11:23:18 749 DEBUG: com.ssports.db.TransTest - Thread id: 1
2013-05-16 11:23:18 749 DEBUG: com.ssports.test.service.TestServiceImpl - Thread Name: main
2013-05-16 11:23:18 749 DEBUG: com.ssports.test.service.TestServiceImpl - Thread id: 1
2013-05-16 11:23:18 754 DEBUG: org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
2013-05-16 11:23:18 757 DEBUG: org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810]
2013-05-16 11:23:18 776 DEBUG: org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [org.apache.commons.dbcp.PoolableConnection@6188024d] will be managed by Spring
2013-05-16 11:23:18 777 DEBUG: com.ssports.test.mapper.RecordMapper.selectByPrimaryKey - ooo Using Connection [org.apache.commons.dbcp.PoolableConnection@6188024d]
2013-05-16 11:23:18 783 DEBUG: com.ssports.test.mapper.RecordMapper.selectByPrimaryKey - ==> Preparing: select id, content, position, time from test where id = ?
2013-05-16 11:23:18 807 DEBUG: com.ssports.test.mapper.RecordMapper.selectByPrimaryKey - ==> Parameters: 1(Integer)
2013-05-16 11:23:18 824 DEBUG: org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810]
2013-05-16 11:23:18 824 DEBUG: com.ssports.db.TransTest - Invoking service method[addRecords]
2013-05-16 11:23:18 824 DEBUG: com.ssports.db.TransTest - Thread Name: main
2013-05-16 11:23:18 824 DEBUG: com.ssports.db.TransTest - Thread id: 1
2013-05-16 11:23:18 824 DEBUG: com.ssports.test.service.TestServiceImpl - Thread Name: main
2013-05-16 11:23:18 824 DEBUG: com.ssports.test.service.TestServiceImpl - Thread id: 1
2013-05-16 11:23:18 824 INFO : com.ssports.test.service.TestServiceImpl - 4:1368674598
2013-05-16 11:23:18 824 DEBUG: org.mybatis.spring.SqlSessionUtils - Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810] from current transaction
2013-05-16 11:23:18 825 DEBUG: com.ssports.test.mapper.RecordMapper.insert - ooo Using Connection [org.apache.commons.dbcp.PoolableConnection@6188024d]
2013-05-16 11:23:18 825 DEBUG: com.ssports.test.mapper.RecordMapper.insert - ==> Preparing: insert into test (id, content, position, time) values (?, ?, ?, ?)
2013-05-16 11:23:18 825 DEBUG: com.ssports.test.mapper.RecordMapper.insert - ==> Parameters: null, ddd(String), 4(Integer), 1368674598(Integer)
2013-05-16 11:23:18 826 DEBUG: org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810]
2013-05-16 11:23:18 826 DEBUG: com.ssports.test.service.TestServiceImpl - Thread Name: main
2013-05-16 11:23:18 826 DEBUG: com.ssports.test.service.TestServiceImpl - Thread id: 1
2013-05-16 11:23:18 826 INFO : com.ssports.test.service.TestServiceImpl - 0:1368164281
2013-05-16 11:23:18 826 DEBUG: org.mybatis.spring.SqlSessionUtils - Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810] from current transaction
2013-05-16 11:23:18 826 DEBUG: com.ssports.test.mapper.RecordMapper.insert - ooo Using Connection [org.apache.commons.dbcp.PoolableConnection@6188024d]
2013-05-16 11:23:18 826 DEBUG: com.ssports.test.mapper.RecordMapper.insert - ==> Preparing: insert into test (id, content, position, time) values (?, ?, ?, ?)
2013-05-16 11:23:18 826 DEBUG: com.ssports.test.mapper.RecordMapper.insert - ==> Parameters: null, test(String), 0(Integer), 1368164281(Integer)
2013-05-16 11:23:18 871 DEBUG: org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810]
2013-05-16 11:23:18 871 DEBUG: com.ssports.test.service.TestServiceImpl - Exception throw
2013-05-16 11:23:18 871 DEBUG: com.ssports.test.service.TestServiceImpl -
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'position'
### The error may involve com.ssports.test.mapper.RecordMapper.insert-Inline
### The error occurred while setting parameters
### SQL: insert into test (id, content, position, time) values (?, ?, ?, ?)
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'position'
; SQL []; Duplicate entry '0' for key 'position'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'position'
2013-05-16 11:23:18 871 DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
2013-05-16 11:23:18 871 DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@6188024d]
2013-05-16 11:23:18 907 DEBUG: org.mybatis.spring.SqlSessionUtils - Transaction synchronization rolling back SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810]
2013-05-16 11:23:18 907 DEBUG: org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@158b6810]
2013-05-16 11:23:18 908 DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [org.apache.commons.dbcp.PoolableConnection@6188024d] after transaction
2013-05-16 11:23:18 909 DEBUG: com.ssports.db.TransTest - Exception throw
2013-05-16 11:23:18 909 DEBUG: com.ssports.db.TransTest -
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'position'
### The error may involve com.ssports.test.mapper.RecordMapper.insert-Inline
### The error occurred while setting parameters
### SQL: insert into test (id, content, position, time) values (?, ?, ?, ?)
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'position'
; SQL []; Duplicate entry '0' for key 'position'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'position'
2013-05-16 11:23:18 909 DEBUG: com.ssports.db.TransTest - Checking Result
2013-05-16 11:23:18 909 DEBUG: org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
2013-05-16 11:23:18 909 DEBUG: org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2c8446f7] was not registered for synchronization because synchronization is not active
2013-05-16 11:23:18 929 DEBUG: org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [org.apache.commons.dbcp.PoolableConnection@6188024d] will not be managed by Spring
2013-05-16 11:23:18 929 DEBUG: com.ssports.test.mapper.RecordMapper.selectByExample - ooo Using Connection [org.apache.commons.dbcp.PoolableConnection@6188024d]
2013-05-16 11:23:18 929 DEBUG: com.ssports.test.mapper.RecordMapper.selectByExample - ==> Preparing: select id, content, position, time from test
2013-05-16 11:23:18 930 DEBUG: com.ssports.test.mapper.RecordMapper.selectByExample - ==> Parameters:
2013-05-16 11:23:18 931 DEBUG: org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2c8446f7]
2013-05-16 11:23:18 932 INFO : com.ssports.db.TransTest - 1:test:Fri May 10 13:38:01 CST 2013:0
2013-05-16 11:23:18 932 INFO : com.ssports.db.TransTest - 2:测试内容:Fri May 10 13:39:24 CST 2013:1
2013-05-16 11:23:18 932 INFO : com.ssports.db.TransTest - 44:bbb:Mon May 13 15:50:59 CST 2013:2
2013-05-16 11:23:18 932 INFO : com.ssports.db.TransTest - 45:ccc:Mon May 13 15:50:59 CST 2013:3
这是SpringHelper类:
package com.ssports.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringHelper {
private static Log logger = LogFactory.getLog(SpringHelper.class);
private static ApplicationContext cx = null;
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanId){
if(cx == null){
cx = new ClassPathXmlApplicationContext("classpath:spring/application-context.xml");
}
return (T)cx.getBean(beanId);
}
public synchronized static void init(){
if(cx == null){
cx = new ClassPathXmlApplicationContext("classpath:spring/application-context.xml");
logger.info("Spring config success!,ApplicationContext set a object");
}
}
public synchronized static void init(String[] paths){
if(cx == null){
cx = new ClassPathXmlApplicationContext(paths);
logger.info("Spring config success!,ApplicationContext set a object");
}
}
public synchronized static void init(String path){
init(new String[]{path});
}
}
更新 我在TestServiceImpl上做了一些改动,它已经解决了,如下所示:
private static RecordMapper mapper;
public void init() {
if (null == mapper) {
mapper = (RecordMapper) SpringHelper.getBean("recordMapper");
}
}
答案 0 :(得分:1)
问题:
我想说问题出在SpringHelper类实现中以及如何使用它(即TestServiceImpl中的静态引用)。 您可能有两个Spring上下文已初始化(此症状包含在日志文件的前4行中)。
为什么不起作用
一个上下文中的事务+回滚对其他上下文所做的数据库连接没有任何影响(两者都有自己的testDataSource
和txManager
bean)。
如何解决:
Spring是一个依赖注入框架,所以我没有看到实现自己的依赖查找策略的重点。您可能需要检查Autowired
注释以获取depdendencies(例如TestServiceImpl.mapper
)。
检查Spring文档和演示项目(例如https://github.com/SpringSource/greenhouse),了解如何充分利用Spring。 尝试以标准方式使用Spring 。
其他AOP问题:
顺便说一下。您的切入点定义不正确,因为只读通知不在其中。