View Javadoc
1   /*
2    * Copyright 2010-2023 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    *    https://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.mybatis.spring;
17  
18  import static org.assertj.core.api.Assertions.assertThat;
19  import static org.junit.jupiter.api.Assertions.assertThrows;
20  import static org.junit.jupiter.api.Assertions.fail;
21  
22  import java.sql.SQLException;
23  
24  import org.apache.ibatis.session.ExecutorType;
25  import org.apache.ibatis.session.SqlSession;
26  import org.junit.jupiter.api.AfterEach;
27  import org.junit.jupiter.api.BeforeAll;
28  import org.junit.jupiter.api.Test;
29  import org.springframework.dao.DataAccessException;
30  import org.springframework.jdbc.datasource.DataSourceTransactionManager;
31  import org.springframework.transaction.TransactionStatus;
32  import org.springframework.transaction.support.DefaultTransactionDefinition;
33  import org.springframework.transaction.support.TransactionSynchronizationManager;
34  
35  // tests basic usage and implementation only
36  // MapperFactoryBeanTest handles testing the transactional functions in SqlSessionTemplate
37  public class SqlSessionTemplateTest extends AbstractMyBatisSpringTest {
38  
39    private static SqlSession sqlSessionTemplate;
40  
41    @BeforeAll
42    static void setupSqlTemplate() {
43      sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
44    }
45  
46    @AfterEach
47    void tearDown() {
48      try {
49        connection.close();
50      } catch (SQLException ignored) {
51      }
52    }
53  
54    @Test
55    void testGetConnection() throws java.sql.SQLException {
56      java.sql.Connection conn = sqlSessionTemplate.getConnection();
57  
58      // outside of an explicit tx, getConnection() will start a tx, get an open connection then
59      // end the tx, which closes the connection
60      assertThat(conn.isClosed()).isTrue();
61    }
62  
63    @Test
64    void testGetConnectionInTx() throws java.sql.SQLException {
65      TransactionStatus status = null;
66  
67      try {
68        status = txManager.getTransaction(new DefaultTransactionDefinition());
69  
70        java.sql.Connection conn = sqlSessionTemplate.getConnection();
71  
72        assertThat(conn.isClosed()).isFalse();
73  
74      } finally {
75        // rollback required to close connection
76        txManager.rollback(status);
77      }
78    }
79  
80    @Test
81    void testCommit() {
82      assertThrows(UnsupportedOperationException.class, sqlSessionTemplate::commit);
83    }
84  
85    @Test
86    void testClose() {
87      assertThrows(UnsupportedOperationException.class, sqlSessionTemplate::close);
88    }
89  
90    @Test
91    void testRollback() {
92      assertThrows(UnsupportedOperationException.class, sqlSessionTemplate::rollback);
93    }
94  
95    @Test
96    void testExecutorType() {
97      SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
98      assertThat(template.getExecutorType()).isEqualTo(ExecutorType.BATCH);
99  
100     DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource);
101 
102     TransactionStatus status = null;
103 
104     try {
105       status = manager.getTransaction(new DefaultTransactionDefinition());
106 
107       // will synchronize the template with the current tx
108       template.getConnection();
109 
110       SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sqlSessionFactory);
111 
112       assertThat(holder.getExecutorType()).isEqualTo(ExecutorType.BATCH);
113     } finally {
114       // rollback required to close connection
115       txManager.rollback(status);
116     }
117   }
118 
119   @Test
120   void testExceptionTranslationShouldThrowMyBatisSystemException() throws SQLException {
121     try {
122       sqlSessionTemplate.selectOne("undefined");
123       fail("exception not thrown when expected");
124     } catch (MyBatisSystemException mbse) {
125       // success
126     } catch (Throwable t) {
127       fail("SqlSessionTemplate should translate MyBatis PersistenceExceptions");
128     } finally {
129       connection.close(); // the template do not open the connection so it do not close it
130     }
131   }
132 
133   @Test
134   void testExceptionTranslationShouldThrowDataAccessException() {
135 
136     // this query must be the same as the query in TestMapper.xml
137     connection.getPreparedStatementResultSetHandler().prepareThrowsSQLException("SELECT 'fail'");
138 
139     try {
140       sqlSessionTemplate.selectOne("org.mybatis.spring.TestMapper.findFail");
141       fail("exception not thrown when expected");
142     } catch (MyBatisSystemException mbse) {
143       fail("SqlSessionTemplate should translate SQLExceptions into DataAccessExceptions");
144     } catch (DataAccessException dae) {
145       // success
146     } catch (Throwable t) {
147       fail("SqlSessionTemplate should translate MyBatis PersistenceExceptions");
148     }
149   }
150 
151   @Test
152   void testTemplateWithNoTxInsert() {
153 
154     sqlSessionTemplate.getMapper(TestMapper.class).insertTest("test1");
155     assertCommitJdbc();
156     assertCommitSession();
157 
158   }
159 
160   @Test
161   void testTemplateWithNoTxSelect() {
162 
163     sqlSessionTemplate.getMapper(TestMapper.class).findTest();
164     assertCommit();
165 
166   }
167 
168   @Test
169   void testWithTxRequired() {
170     DefaultTransactionDefinition txDef = new DefaultTransactionDefinition();
171     txDef.setPropagationBehaviorName("PROPAGATION_REQUIRED");
172 
173     TransactionStatus status = txManager.getTransaction(txDef);
174 
175     sqlSessionTemplate.getMapper(TestMapper.class).findTest();
176 
177     txManager.commit(status);
178 
179     assertCommit();
180     assertSingleConnection();
181   }
182 
183 }