1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.builder;
17
18 import static com.googlecode.catchexception.apis.BDDCatchException.*;
19 import static org.assertj.core.api.Assertions.assertThat;
20 import static org.assertj.core.api.BDDAssertions.then;
21 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25
26 import java.io.InputStream;
27 import java.io.StringReader;
28 import java.math.RoundingMode;
29 import java.sql.CallableStatement;
30 import java.sql.PreparedStatement;
31 import java.sql.ResultSet;
32 import java.sql.SQLException;
33 import java.util.Arrays;
34 import java.util.HashSet;
35 import java.util.Properties;
36
37 import org.apache.ibatis.builder.mapper.CustomMapper;
38 import org.apache.ibatis.builder.typehandler.CustomIntegerTypeHandler;
39 import org.apache.ibatis.builder.xml.XMLConfigBuilder;
40 import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
41 import org.apache.ibatis.domain.blog.Author;
42 import org.apache.ibatis.domain.blog.Blog;
43 import org.apache.ibatis.domain.blog.mappers.BlogMapper;
44 import org.apache.ibatis.domain.blog.mappers.NestedBlogMapper;
45 import org.apache.ibatis.domain.jpetstore.Cart;
46 import org.apache.ibatis.executor.loader.cglib.CglibProxyFactory;
47 import org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory;
48 import org.apache.ibatis.io.JBoss6VFS;
49 import org.apache.ibatis.io.Resources;
50 import org.apache.ibatis.logging.slf4j.Slf4jImpl;
51 import org.apache.ibatis.mapping.Environment;
52 import org.apache.ibatis.mapping.ResultSetType;
53 import org.apache.ibatis.scripting.defaults.RawLanguageDriver;
54 import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
55 import org.apache.ibatis.session.AutoMappingBehavior;
56 import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior;
57 import org.apache.ibatis.session.Configuration;
58 import org.apache.ibatis.session.ExecutorType;
59 import org.apache.ibatis.session.LocalCacheScope;
60 import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
61 import org.apache.ibatis.type.BaseTypeHandler;
62 import org.apache.ibatis.type.EnumOrdinalTypeHandler;
63 import org.apache.ibatis.type.EnumTypeHandler;
64 import org.apache.ibatis.type.JdbcType;
65 import org.apache.ibatis.type.TypeHandler;
66 import org.apache.ibatis.type.TypeHandlerRegistry;
67 import org.junit.jupiter.api.Test;
68
69 class XmlConfigBuilderTest {
70
71 @Test
72 void shouldSuccessfullyLoadMinimalXMLConfigFile() throws Exception {
73 String resource = "org/apache/ibatis/builder/MinimalMapperConfig.xml";
74 try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
75 XMLConfigBuilder builder = new XMLConfigBuilder(inputStream);
76 Configuration config = builder.parse();
77 assertNotNull(config);
78 assertThat(config.getAutoMappingBehavior()).isEqualTo(AutoMappingBehavior.PARTIAL);
79 assertThat(config.getAutoMappingUnknownColumnBehavior()).isEqualTo(AutoMappingUnknownColumnBehavior.NONE);
80 assertThat(config.isCacheEnabled()).isTrue();
81 assertThat(config.getProxyFactory()).isInstanceOf(JavassistProxyFactory.class);
82 assertThat(config.isLazyLoadingEnabled()).isFalse();
83 assertThat(config.isAggressiveLazyLoading()).isFalse();
84 assertThat(config.isMultipleResultSetsEnabled()).isTrue();
85 assertThat(config.isUseColumnLabel()).isTrue();
86 assertThat(config.isUseGeneratedKeys()).isFalse();
87 assertThat(config.getDefaultExecutorType()).isEqualTo(ExecutorType.SIMPLE);
88 assertNull(config.getDefaultStatementTimeout());
89 assertNull(config.getDefaultFetchSize());
90 assertNull(config.getDefaultResultSetType());
91 assertThat(config.isMapUnderscoreToCamelCase()).isFalse();
92 assertThat(config.isSafeRowBoundsEnabled()).isFalse();
93 assertThat(config.getLocalCacheScope()).isEqualTo(LocalCacheScope.SESSION);
94 assertThat(config.getJdbcTypeForNull()).isEqualTo(JdbcType.OTHER);
95 assertThat(config.getLazyLoadTriggerMethods()).isEqualTo(new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString")));
96 assertThat(config.isSafeResultHandlerEnabled()).isTrue();
97 assertThat(config.getDefaultScriptingLanuageInstance()).isInstanceOf(XMLLanguageDriver.class);
98 assertThat(config.isCallSettersOnNulls()).isFalse();
99 assertNull(config.getLogPrefix());
100 assertNull(config.getLogImpl());
101 assertNull(config.getConfigurationFactory());
102 assertThat(config.getTypeHandlerRegistry().getTypeHandler(RoundingMode.class)).isInstanceOf(EnumTypeHandler.class);
103 }
104 }
105
106 enum MyEnum {
107 ONE, TWO
108 }
109
110 public static class EnumOrderTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
111
112 private E[] constants;
113
114 public EnumOrderTypeHandler(Class<E> javaType) {
115 constants = javaType.getEnumConstants();
116 }
117
118 @Override
119 public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
120 ps.setInt(i, parameter.ordinal() + 1);
121 }
122
123 @Override
124 public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
125 int index = rs.getInt(columnName) - 1;
126 return index < 0 ? null : constants[index];
127 }
128
129 @Override
130 public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
131 int index = rs.getInt(rs.getInt(columnIndex)) - 1;
132 return index < 0 ? null : constants[index];
133 }
134
135 @Override
136 public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
137 int index = cs.getInt(columnIndex) - 1;
138 return index < 0 ? null : constants[index];
139 }
140 }
141
142 @Test
143 void registerJavaTypeInitializingTypeHandler() {
144 final String MAPPER_CONFIG = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
145 + "<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n"
146 + "<configuration>\n"
147 + " <typeHandlers>\n"
148 + " <typeHandler javaType=\"org.apache.ibatis.builder.XmlConfigBuilderTest$MyEnum\"\n"
149 + " handler=\"org.apache.ibatis.builder.XmlConfigBuilderTest$EnumOrderTypeHandler\"/>\n"
150 + " </typeHandlers>\n"
151 + "</configuration>\n";
152
153 XMLConfigBuilder builder = new XMLConfigBuilder(new StringReader(MAPPER_CONFIG));
154 builder.parse();
155
156 TypeHandlerRegistry typeHandlerRegistry = builder.getConfiguration().getTypeHandlerRegistry();
157 TypeHandler<MyEnum> typeHandler = typeHandlerRegistry.getTypeHandler(MyEnum.class);
158
159 assertTrue(typeHandler instanceof EnumOrderTypeHandler);
160 assertArrayEquals(MyEnum.values(), ((EnumOrderTypeHandler<MyEnum>) typeHandler).constants);
161 }
162
163 @Test
164 void shouldSuccessfullyLoadXMLConfigFile() throws Exception {
165 String resource = "org/apache/ibatis/builder/CustomizedSettingsMapperConfig.xml";
166 try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
167 Properties props = new Properties();
168 props.put("prop2", "cccc");
169 XMLConfigBuilder builder = new XMLConfigBuilder(inputStream, null, props);
170 Configuration config = builder.parse();
171
172 assertThat(config.getAutoMappingBehavior()).isEqualTo(AutoMappingBehavior.NONE);
173 assertThat(config.getAutoMappingUnknownColumnBehavior()).isEqualTo(AutoMappingUnknownColumnBehavior.WARNING);
174 assertThat(config.isCacheEnabled()).isFalse();
175 assertThat(config.getProxyFactory()).isInstanceOf(CglibProxyFactory.class);
176 assertThat(config.isLazyLoadingEnabled()).isTrue();
177 assertThat(config.isAggressiveLazyLoading()).isTrue();
178 assertThat(config.isMultipleResultSetsEnabled()).isFalse();
179 assertThat(config.isUseColumnLabel()).isFalse();
180 assertThat(config.isUseGeneratedKeys()).isTrue();
181 assertThat(config.getDefaultExecutorType()).isEqualTo(ExecutorType.BATCH);
182 assertThat(config.getDefaultStatementTimeout()).isEqualTo(10);
183 assertThat(config.getDefaultFetchSize()).isEqualTo(100);
184 assertThat(config.getDefaultResultSetType()).isEqualTo(ResultSetType.SCROLL_INSENSITIVE);
185 assertThat(config.isMapUnderscoreToCamelCase()).isTrue();
186 assertThat(config.isSafeRowBoundsEnabled()).isTrue();
187 assertThat(config.getLocalCacheScope()).isEqualTo(LocalCacheScope.STATEMENT);
188 assertThat(config.getJdbcTypeForNull()).isEqualTo(JdbcType.NULL);
189 assertThat(config.getLazyLoadTriggerMethods()).isEqualTo(new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString", "xxx")));
190 assertThat(config.isSafeResultHandlerEnabled()).isFalse();
191 assertThat(config.getDefaultScriptingLanuageInstance()).isInstanceOf(RawLanguageDriver.class);
192 assertThat(config.isCallSettersOnNulls()).isTrue();
193 assertThat(config.getLogPrefix()).isEqualTo("mybatis_");
194 assertThat(config.getLogImpl().getName()).isEqualTo(Slf4jImpl.class.getName());
195 assertThat(config.getVfsImpl().getName()).isEqualTo(JBoss6VFS.class.getName());
196 assertThat(config.getConfigurationFactory().getName()).isEqualTo(String.class.getName());
197
198 assertThat(config.getTypeAliasRegistry().getTypeAliases().get("blogauthor")).isEqualTo(Author.class);
199 assertThat(config.getTypeAliasRegistry().getTypeAliases().get("blog")).isEqualTo(Blog.class);
200 assertThat(config.getTypeAliasRegistry().getTypeAliases().get("cart")).isEqualTo(Cart.class);
201
202 assertThat(config.getTypeHandlerRegistry().getTypeHandler(Integer.class)).isInstanceOf(CustomIntegerTypeHandler.class);
203 assertThat(config.getTypeHandlerRegistry().getTypeHandler(Long.class)).isInstanceOf(CustomLongTypeHandler.class);
204 assertThat(config.getTypeHandlerRegistry().getTypeHandler(String.class)).isInstanceOf(CustomStringTypeHandler.class);
205 assertThat(config.getTypeHandlerRegistry().getTypeHandler(String.class, JdbcType.VARCHAR)).isInstanceOf(CustomStringTypeHandler.class);
206 assertThat(config.getTypeHandlerRegistry().getTypeHandler(RoundingMode.class)).isInstanceOf(EnumOrdinalTypeHandler.class);
207
208 ExampleObjectFactorye/ibatis/builder/ExampleObjectFactory.html#ExampleObjectFactory">ExampleObjectFactory objectFactory = (ExampleObjectFactory) config.getObjectFactory();
209 assertThat(objectFactory.getProperties().size()).isEqualTo(1);
210 assertThat(objectFactory.getProperties().getProperty("objectFactoryProperty")).isEqualTo("100");
211
212 assertThat(config.getObjectWrapperFactory()).isInstanceOf(CustomObjectWrapperFactory.class);
213
214 assertThat(config.getReflectorFactory()).isInstanceOf(CustomReflectorFactory.class);
215
216 ExamplePlugin plugin = (ExamplePlugin) config.getInterceptors().get(0);
217 assertThat(plugin.getProperties().size()).isEqualTo(1);
218 assertThat(plugin.getProperties().getProperty("pluginProperty")).isEqualTo("100");
219
220 Environment environment = config.getEnvironment();
221 assertThat(environment.getId()).isEqualTo("development");
222 assertThat(environment.getDataSource()).isInstanceOf(UnpooledDataSource.class);
223 assertThat(environment.getTransactionFactory()).isInstanceOf(JdbcTransactionFactory.class);
224
225 assertThat(config.getDatabaseId()).isEqualTo("derby");
226
227 assertThat(config.getMapperRegistry().getMappers().size()).isEqualTo(4);
228 assertThat(config.getMapperRegistry().hasMapper(CachedAuthorMapper.class)).isTrue();
229 assertThat(config.getMapperRegistry().hasMapper(CustomMapper.class)).isTrue();
230 assertThat(config.getMapperRegistry().hasMapper(BlogMapper.class)).isTrue();
231 assertThat(config.getMapperRegistry().hasMapper(NestedBlogMapper.class)).isTrue();
232 }
233 }
234
235 @Test
236 void shouldSuccessfullyLoadXMLConfigFileWithPropertiesUrl() throws Exception {
237 String resource = "org/apache/ibatis/builder/PropertiesUrlMapperConfig.xml";
238 try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
239 XMLConfigBuilder builder = new XMLConfigBuilder(inputStream);
240 Configuration config = builder.parse();
241 assertThat(config.getVariables().get("driver").toString()).isEqualTo("org.apache.derby.jdbc.EmbeddedDriver");
242 assertThat(config.getVariables().get("prop1").toString()).isEqualTo("bbbb");
243 }
244 }
245
246 @Test
247 void parseIsTwice() throws Exception {
248 String resource = "org/apache/ibatis/builder/MinimalMapperConfig.xml";
249 try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
250 XMLConfigBuilder builder = new XMLConfigBuilder(inputStream);
251 builder.parse();
252
253 when(builder::parse);
254 then(caughtException()).isInstanceOf(BuilderException.class)
255 .hasMessage("Each XMLConfigBuilder can only be used once.");
256 }
257 }
258
259 @Test
260 void unknownSettings() {
261 final String MAPPER_CONFIG = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
262 + "<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n"
263 + "<configuration>\n"
264 + " <settings>\n"
265 + " <setting name=\"foo\" value=\"bar\"/>\n"
266 + " </settings>\n"
267 + "</configuration>\n";
268
269 XMLConfigBuilder builder = new XMLConfigBuilder(new StringReader(MAPPER_CONFIG));
270 when(builder::parse);
271 then(caughtException()).isInstanceOf(BuilderException.class)
272 .hasMessageContaining("The setting foo is not known. Make sure you spelled it correctly (case sensitive).");
273 }
274
275 @Test
276 void unknownJavaTypeOnTypeHandler() {
277 final String MAPPER_CONFIG = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
278 + "<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n"
279 + "<configuration>\n"
280 + " <typeAliases>\n"
281 + " <typeAlias type=\"a.b.c.Foo\"/>\n"
282 + " </typeAliases>\n"
283 + "</configuration>\n";
284
285 XMLConfigBuilder builder = new XMLConfigBuilder(new StringReader(MAPPER_CONFIG));
286 when(builder::parse);
287 then(caughtException()).isInstanceOf(BuilderException.class)
288 .hasMessageContaining("Error registering typeAlias for 'null'. Cause: ");
289 }
290
291 @Test
292 void propertiesSpecifyResourceAndUrlAtSameTime() {
293 final String MAPPER_CONFIG = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
294 + "<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n"
295 + "<configuration>\n"
296 + " <properties resource=\"a/b/c/foo.properties\" url=\"file:./a/b/c/jdbc.properties\"/>\n"
297 + "</configuration>\n";
298
299 XMLConfigBuilder builder = new XMLConfigBuilder(new StringReader(MAPPER_CONFIG));
300 when(builder::parse);
301 then(caughtException()).isInstanceOf(BuilderException.class)
302 .hasMessageContaining("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.");
303 }
304
305 }