Skip to content

Commit 13d5d0d

Browse files
authored
Merge pull request #2516 from harawata/add-skipSetAutoCommitOnClose-to-JdbcTransactionFactory
Add a new property skipSetAutoCommitOnClose to JdbcTransactionFactory
2 parents 0f42365 + ccf52ab commit 13d5d0d

File tree

10 files changed

+457
-9
lines changed

10 files changed

+457
-9
lines changed

src/main/java/org/apache/ibatis/transaction/jdbc/JdbcTransaction.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2021 the original author or authors.
2+
* Copyright 2009-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -44,11 +44,17 @@ public class JdbcTransaction implements Transaction {
4444
protected DataSource dataSource;
4545
protected TransactionIsolationLevel level;
4646
protected boolean autoCommit;
47+
protected boolean skipSetAutoCommitOnClose;
4748

4849
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
50+
this(ds, desiredLevel, desiredAutoCommit, false);
51+
}
52+
53+
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit, boolean skipSetAutoCommitOnClose) {
4954
dataSource = ds;
5055
level = desiredLevel;
5156
autoCommit = desiredAutoCommit;
57+
this.skipSetAutoCommitOnClose = skipSetAutoCommitOnClose;
5258
}
5359

5460
public JdbcTransaction(Connection connection) {
@@ -113,7 +119,7 @@ protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
113119

114120
protected void resetAutoCommit() {
115121
try {
116-
if (!connection.getAutoCommit()) {
122+
if (!skipSetAutoCommitOnClose && !connection.getAutoCommit()) {
117123
// MyBatis does not call commit/rollback on a connection if just selects were performed.
118124
// Some databases start transactions with select statements
119125
// and they mandate a commit/rollback before closing the connection.

src/main/java/org/apache/ibatis/transaction/jdbc/JdbcTransactionFactory.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2021 the original author or authors.
2+
* Copyright 2009-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616
package org.apache.ibatis.transaction.jdbc;
1717

1818
import java.sql.Connection;
19+
import java.util.Properties;
1920

2021
import javax.sql.DataSource;
2122

@@ -32,13 +33,26 @@
3233
*/
3334
public class JdbcTransactionFactory implements TransactionFactory {
3435

36+
private boolean skipSetAutoCommitOnClose;
37+
38+
@Override
39+
public void setProperties(Properties props) {
40+
if (props == null) {
41+
return;
42+
}
43+
String value = props.getProperty("skipSetAutoCommitOnClose");
44+
if (value != null) {
45+
skipSetAutoCommitOnClose = Boolean.parseBoolean(value);
46+
}
47+
}
48+
3549
@Override
3650
public Transaction newTransaction(Connection conn) {
3751
return new JdbcTransaction(conn);
3852
}
3953

4054
@Override
4155
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
42-
return new JdbcTransaction(ds, level, autoCommit);
56+
return new JdbcTransaction(ds, level, autoCommit, skipSetAutoCommitOnClose);
4357
}
4458
}

src/site/es/xdoc/configuration.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,10 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader,properti
16471647
<p>MyBatis incluye dos tipos de TransactionManager (ej. type=”[JDBC|MANAGED]”):
16481648
</p>
16491649
<ul>
1650-
<li>JDBC – Este TransactionManager simplemente hace uso del las capacidades de commit y rollback de JDBC. Utiliza la conexión obtenida del DataSource para gestionar la transacción.
1650+
<li>JDBC – Este TransactionManager simplemente hace uso del las capacidades de commit y rollback de JDBC. Utiliza la conexión obtenida del DataSource para gestionar la transacción. By default, it enables auto-commit when closing the connection for compatibility with some drivers. However, for some drivers, enabling auto-commit is not only unnecesry, but also is an expensive operation. So, since version 3.5.10, you can skip this step by setting the "skipSetAutoCommitOnClose" property to true. For example:
1651+
<source><![CDATA[<transactionManager type="JDBC">
1652+
<property name="skipSetAutoCommitOnClose" value="true"/>
1653+
</transactionManager>]]></source>
16511654
</li>
16521655
<li>MANAGED – Este TransactionManager no hace nada. No hace commit ni rollback sobre la conexión. En su lugar, permite que el contenedor gestione el ciclo de vida completo de la transacción (ej. Spring o un servidor de aplicaciones JEE). Por defecto cierra la conexión. Sin embargo, algunos contenedores no esperan que la conexión se cierre y por tanto, si necesitas cambiar este comportamiento, informa la propiedad closeConnection a false. Por ejemplo:
16531656
<source><![CDATA[<transactionManager type="MANAGED">

src/site/ja/xdoc/configuration.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,10 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader,properti
17191719
<ul>
17201720
<li>
17211721
JDBC - JDBC トランザクションマネージャーは、単純に JDBC のコミットとロールバックの機能を直接利用します。
1722-
この場合、トランザクションのスコープはデータソースから取得した接続に依存します。
1722+
この場合、トランザクションのスコープはデータソースから取得した接続に依存します。一部のドライバーとの互換性を保つため、デフォルトでは接続をクローズする前にオートコミットを有効化するようになっていますが、この処理は他のドライバにとっては不要なだけでなく負荷の高い操作となる可能性があります。バージョン 3.5.10 以降では skipSetAutoCommitOnClose に false を設定することでオートコミットの有効化処理をスキップできるようになっています。
1723+
<source><![CDATA[<transactionManager type="JDBC">
1724+
<property name="skipSetAutoCommitOnClose" value="false"/>
1725+
</transactionManager>]]></source>
17231726
</li>
17241727
<li>
17251728
MANAGED - MANAGED トランザクションマネージャーはコミットもロールバックもしません。

src/site/ko/xdoc/configuration.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1613,7 +1613,11 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader,properti
16131613
<p>마이바티스는 두 가지 타입의 TransactionManager를 제공한다.</p>
16141614
<ul>
16151615
<li>JDBC - 이 설정은 간단하게 JDBC 커밋과 롤백을 처리하기 위해 사용된다.
1616-
트랜잭션의 스코프를 관리하기 위해 dataSource 로 부터 커넥션을 가져온다. </li>
1616+
트랜잭션의 스코프를 관리하기 위해 dataSource 로 부터 커넥션을 가져온다. By default, it enables auto-commit when closing the connection for compatibility with some drivers. However, for some drivers, enabling auto-commit is not only unnecesry, but also is an expensive operation. So, since version 3.5.10, you can skip this step by setting the "skipSetAutoCommitOnClose" property to true. For example:
1617+
<source><![CDATA[<transactionManager type="JDBC">
1618+
<property name="skipSetAutoCommitOnClose" value="true"/>
1619+
</transactionManager>]]></source>
1620+
</li>
16171621
<li>MANAGED - 이 설정은 어떤것도 하지 않는다.
16181622
결코 커밋이나 롤백을 하지 않는다.
16191623
대신 컨테이너가 트랜잭션의 모든 생명주기를 관리한다.

src/site/xdoc/configuration.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1885,7 +1885,10 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert
18851885
and
18861886
rollback facilities directly. It relies on the connection
18871887
retrieved from the dataSource to manage the scope of the
1888-
transaction.
1888+
transaction. By default, it enables auto-commit when closing the connection for compatibility with some drivers. However, for some drivers, enabling auto-commit is not only unnecesry, but also is an expensive operation. So, since version 3.5.10, you can skip this step by setting the "skipSetAutoCommitOnClose" property to true. For example:
1889+
<source><![CDATA[<transactionManager type="JDBC">
1890+
<property name="skipSetAutoCommitOnClose" value="true"/>
1891+
</transactionManager>]]></source>
18891892
</li>
18901893
<li>
18911894
MANAGED – This configuration simply does almost nothing. It

src/site/zh/xdoc/configuration.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1672,7 +1672,10 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert
16721672
<p>在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):</p>
16731673
<ul>
16741674
<li>
1675-
JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
1675+
JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。 By default, it enables auto-commit when closing the connection for compatibility with some drivers. However, for some drivers, enabling auto-commit is not only unnecesry, but also is an expensive operation. So, since version 3.5.10, you can skip this step by setting the "skipSetAutoCommitOnClose" property to true. For example:
1676+
<source><![CDATA[<transactionManager type="JDBC">
1677+
<property name="skipSetAutoCommitOnClose" value="true"/>
1678+
</transactionManager>]]></source>
16761679
</li>
16771680
<li>
16781681
MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2009-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.apache.ibatis.transaction.jdbc;
17+
18+
import static org.junit.Assert.*;
19+
import static org.mockito.Mockito.*;
20+
21+
import java.util.Properties;
22+
23+
import javax.sql.DataSource;
24+
25+
import org.apache.ibatis.session.TransactionIsolationLevel;
26+
import org.apache.ibatis.transaction.Transaction;
27+
import org.junit.jupiter.api.Test;
28+
29+
class JdbcTransactionFactoryTest {
30+
31+
@Test
32+
void testNullProperties() throws Exception {
33+
TestConnection connection = new TestConnection(false);
34+
JdbcTransactionFactory factory = new JdbcTransactionFactory();
35+
factory.setProperties(null);
36+
Transaction transaction = factory.newTransaction(connection);
37+
transaction.getConnection();
38+
transaction.close();
39+
assertTrue(connection.getAutoCommit());
40+
}
41+
42+
@Test
43+
void testSkipSetAutoCommitOnClose() throws Exception {
44+
TestConnection connection = new TestConnection(false);
45+
DataSource ds = mock(DataSource.class);
46+
when(ds.getConnection()).thenReturn(connection);
47+
48+
JdbcTransactionFactory factory = new JdbcTransactionFactory();
49+
Properties properties = new Properties();
50+
properties.setProperty("skipSetAutoCommitOnClose", "true");
51+
factory.setProperties(properties);
52+
Transaction transaction = factory.newTransaction(ds, TransactionIsolationLevel.NONE, false);
53+
transaction.getConnection();
54+
transaction.close();
55+
assertFalse(connection.getAutoCommit());
56+
}
57+
58+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2009-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.apache.ibatis.transaction.jdbc;
17+
18+
import static org.junit.Assert.*;
19+
import static org.mockito.Mockito.*;
20+
21+
import javax.sql.DataSource;
22+
23+
import org.apache.ibatis.session.TransactionIsolationLevel;
24+
import org.junit.jupiter.api.Test;
25+
26+
class JdbcTransactionTest {
27+
@Test
28+
void testSetAutoCommitOnClose() throws Exception {
29+
testAutoCommit(true, false, true, false);
30+
testAutoCommit(false, false, true, false);
31+
testAutoCommit(true, true, true, false);
32+
testAutoCommit(false, true, true, false);
33+
testAutoCommit(true, false, false, true);
34+
testAutoCommit(false, false, false, true);
35+
testAutoCommit(true, true, true, true);
36+
testAutoCommit(false, true, true, true);
37+
}
38+
39+
private void testAutoCommit(boolean initialAutoCommit, boolean desiredAutoCommit, boolean resultAutoCommit,
40+
boolean skipSetAutoCommitOnClose) throws Exception {
41+
TestConnection con = new TestConnection(initialAutoCommit);
42+
DataSource ds = mock(DataSource.class);
43+
when(ds.getConnection()).thenReturn(con);
44+
45+
JdbcTransaction transaction = new JdbcTransaction(ds, TransactionIsolationLevel.NONE, desiredAutoCommit, skipSetAutoCommitOnClose);
46+
transaction.getConnection();
47+
transaction.commit();
48+
transaction.close();
49+
50+
assertEquals(resultAutoCommit, con.getAutoCommit());
51+
}
52+
}

0 commit comments

Comments
 (0)