Comments (9)
Hi,
How are you going to control the tx manually. Which api are you going to
use?
2014-07-18 17:42 GMT+02:00 Zen Zhong [email protected]:
I'm running mybatis-spring 1.2.2, I need to control transaction manually
for part of DAO (for integration with datagrid via JTA), transaction is
controlled by SqlSession, SqlSession is got from sqlSessionFactory manually
in code, and sqlSessionFactory is a spring bean:When logs show "DEBUG [main]
org.mybatis.spring.transaction.SpringManagedTransaction: JDBC Connection
com.mysql.jdbc.JDBC4Connection @ 7f946a32 will not be managed by Spring",
my rollback doesn't work.From org.mybatis.spring.transaction.SpringManagedTransactionFactory's
javadoc: "If Spring's transaction handling is active it will no-op all
commit/rollback/close calls assuming that the Spring transaction manager
will do the job. If it is not it will behave like JdbcTransaction.", to my
understanding, it should be rolled back.Part code of SpringManagedTransactionFactory:
public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
return new SpringManagedTransaction(dataSource);
}autoCommit is ignored, always. Is it a bug?
I'll push my whole testing project to GitHub if necessary.
Currently, a workaround is to set JdbcTransactionFactory as
transactionFactory, configuration:—
Reply to this email directly or view it on GitHub
#39.
from spring.
Hi,
via SqlSession, sqlSessionFactory.openSession(false) -> sqlSession.rollback()
I've pushed the testing project to https://github.com/zenzhong8383/mybatis_test , the testing failed method is TestSqlSessionFactoryBean.testMybatisSpring1
from spring.
Is autocommit off?
2014-07-19 17:06 GMT+02:00 Zen Zhong [email protected]:
Hi,
via SqlSession, sqlSessionFactory.openSession(false) ->
sqlSession.rollback()I've pushed the testing project to
https://github.com/zenzhong8383/mybatis_test , the testing failed method
is TestSqlSessionFactoryBean.testMybatisSpring1—
Reply to this email directly or view it on GitHub
#39 (comment).
from spring.
autocommit is off.
sqlSession is assigned as "SqlSessionFactory.openSession(boolean autoCommit)", autoCommit is false.
In fact, there're 3 test cases: testMybatisSpring1/testMybatisSpring2/testMybatis, all of them will call "testRollback(SqlSessionFactory sqlSessionFactory, List<ImmutablePair<Long, String>> pairs)" method, the difference is they get sqlSessionFactory by different way.
Simplified code:
public class TestSqlSessionFactoryBean {
private SqlSessionFactory sqlSessionFactory1;
private SqlSessionFactory sqlSessionFactory2;
@Before
public void init() throws SQLException {
try (AbstractApplicationContext appCtx = new ClassPathXmlApplicationContext("config/applicationContext.xml")) {
sqlSessionFactory1 = (SqlSessionFactory) appCtx.getBean("sqlSessionFactory1");
sqlSessionFactory2 = (SqlSessionFactory) appCtx.getBean("sqlSessionFactory2");
}
try (SqlSession sqlSession = sqlSessionFactory1.openSession(); Connection conn = sqlSession.getConnection();) {
try (Statement stmt = conn.createStatement()) {
stmt.execute("DROP TABLE IF EXISTS mybatis_test");
}
try (Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE mybatis_test (id UNIQUE, name NOT NULL)");
}
}
}
private void testRollback(SqlSessionFactory sqlSessionFactory) {
try (SqlSession sqlSession = sqlSessionFactory.openSession(false)) {
MybatisTestMapper mapper = sqlSession.getMapper(MybatisTestMapper.class);
mapper.insert(1, "test1");
sqlSession.rollback();
}
}
// rollback doesn't work
@Test
public void testMybatisSpring1() {
testRollback(sqlSessionFactory1);
}
// rollback works
@Test
public void testMybatisSpring2() {
testRollback(sqlSessionFactory2);
}
// rollback works
@Test
public void testMybatis() throws IOException {
SqlSessionFactory sqlSessionFactory;
try (InputStream inputStream = Resources.getResourceAsStream("config/mybatis-config-standalone.xml")) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
testRollback(sqlSessionFactory);
}
}
config/applicationContext.xml
<bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="config/mybatis-config-spring.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionFactory" class="org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory" />
<bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="config/mybatis-config-spring.xml" />
<property name="dataSource" ref="dataSource" />
<property name="transactionFactory" ref="transactionFactory" />
</bean>
from spring.
Hi Zen,
MyBatis-Spring is built around an object called SqlSessionTemplate
(following String templates saga like JdbcTemplate). This bean makes your
code participate in an Spring transaction.
You are not using that but injecting a "normal" SqlSessionFactory on your
bean. This SqlSessionFactory is not 100% normal because it will have the
SpringTransactionFactory set instead of the JdbcTransactionFactory. Anyway
they behave almost alike when Spring TX is not active.
Note that there is no magic here, if you call session.rollback() it will
end up call ing connnection.rollback() and changes should rollback. If it
does not, I can only think of autocommit being the culprit.
I would suggest printing conn.getAutocommit() to make sure it is off.
Debugging line by line may bring some light also.
2014-07-20 4:03 GMT+02:00 Zen Zhong [email protected]:
autocommit is off.
sqlSession is assigned as "SqlSessionFactory.openSession(boolean
autoCommit)", autoCommit is false.In fact, there're 3 test cases:
testMybatisSpring1/testMybatisSpring2/testMybatis, all of them will call
"testRollback(SqlSessionFactory sqlSessionFactory, List> pairs)" method,
the difference is they get sqlSessionFactory by different way.Simplified code:
public class TestSqlSessionFactoryBean {
private SqlSessionFactory sqlSessionFactory1;
private SqlSessionFactory sqlSessionFactory2;@Before public void init() throws SQLException { try (AbstractApplicationContext appCtx = new ClassPathXmlApplicationContext("config/applicationContext.xml")) { sqlSessionFactory1 = (SqlSessionFactory) appCtx.getBean("sqlSessionFactory1"); sqlSessionFactory2 = (SqlSessionFactory) appCtx.getBean("sqlSessionFactory2"); } try (SqlSession sqlSession = sqlSessionFactory1.openSession(); Connection conn = sqlSession.getConnection();) { try (Statement stmt = conn.createStatement()) { stmt.execute("DROP TABLE IF EXISTS mybatis_test"); } try (Statement stmt = conn.createStatement()) { stmt.execute("CREATE TABLE mybatis_test (id UNIQUE, name NOT NULL)"); } } } private void testRollback(SqlSessionFactory sqlSessionFactory) { try (SqlSession sqlSession = sqlSessionFactory.openSession(false)) { MybatisTestMapper mapper = sqlSession.getMapper(MybatisTestMapper.class); mapper.insert(1, "test1"); sqlSession.rollback(); } } // rollback doesn't work @Test public void testMybatisSpring1() { testRollback(sqlSessionFactory1); } // rollback works @Test public void testMybatisSpring2() { testRollback(sqlSessionFactory2); } // rollback works @Test public void testMybatis() throws IOException { SqlSessionFactory sqlSessionFactory; try (InputStream inputStream = Resources.getResourceAsStream("config/mybatis-config-standalone.xml")) { sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } testRollback(sqlSessionFactory); }
}
config/applicationContext.xml
<bean id="transactionFactory" class="org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory" /> <bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="config/mybatis-config-spring.xml" /> <property name="dataSource" ref="dataSource" /> <property name="transactionFactory" ref="transactionFactory" /> </bean>
—
Reply to this email directly or view it on GitHub
#39 (comment).
from spring.
Hi Eduardo,
I debugged it, some objects' states:
sqlSession.autoCommit=false
sqlSession.executor.transaction is instanceof SpringManagedTransaction
sqlSession.executor.transaction.autoCommit=true
sqlSession.executor.transaction.connection.autoCommit=true
Since sqlSession.executor.transaction.autoCommit=true, SpringManagedTransaction.rollback() doesn't execute "this.connection.rollback();", the related code is:
public void rollback() throws SQLException {
if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
if (logger.isDebugEnabled()) {
logger.debug("Rolling back JDBC Connection [" + this.connection + "]");
}
this.connection.rollback();
}
}
SpringManagedTransactionFactory ignore autoCommit; SpringManagedTransaction.openConnection() will set this.autoCommit as "this.connection.getAutoCommit()", it always be true.
And also, SqlSessionTemplate doesn't support rollback. What's the correct way to control transaction manually when current code is based on MyBatis-Spring?
from spring.
Hi Zen. That makes sense.
Options are:
1.- Configure your datasource to turn autocommit off
2.- Configure the SqlSessionFactoryBean to use JdbcTransactionFactory
3.- Use Spring's programmatic TX management API (
http://mybatis.github.io/spring/transactions.html#programmatic)
Hope this helps!
2014-07-20 16:07 GMT+02:00 Zen Zhong [email protected]:
Hi Eduardo,
I debugged it, some objects' states:
sqlSession.autoCommit=false
sqlSession.executor.transaction is instanceof SpringManagedTransaction
sqlSession.executor.transaction.autoCommit=true
sqlSession.executor.transaction.connection.autoCommit=trueSince sqlSession.executor.transaction.autoCommit=true,
SpringManagedTransaction.rollback() doesn't execute
"this.connection.rollback();", the related code is:public void rollback() throws SQLException {
if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
if (logger.isDebugEnabled()) {
logger.debug("Rolling back JDBC Connection [" + this.connection + "]");
}
this.connection.rollback();
}
}SpringManagedTransactionFactory ignore autoCommit;
SpringManagedTransaction.openConnection() will set this.autoCommit as
"this.connection.getAutoCommit()", it always be true.And also, SqlSessionTemplate doesn't support rollback. What's the correct
way to control transaction manually when current code is based on
MyBatis-Spring?—
Reply to this email directly or view it on GitHub
#39 (comment).
from spring.
Thanks, Eduardo. It's impressive to receive replies so quickly, I could
move on now.
2014-07-21 4:17 GMT+08:00 Eduardo Macarron [email protected]:
Hi Zen. That makes sense.
Options are:
1.- Configure your datasource to turn autocommit off
2.- Configure the SqlSessionFactoryBean to use JdbcTransactionFactory
3.- Use Spring's programmatic TX management API (
http://mybatis.github.io/spring/transactions.html#programmatic)Hope this helps!
2014-07-20 16:07 GMT+02:00 Zen Zhong [email protected]:
Hi Eduardo,
I debugged it, some objects' states:
sqlSession.autoCommit=false
sqlSession.executor.transaction is instanceof SpringManagedTransaction
sqlSession.executor.transaction.autoCommit=true
sqlSession.executor.transaction.connection.autoCommit=trueSince sqlSession.executor.transaction.autoCommit=true,
SpringManagedTransaction.rollback() doesn't execute
"this.connection.rollback();", the related code is:public void rollback() throws SQLException {
if (this.connection != null && !this.isConnectionTransactional &&
!this.autoCommit) {
if (logger.isDebugEnabled()) {
logger.debug("Rolling back JDBC Connection [" + this.connection + "]");
}
this.connection.rollback();
}
}SpringManagedTransactionFactory ignore autoCommit;
SpringManagedTransaction.openConnection() will set this.autoCommit as
"this.connection.getAutoCommit()", it always be true.And also, SqlSessionTemplate doesn't support rollback. What's the
correct
way to control transaction manually when current code is based on
MyBatis-Spring?—
Reply to this email directly or view it on GitHub
#39 (comment).—
Reply to this email directly or view it on GitHub
#39 (comment).
from spring.
Hi Eduardo,
I am using SqlSessionFactoryBean with below properties along with Mapper interfaces and mybatis:scan in the spring config . So, how do i manually control the transaction now .
<mybatis:scan base-package="jrout.mypackage" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="transactionFactory">
<bean class="org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory" />
</property>
<property name="configLocation" value="classpath:mySqlMapConfig.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
Is there any working copy of the code which i can refer it to.
from spring.
Related Issues (20)
- mapperLocations is overwritten HOT 1
- SqlSessionFactoryBean single resource, using wildcard causes a IOException HOT 4
- When Spring has multiple ApplicationContexts, it may throw BeanCreationNotAllowedException HOT 1
- Update dependency org.mybatis:mybatis to v3.5.13 on 2.1.x
- fix: change the event type that SqlSessionFactory is listening to on 2.1.x
- Drop support 1.3.x and 2.0.x
- Support processPropertyPlaceHolders option in mapper:scan and @MapperScan
- does mybatis-spring support to use customized mapper excludeFilters? HOT 1
- The logic regarding transaction rollback seems incorrect HOT 3
- The latest springboot using mybatis-spring-stater 3.0.2 throw exception "Invalid value type for attribute 'factoryBeanObjectType': java.lang.String" HOT 6
- The first query of maybatis takes longer than the second query. How to warm up in advance? HOT 1
- Switch baseline to Spring 6.1 and Spring Batch 5.1
- Support JDK 22 on CI
- why not override postProcessBeanDefinition method in ClassPathMapperScanner
- The latest springboot using mybatis-spring-stater 3.0.3-SNAPSHOT throw exception "Invalid value type for attribute 'factoryBeanObjectType': java.lang.String" HOT 5
- An idea to adapt to Spring 6.1 HOT 3
- MyBatisSystemException message is null
- Why @MapperScan scan all interface? Maybe only scan annotated with @Mapper is better? HOT 2
- mybatis-spring official docs for english responds 404 HOT 8
- spring boot 3.2.x aot problem
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from spring.