View Javadoc
1   /*
2    *    Copyright 2015-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    *       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.boot.autoconfigure;
17  
18  import static org.assertj.core.api.Assertions.assertThat;
19  import static org.junit.jupiter.api.Assertions.assertAll;
20  
21  import java.beans.PropertyDescriptor;
22  import java.util.Arrays;
23  import java.util.HashSet;
24  import java.util.Set;
25  import java.util.stream.Collectors;
26  
27  import org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl;
28  import org.apache.ibatis.mapping.ResultSetType;
29  import org.apache.ibatis.session.AutoMappingBehavior;
30  import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior;
31  import org.apache.ibatis.session.Configuration;
32  import org.apache.ibatis.session.ExecutorType;
33  import org.apache.ibatis.session.LocalCacheScope;
34  import org.apache.ibatis.session.SqlSessionFactory;
35  import org.apache.ibatis.type.EnumOrdinalTypeHandler;
36  import org.apache.ibatis.type.EnumTypeHandler;
37  import org.apache.ibatis.type.JdbcType;
38  import org.junit.jupiter.api.Test;
39  import org.springframework.beans.PropertyAccessorFactory;
40  import org.springframework.boot.autoconfigure.AutoConfigurations;
41  import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
42  import org.springframework.boot.test.context.runner.ApplicationContextRunner;
43  
44  /**
45   * @author EddĂș MelĂ©ndez
46   */
47  class MybatisPropertiesTest {
48  
49    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
50        .withConfiguration(AutoConfigurations.of(MybatisAutoConfiguration.class));
51  
52    @Test
53    void emptyMapperLocations() {
54      MybatisProperties properties = new MybatisProperties();
55      assertThat(properties.resolveMapperLocations()).isEmpty();
56    }
57  
58    @Test
59    void twoLocations() {
60      MybatisProperties properties = new MybatisProperties();
61      properties
62          .setMapperLocations(new String[] { "classpath:org/mybatis/spring/boot/autoconfigure/repository/CityMapper.xml",
63              "classpath:org/mybatis/spring/boot/autoconfigure/repository/*Mapper.xml" });
64      assertThat(properties.resolveMapperLocations()).hasSize(2);
65    }
66  
67    @Test
68    void twoLocationsWithOneIncorrectLocation() {
69      MybatisProperties properties = new MybatisProperties();
70      properties
71          .setMapperLocations(new String[] { "classpath:org/mybatis/spring/boot/autoconfigure/repository/CityMapper.xml",
72              "classpath:org/mybatis/spring/boot/autoconfigure/repositoy/*Mapper.xml" });
73      assertThat(properties.resolveMapperLocations()).hasSize(1);
74    }
75  
76    @Test
77    void testWithDefaultCoreConfiguration() {
78      this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class).run(context -> {
79        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isSafeRowBoundsEnabled()).isFalse();
80        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isSafeResultHandlerEnabled()).isTrue();
81        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isSafeResultHandlerEnabled()).isTrue();
82        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isAggressiveLazyLoading()).isFalse();
83        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isMultipleResultSetsEnabled()).isTrue();
84        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isUseGeneratedKeys()).isFalse();
85        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isUseColumnLabel()).isTrue();
86        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isCacheEnabled()).isTrue();
87        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isCallSettersOnNulls()).isFalse();
88        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isUseActualParamName()).isTrue();
89        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isReturnInstanceForEmptyRow()).isFalse();
90        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isShrinkWhitespacesInSql()).isFalse();
91        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isNullableOnForEach()).isFalse();
92        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isArgNameBasedConstructorAutoMapping())
93            .isFalse();
94        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isLazyLoadingEnabled()).isFalse();
95        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultStatementTimeout()).isNull();
96        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultFetchSize()).isNull();
97        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLocalCacheScope())
98            .isEqualTo(LocalCacheScope.SESSION);
99        assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getJdbcTypeForNull())
100           .isEqualTo(JdbcType.OTHER);
101       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultResultSetType()).isNull();
102       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultExecutorType())
103           .isEqualTo(ExecutorType.SIMPLE);
104       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getAutoMappingBehavior())
105           .isEqualTo(AutoMappingBehavior.PARTIAL);
106       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getAutoMappingUnknownColumnBehavior())
107           .isEqualTo(AutoMappingUnknownColumnBehavior.NONE);
108       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLogPrefix()).isNull();
109       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLazyLoadTriggerMethods())
110           .isEqualTo(new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString")));
111       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLogImpl()).isNull();
112       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getVfsImpl())
113           .isEqualTo(SpringBootVFS.class);
114       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultSqlProviderType()).isNull();
115       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getTypeHandlerRegistry()
116           .getTypeHandler(JdbcType.class).getClass()).isEqualTo(EnumTypeHandler.class);
117       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getConfigurationFactory()).isNull();
118       assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getVariables()).hasToString("{}");
119     });
120   }
121 
122   @Test
123   void testWithCustomizeCoreConfiguration() {
124     assertAll(
125         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
126             .withPropertyValues("mybatis.configuration.safe-row-bounds-enabled:true")
127             .run(context -> assertThat(
128                 context.getBean(SqlSessionFactory.class).getConfiguration().isSafeRowBoundsEnabled()).isTrue()),
129         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
130             .withPropertyValues("mybatis.configuration.safe-result-handler-enabled:false")
131             .run(context -> assertThat(
132                 context.getBean(SqlSessionFactory.class).getConfiguration().isSafeResultHandlerEnabled()).isFalse()),
133         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
134             .withPropertyValues("mybatis.configuration.safe-result-handler-enabled:false")
135             .run(context -> assertThat(
136                 context.getBean(SqlSessionFactory.class).getConfiguration().isSafeResultHandlerEnabled()).isFalse()),
137         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
138             .withPropertyValues("mybatis.configuration.aggressive-lazy-loading:true")
139             .run(context -> assertThat(
140                 context.getBean(SqlSessionFactory.class).getConfiguration().isAggressiveLazyLoading()).isTrue()),
141         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
142             .withPropertyValues("mybatis.configuration.multiple-result-sets-enabled:false")
143             .run(context -> assertThat(
144                 context.getBean(SqlSessionFactory.class).getConfiguration().isMultipleResultSetsEnabled()).isFalse()),
145         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
146             .withPropertyValues("mybatis.configuration.use-generated-keys:true")
147             .run(context -> assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isUseGeneratedKeys())
148                 .isTrue()),
149         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
150             .withPropertyValues("mybatis.configuration.use-column-label:false")
151             .run(context -> assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isUseColumnLabel())
152                 .isFalse()),
153         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
154             .withPropertyValues("mybatis.configuration.cache-enabled:false")
155             .run(context -> assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isCacheEnabled())
156                 .isFalse()),
157         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
158             .withPropertyValues("mybatis.configuration.call-setters-on-nulls:true")
159             .run(context -> assertThat(
160                 context.getBean(SqlSessionFactory.class).getConfiguration().isCallSettersOnNulls()).isTrue()),
161         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
162             .withPropertyValues("mybatis.configuration.use-actual-paramName:false")
163             .run(context -> assertThat(
164                 context.getBean(SqlSessionFactory.class).getConfiguration().isUseActualParamName()).isFalse()),
165         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
166             .withPropertyValues("mybatis.configuration.return-instance-for-empty-row:true")
167             .run(context -> assertThat(
168                 context.getBean(SqlSessionFactory.class).getConfiguration().isReturnInstanceForEmptyRow()).isTrue()),
169         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
170             .withPropertyValues("mybatis.configuration.shrink-whitespaces-in-sql:true")
171             .run(context -> assertThat(
172                 context.getBean(SqlSessionFactory.class).getConfiguration().isShrinkWhitespacesInSql()).isTrue()),
173         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
174             .withPropertyValues("mybatis.configuration.nullable-on-for-each:true").run(
175                 context -> assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().isNullableOnForEach())
176                     .isTrue()),
177         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
178             .withPropertyValues("mybatis.configuration.arg-name-based-constructor-auto-mapping:true")
179             .run(context -> assertThat(
180                 context.getBean(SqlSessionFactory.class).getConfiguration().isArgNameBasedConstructorAutoMapping())
181                     .isTrue()),
182         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
183             .withPropertyValues("mybatis.configuration.lazy-loading-enabled:true")
184             .run(context -> assertThat(
185                 context.getBean(SqlSessionFactory.class).getConfiguration().isLazyLoadingEnabled()).isTrue()),
186         () -> this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class).withPropertyValues(
187             "mybatis.configuration.default-statement-timeout:2000", "mybatis.configuration.default-fetch-size:1000",
188             "mybatis.configuration.local-cache-scope:STATEMENT", "mybatis.configuration.jdbc-type-for-null:NULL",
189             "mybatis.configuration.default-result-set-type:FORWARD_ONLY",
190             "mybatis.configuration.default-executor-type:BATCH", "mybatis.configuration.auto-mapping-behavior:FULL",
191             "mybatis.configuration.auto-mapping-unknown-column-behavior:WARNING",
192             "mybatis.configuration.log-prefix:[SQL]",
193             "mybatis.configuration.lazy-Load-trigger-methods:equals,clone,hashCode,toString,toDumpString",
194             "mybatis.configuration.logImpl:org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl",
195             "mybatis.configuration.vfsImpl:org.mybatis.spring.boot.autoconfigure.MybatisPropertiesTest$MyVFS",
196             "mybatis.configuration.default-sql-provider-type:org.mybatis.spring.boot.autoconfigure.MybatisPropertiesTest$MySqlProvider",
197             "mybatis.configuration.defaultEnumTypeHandler:org.apache.ibatis.type.EnumOrdinalTypeHandler",
198             "mybatis.configuration.configuration-factory:org.mybatis.spring.boot.autoconfigure.MybatisPropertiesTest$MyConfigurationFactory",
199             "mybatis.configuration.variables.key1:value1", "mybatis.configuration.variables.key2:value2")
200             .run(context -> {
201               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultStatementTimeout())
202                   .isEqualTo(2000);
203               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultFetchSize())
204                   .isEqualTo(1000);
205               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLocalCacheScope())
206                   .isEqualTo(LocalCacheScope.STATEMENT);
207               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getJdbcTypeForNull())
208                   .isEqualTo(JdbcType.NULL);
209               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultResultSetType())
210                   .isEqualTo(ResultSetType.FORWARD_ONLY);
211               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultExecutorType())
212                   .isEqualTo(ExecutorType.BATCH);
213               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getAutoMappingBehavior())
214                   .isEqualTo(AutoMappingBehavior.FULL);
215               assertThat(
216                   context.getBean(SqlSessionFactory.class).getConfiguration().getAutoMappingUnknownColumnBehavior())
217                       .isEqualTo(AutoMappingUnknownColumnBehavior.WARNING);
218               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLogPrefix()).isEqualTo("[SQL]");
219               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLazyLoadTriggerMethods())
220                   .isEqualTo(new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString", "toDumpString")));
221               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getLogImpl())
222                   .isEqualTo(JakartaCommonsLoggingImpl.class);
223               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getVfsImpl())
224                   .isEqualTo(MyVFS.class);
225               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getDefaultSqlProviderType())
226                   .isEqualTo(MySqlProvider.class);
227               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getTypeHandlerRegistry()
228                   .getTypeHandler(JdbcType.class).getClass()).isEqualTo(EnumOrdinalTypeHandler.class);
229               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getConfigurationFactory())
230                   .isEqualTo(MyConfigurationFactory.class);
231               assertThat(context.getBean(SqlSessionFactory.class).getConfiguration().getVariables())
232                   .hasToString("{key1=value1, key2=value2}");
233             }));
234   }
235 
236   @Test
237   void checkProperties() {
238     Set<String> mybatisCoreConfigurationProperties = Arrays
239         .stream(PropertyAccessorFactory.forBeanPropertyAccess(new Configuration()).getPropertyDescriptors())
240         .map(PropertyDescriptor::getName).collect(Collectors.toSet());
241     Set<String> mybatisSpringBootConfigurationProperties = Arrays.stream(PropertyAccessorFactory
242         .forBeanPropertyAccess(new MybatisProperties.CoreConfiguration()).getPropertyDescriptors())
243         .map(PropertyDescriptor::getName).collect(Collectors.toSet());
244     mybatisCoreConfigurationProperties.removeAll(mybatisSpringBootConfigurationProperties);
245     mybatisCoreConfigurationProperties.removeAll(Arrays.asList("reflectorFactory", "defaultScriptingLanguage",
246         "sqlFragments", "typeHandlerRegistry", "mapperRegistry", "interceptors", "cacheNames", "incompleteResultMaps",
247         "typeAliasRegistry", "incompleteMethods", "proxyFactory", "resultMaps", "defaultScriptingLanguageInstance",
248         "parameterMaps", "keyGenerators", "parameterMapNames", "caches", "mappedStatementNames", "objectWrapperFactory",
249         "objectFactory", "databaseId", "incompleteStatements", "resultMapNames", "defaultScriptingLanuageInstance",
250         "keyGeneratorNames", "environment", "mappedStatements", "languageRegistry", "incompleteCacheRefs"));
251     assertThat(mybatisCoreConfigurationProperties).isEmpty();
252   }
253 
254   static class MyVFS extends SpringBootVFS {
255   }
256 
257   static class MySqlProvider {
258   }
259 
260   static class MyConfigurationFactory {
261   }
262 
263 }