Json处理器支持自定义XML.
This commit is contained in:
parent
a1a273df92
commit
2381495af9
@ -28,11 +28,9 @@ import org.apache.ibatis.binding.MapperMethod;
|
|||||||
import org.apache.ibatis.builder.BuilderException;
|
import org.apache.ibatis.builder.BuilderException;
|
||||||
import org.apache.ibatis.builder.CacheRefResolver;
|
import org.apache.ibatis.builder.CacheRefResolver;
|
||||||
import org.apache.ibatis.builder.IncompleteElementException;
|
import org.apache.ibatis.builder.IncompleteElementException;
|
||||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
|
||||||
import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
|
import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
|
||||||
import org.apache.ibatis.builder.annotation.MethodResolver;
|
import org.apache.ibatis.builder.annotation.MethodResolver;
|
||||||
import org.apache.ibatis.builder.annotation.ProviderSqlSource;
|
import org.apache.ibatis.builder.annotation.ProviderSqlSource;
|
||||||
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
|
|
||||||
import org.apache.ibatis.cursor.Cursor;
|
import org.apache.ibatis.cursor.Cursor;
|
||||||
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
|
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
|
||||||
import org.apache.ibatis.executor.keygen.KeyGenerator;
|
import org.apache.ibatis.executor.keygen.KeyGenerator;
|
||||||
@ -77,13 +75,13 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
private final Configuration configuration;
|
private final Configuration configuration;
|
||||||
private final MapperBuilderAssistant assistant;
|
private final MybatisMapperBuilderAssistant assistant;
|
||||||
private final Class<?> type;
|
private final Class<?> type;
|
||||||
|
|
||||||
public MybatisMapperAnnotationBuilder(Configuration configuration, Class<?> type) {
|
public MybatisMapperAnnotationBuilder(Configuration configuration, Class<?> type) {
|
||||||
super(configuration, type);
|
super(configuration, type);
|
||||||
String resource = type.getName().replace(StringPool.DOT, StringPool.SLASH) + ".java (best guess)";
|
String resource = type.getName().replace(StringPool.DOT, StringPool.SLASH) + ".java (best guess)";
|
||||||
this.assistant = new MapperBuilderAssistant(configuration, resource);
|
this.assistant = new MybatisMapperBuilderAssistant(configuration, resource);
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
@ -167,7 +165,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inputStream != null) {
|
if (inputStream != null) {
|
||||||
XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
|
MybatisXMLMapperBuilder xmlParser = new MybatisXMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
|
||||||
xmlParser.parse();
|
xmlParser.parse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011-2023, baomidou (jobob@qq.com).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.baomidou.mybatisplus.core;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.MybatisUtils;
|
||||||
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||||
|
import org.apache.ibatis.mapping.ResultFlag;
|
||||||
|
import org.apache.ibatis.mapping.ResultMapping;
|
||||||
|
import org.apache.ibatis.reflection.MetaClass;
|
||||||
|
import org.apache.ibatis.session.Configuration;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
import org.apache.ibatis.type.TypeHandler;
|
||||||
|
import org.apache.ibatis.type.UnknownTypeHandler;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写了原生方法.
|
||||||
|
*
|
||||||
|
* @author nieqiurong
|
||||||
|
* @see MapperBuilderAssistant
|
||||||
|
* @since 3.5.6
|
||||||
|
*/
|
||||||
|
public class MybatisMapperBuilderAssistant extends MapperBuilderAssistant {
|
||||||
|
|
||||||
|
public MybatisMapperBuilderAssistant(Configuration configuration, String resource) {
|
||||||
|
super(configuration, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultMapping buildResultMapping(Class<?> resultType, String property, String column, Class<?> javaType,
|
||||||
|
JdbcType jdbcType, String nestedSelect, String nestedResultMap, String notNullColumn, String columnPrefix,
|
||||||
|
Class<? extends TypeHandler<?>> typeHandler, List<ResultFlag> flags, String resultSet, String foreignColumn,
|
||||||
|
boolean lazy) {
|
||||||
|
Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);
|
||||||
|
TypeHandler<?> typeHandlerInstance = null;
|
||||||
|
if (typeHandler != null && typeHandler != UnknownTypeHandler.class) {
|
||||||
|
if (IJsonTypeHandler.class.isAssignableFrom(typeHandler)) {
|
||||||
|
try {
|
||||||
|
Field field = resultType.getDeclaredField(property);
|
||||||
|
typeHandlerInstance = MybatisUtils.newJsonTypeHandler(typeHandler, javaTypeClass, field);
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
//ignore 降级兼容处理
|
||||||
|
typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<ResultMapping> composites;
|
||||||
|
if ((nestedSelect == null || nestedSelect.isEmpty()) && (foreignColumn == null || foreignColumn.isEmpty())) {
|
||||||
|
composites = Collections.emptyList();
|
||||||
|
} else {
|
||||||
|
composites = parseCompositeColumnName(column);
|
||||||
|
}
|
||||||
|
return new ResultMapping.Builder(configuration, property, column, javaTypeClass).jdbcType(jdbcType)
|
||||||
|
.nestedQueryId(applyCurrentNamespace(nestedSelect, true))
|
||||||
|
.nestedResultMapId(applyCurrentNamespace(nestedResultMap, true)).resultSet(resultSet)
|
||||||
|
.typeHandler(typeHandlerInstance).flags(flags == null ? new ArrayList<>() : flags).composites(composites)
|
||||||
|
.notNullColumns(parseMultipleColumnNames(notNullColumn)).columnPrefix(columnPrefix).foreignColumn(foreignColumn)
|
||||||
|
.lazy(lazy).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Set<String> parseMultipleColumnNames(String columnName) {
|
||||||
|
Set<String> columns = new HashSet<>();
|
||||||
|
if (columnName != null) {
|
||||||
|
if (columnName.indexOf(',') > -1) {
|
||||||
|
StringTokenizer parser = new StringTokenizer(columnName, "{}, ", false);
|
||||||
|
while (parser.hasMoreTokens()) {
|
||||||
|
String column = parser.nextToken();
|
||||||
|
columns.add(column);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
columns.add(columnName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<ResultMapping> parseCompositeColumnName(String columnName) {
|
||||||
|
List<ResultMapping> composites = new ArrayList<>();
|
||||||
|
if (columnName != null && (columnName.indexOf('=') > -1 || columnName.indexOf(',') > -1)) {
|
||||||
|
StringTokenizer parser = new StringTokenizer(columnName, "{}=, ", false);
|
||||||
|
while (parser.hasMoreTokens()) {
|
||||||
|
String property = parser.nextToken();
|
||||||
|
String column = parser.nextToken();
|
||||||
|
ResultMapping complexResultMapping = new ResultMapping.Builder(configuration, property, column,
|
||||||
|
configuration.getTypeHandlerRegistry().getUnknownTypeHandler()).build();
|
||||||
|
composites.add(complexResultMapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return composites;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class<?> resolveResultJavaType(Class<?> resultType, String property, Class<?> javaType) {
|
||||||
|
if (javaType == null && property != null) {
|
||||||
|
try {
|
||||||
|
MetaClass metaResultType = MetaClass.forClass(resultType, configuration.getReflectorFactory());
|
||||||
|
javaType = metaResultType.getSetterType(property);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore, following null check statement will deal with the situation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (javaType == null) {
|
||||||
|
javaType = Object.class;
|
||||||
|
}
|
||||||
|
return javaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -18,7 +18,6 @@ package com.baomidou.mybatisplus.core;
|
|||||||
import org.apache.ibatis.builder.BaseBuilder;
|
import org.apache.ibatis.builder.BaseBuilder;
|
||||||
import org.apache.ibatis.builder.BuilderException;
|
import org.apache.ibatis.builder.BuilderException;
|
||||||
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
|
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
|
||||||
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
|
|
||||||
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
|
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
|
||||||
import org.apache.ibatis.datasource.DataSourceFactory;
|
import org.apache.ibatis.datasource.DataSourceFactory;
|
||||||
import org.apache.ibatis.executor.ErrorContext;
|
import org.apache.ibatis.executor.ErrorContext;
|
||||||
@ -377,13 +376,13 @@ public class MybatisXMLConfigBuilder extends BaseBuilder {
|
|||||||
if (resource != null && url == null && mapperClass == null) {
|
if (resource != null && url == null && mapperClass == null) {
|
||||||
ErrorContext.instance().resource(resource);
|
ErrorContext.instance().resource(resource);
|
||||||
try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
|
try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
|
||||||
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
|
MybatisXMLMapperBuilder mapperParser = new MybatisXMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
|
||||||
mapperParser.parse();
|
mapperParser.parse();
|
||||||
}
|
}
|
||||||
} else if (resource == null && url != null && mapperClass == null) {
|
} else if (resource == null && url != null && mapperClass == null) {
|
||||||
ErrorContext.instance().resource(url);
|
ErrorContext.instance().resource(url);
|
||||||
try (InputStream inputStream = Resources.getUrlAsStream(url)) {
|
try (InputStream inputStream = Resources.getUrlAsStream(url)) {
|
||||||
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
|
MybatisXMLMapperBuilder mapperParser = new MybatisXMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
|
||||||
mapperParser.parse();
|
mapperParser.parse();
|
||||||
}
|
}
|
||||||
} else if (resource == null && url == null && mapperClass != null) {
|
} else if (resource == null && url == null && mapperClass != null) {
|
||||||
|
@ -0,0 +1,451 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011-2023, baomidou (jobob@qq.com).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.baomidou.mybatisplus.core;
|
||||||
|
|
||||||
|
import org.apache.ibatis.builder.BaseBuilder;
|
||||||
|
import org.apache.ibatis.builder.BuilderException;
|
||||||
|
import org.apache.ibatis.builder.CacheRefResolver;
|
||||||
|
import org.apache.ibatis.builder.IncompleteElementException;
|
||||||
|
import org.apache.ibatis.builder.ResultMapResolver;
|
||||||
|
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
|
||||||
|
import org.apache.ibatis.builder.xml.XMLStatementBuilder;
|
||||||
|
import org.apache.ibatis.cache.Cache;
|
||||||
|
import org.apache.ibatis.executor.ErrorContext;
|
||||||
|
import org.apache.ibatis.io.Resources;
|
||||||
|
import org.apache.ibatis.mapping.Discriminator;
|
||||||
|
import org.apache.ibatis.mapping.ParameterMapping;
|
||||||
|
import org.apache.ibatis.mapping.ParameterMode;
|
||||||
|
import org.apache.ibatis.mapping.ResultFlag;
|
||||||
|
import org.apache.ibatis.mapping.ResultMap;
|
||||||
|
import org.apache.ibatis.mapping.ResultMapping;
|
||||||
|
import org.apache.ibatis.parsing.XNode;
|
||||||
|
import org.apache.ibatis.parsing.XPathParser;
|
||||||
|
import org.apache.ibatis.reflection.MetaClass;
|
||||||
|
import org.apache.ibatis.session.Configuration;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
import org.apache.ibatis.type.TypeHandler;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写了{@link org.apache.ibatis.builder.xml.XMLMapperBuilder} 替换了 {@link org.apache.ibatis.builder.MapperBuilderAssistant}
|
||||||
|
*
|
||||||
|
* @author nieqiurong
|
||||||
|
* @since 3.5.6
|
||||||
|
*/
|
||||||
|
public class MybatisXMLMapperBuilder extends BaseBuilder {
|
||||||
|
|
||||||
|
private final XPathParser parser;
|
||||||
|
private final MybatisMapperBuilderAssistant builderAssistant;
|
||||||
|
private final Map<String, XNode> sqlFragments;
|
||||||
|
private final String resource;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public MybatisXMLMapperBuilder(Reader reader, Configuration configuration, String resource, Map<String, XNode> sqlFragments,
|
||||||
|
String namespace) {
|
||||||
|
this(reader, configuration, resource, sqlFragments);
|
||||||
|
this.builderAssistant.setCurrentNamespace(namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public MybatisXMLMapperBuilder(Reader reader, Configuration configuration, String resource,
|
||||||
|
Map<String, XNode> sqlFragments) {
|
||||||
|
this(new XPathParser(reader, true, configuration.getVariables(), new XMLMapperEntityResolver()), configuration,
|
||||||
|
resource, sqlFragments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MybatisXMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource,
|
||||||
|
Map<String, XNode> sqlFragments, String namespace) {
|
||||||
|
this(inputStream, configuration, resource, sqlFragments);
|
||||||
|
this.builderAssistant.setCurrentNamespace(namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MybatisXMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource,
|
||||||
|
Map<String, XNode> sqlFragments) {
|
||||||
|
this(new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver()), configuration,
|
||||||
|
resource, sqlFragments);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MybatisXMLMapperBuilder(XPathParser parser, Configuration configuration, String resource,
|
||||||
|
Map<String, XNode> sqlFragments) {
|
||||||
|
super(configuration);
|
||||||
|
this.builderAssistant = new MybatisMapperBuilderAssistant(configuration, resource);
|
||||||
|
this.parser = parser;
|
||||||
|
this.sqlFragments = sqlFragments;
|
||||||
|
this.resource = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse() {
|
||||||
|
if (!configuration.isResourceLoaded(resource)) {
|
||||||
|
configurationElement(parser.evalNode("/mapper"));
|
||||||
|
configuration.addLoadedResource(resource);
|
||||||
|
bindMapperForNamespace();
|
||||||
|
}
|
||||||
|
parsePendingResultMaps();
|
||||||
|
parsePendingCacheRefs();
|
||||||
|
parsePendingStatements();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XNode getSqlFragment(String refid) {
|
||||||
|
return sqlFragments.get(refid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configurationElement(XNode context) {
|
||||||
|
try {
|
||||||
|
String namespace = context.getStringAttribute("namespace");
|
||||||
|
if (namespace == null || namespace.isEmpty()) {
|
||||||
|
throw new BuilderException("Mapper's namespace cannot be empty");
|
||||||
|
}
|
||||||
|
builderAssistant.setCurrentNamespace(namespace);
|
||||||
|
cacheRefElement(context.evalNode("cache-ref"));
|
||||||
|
cacheElement(context.evalNode("cache"));
|
||||||
|
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
|
||||||
|
resultMapElements(context.evalNodes("/mapper/resultMap"));
|
||||||
|
sqlElement(context.evalNodes("/mapper/sql"));
|
||||||
|
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildStatementFromContext(List<XNode> list) {
|
||||||
|
if (configuration.getDatabaseId() != null) {
|
||||||
|
buildStatementFromContext(list, configuration.getDatabaseId());
|
||||||
|
}
|
||||||
|
buildStatementFromContext(list, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
|
||||||
|
for (XNode context : list) {
|
||||||
|
final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context,
|
||||||
|
requiredDatabaseId);
|
||||||
|
try {
|
||||||
|
statementParser.parseStatementNode();
|
||||||
|
} catch (IncompleteElementException e) {
|
||||||
|
configuration.addIncompleteStatement(statementParser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parsePendingResultMaps() {
|
||||||
|
Collection<ResultMapResolver> incompleteResultMaps = configuration.getIncompleteResultMaps();
|
||||||
|
synchronized (incompleteResultMaps) {
|
||||||
|
Iterator<ResultMapResolver> iter = incompleteResultMaps.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
try {
|
||||||
|
iter.next().resolve();
|
||||||
|
iter.remove();
|
||||||
|
} catch (IncompleteElementException e) {
|
||||||
|
// ResultMap is still missing a resource...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parsePendingCacheRefs() {
|
||||||
|
Collection<CacheRefResolver> incompleteCacheRefs = configuration.getIncompleteCacheRefs();
|
||||||
|
synchronized (incompleteCacheRefs) {
|
||||||
|
Iterator<CacheRefResolver> iter = incompleteCacheRefs.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
try {
|
||||||
|
iter.next().resolveCacheRef();
|
||||||
|
iter.remove();
|
||||||
|
} catch (IncompleteElementException e) {
|
||||||
|
// Cache ref is still missing a resource...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parsePendingStatements() {
|
||||||
|
Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements();
|
||||||
|
synchronized (incompleteStatements) {
|
||||||
|
Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
try {
|
||||||
|
iter.next().parseStatementNode();
|
||||||
|
iter.remove();
|
||||||
|
} catch (IncompleteElementException e) {
|
||||||
|
// Statement is still missing a resource...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cacheRefElement(XNode context) {
|
||||||
|
if (context != null) {
|
||||||
|
configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
|
||||||
|
CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant,
|
||||||
|
context.getStringAttribute("namespace"));
|
||||||
|
try {
|
||||||
|
cacheRefResolver.resolveCacheRef();
|
||||||
|
} catch (IncompleteElementException e) {
|
||||||
|
configuration.addIncompleteCacheRef(cacheRefResolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cacheElement(XNode context) {
|
||||||
|
if (context != null) {
|
||||||
|
String type = context.getStringAttribute("type", "PERPETUAL");
|
||||||
|
Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
|
||||||
|
String eviction = context.getStringAttribute("eviction", "LRU");
|
||||||
|
Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
|
||||||
|
Long flushInterval = context.getLongAttribute("flushInterval");
|
||||||
|
Integer size = context.getIntAttribute("size");
|
||||||
|
boolean readWrite = !context.getBooleanAttribute("readOnly", false);
|
||||||
|
boolean blocking = context.getBooleanAttribute("blocking", false);
|
||||||
|
Properties props = context.getChildrenAsProperties();
|
||||||
|
builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parameterMapElement(List<XNode> list) {
|
||||||
|
for (XNode parameterMapNode : list) {
|
||||||
|
String id = parameterMapNode.getStringAttribute("id");
|
||||||
|
String type = parameterMapNode.getStringAttribute("type");
|
||||||
|
Class<?> parameterClass = resolveClass(type);
|
||||||
|
List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
|
||||||
|
List<ParameterMapping> parameterMappings = new ArrayList<>();
|
||||||
|
for (XNode parameterNode : parameterNodes) {
|
||||||
|
String property = parameterNode.getStringAttribute("property");
|
||||||
|
String javaType = parameterNode.getStringAttribute("javaType");
|
||||||
|
String jdbcType = parameterNode.getStringAttribute("jdbcType");
|
||||||
|
String resultMap = parameterNode.getStringAttribute("resultMap");
|
||||||
|
String mode = parameterNode.getStringAttribute("mode");
|
||||||
|
String typeHandler = parameterNode.getStringAttribute("typeHandler");
|
||||||
|
Integer numericScale = parameterNode.getIntAttribute("numericScale");
|
||||||
|
ParameterMode modeEnum = resolveParameterMode(mode);
|
||||||
|
Class<?> javaTypeClass = resolveClass(javaType);
|
||||||
|
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
|
||||||
|
Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
|
||||||
|
ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property,
|
||||||
|
javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
|
||||||
|
parameterMappings.add(parameterMapping);
|
||||||
|
}
|
||||||
|
builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resultMapElements(List<XNode> list) {
|
||||||
|
for (XNode resultMapNode : list) {
|
||||||
|
try {
|
||||||
|
resultMapElement(resultMapNode);
|
||||||
|
} catch (IncompleteElementException e) {
|
||||||
|
// ignore, it will be retried
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultMap resultMapElement(XNode resultMapNode) {
|
||||||
|
return resultMapElement(resultMapNode, Collections.emptyList(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings,
|
||||||
|
Class<?> enclosingType) {
|
||||||
|
ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
|
||||||
|
String type = resultMapNode.getStringAttribute("type", resultMapNode.getStringAttribute("ofType",
|
||||||
|
resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType"))));
|
||||||
|
Class<?> typeClass = resolveClass(type);
|
||||||
|
if (typeClass == null) {
|
||||||
|
typeClass = inheritEnclosingType(resultMapNode, enclosingType);
|
||||||
|
}
|
||||||
|
Discriminator discriminator = null;
|
||||||
|
List<ResultMapping> resultMappings = new ArrayList<>(additionalResultMappings);
|
||||||
|
List<XNode> resultChildren = resultMapNode.getChildren();
|
||||||
|
for (XNode resultChild : resultChildren) {
|
||||||
|
if ("constructor".equals(resultChild.getName())) {
|
||||||
|
processConstructorElement(resultChild, typeClass, resultMappings);
|
||||||
|
} else if ("discriminator".equals(resultChild.getName())) {
|
||||||
|
discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
|
||||||
|
} else {
|
||||||
|
List<ResultFlag> flags = new ArrayList<>();
|
||||||
|
if ("id".equals(resultChild.getName())) {
|
||||||
|
flags.add(ResultFlag.ID);
|
||||||
|
}
|
||||||
|
resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
|
||||||
|
String extend = resultMapNode.getStringAttribute("extends");
|
||||||
|
Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
|
||||||
|
ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator,
|
||||||
|
resultMappings, autoMapping);
|
||||||
|
try {
|
||||||
|
return resultMapResolver.resolve();
|
||||||
|
} catch (IncompleteElementException e) {
|
||||||
|
configuration.addIncompleteResultMap(resultMapResolver);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?> inheritEnclosingType(XNode resultMapNode, Class<?> enclosingType) {
|
||||||
|
if ("association".equals(resultMapNode.getName()) && resultMapNode.getStringAttribute("resultMap") == null) {
|
||||||
|
String property = resultMapNode.getStringAttribute("property");
|
||||||
|
if (property != null && enclosingType != null) {
|
||||||
|
MetaClass metaResultType = MetaClass.forClass(enclosingType, configuration.getReflectorFactory());
|
||||||
|
return metaResultType.getSetterType(property);
|
||||||
|
}
|
||||||
|
} else if ("case".equals(resultMapNode.getName()) && resultMapNode.getStringAttribute("resultMap") == null) {
|
||||||
|
return enclosingType;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) {
|
||||||
|
List<XNode> argChildren = resultChild.getChildren();
|
||||||
|
for (XNode argChild : argChildren) {
|
||||||
|
List<ResultFlag> flags = new ArrayList<>();
|
||||||
|
flags.add(ResultFlag.CONSTRUCTOR);
|
||||||
|
if ("idArg".equals(argChild.getName())) {
|
||||||
|
flags.add(ResultFlag.ID);
|
||||||
|
}
|
||||||
|
resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType,
|
||||||
|
List<ResultMapping> resultMappings) {
|
||||||
|
String column = context.getStringAttribute("column");
|
||||||
|
String javaType = context.getStringAttribute("javaType");
|
||||||
|
String jdbcType = context.getStringAttribute("jdbcType");
|
||||||
|
String typeHandler = context.getStringAttribute("typeHandler");
|
||||||
|
Class<?> javaTypeClass = resolveClass(javaType);
|
||||||
|
Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
|
||||||
|
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
|
||||||
|
Map<String, String> discriminatorMap = new HashMap<>();
|
||||||
|
for (XNode caseChild : context.getChildren()) {
|
||||||
|
String value = caseChild.getStringAttribute("value");
|
||||||
|
String resultMap = caseChild.getStringAttribute("resultMap",
|
||||||
|
processNestedResultMappings(caseChild, resultMappings, resultType));
|
||||||
|
discriminatorMap.put(value, resultMap);
|
||||||
|
}
|
||||||
|
return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass,
|
||||||
|
discriminatorMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sqlElement(List<XNode> list) {
|
||||||
|
if (configuration.getDatabaseId() != null) {
|
||||||
|
sqlElement(list, configuration.getDatabaseId());
|
||||||
|
}
|
||||||
|
sqlElement(list, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sqlElement(List<XNode> list, String requiredDatabaseId) {
|
||||||
|
for (XNode context : list) {
|
||||||
|
String databaseId = context.getStringAttribute("databaseId");
|
||||||
|
String id = context.getStringAttribute("id");
|
||||||
|
id = builderAssistant.applyCurrentNamespace(id, false);
|
||||||
|
if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
|
||||||
|
sqlFragments.put(id, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) {
|
||||||
|
if (requiredDatabaseId != null) {
|
||||||
|
return requiredDatabaseId.equals(databaseId);
|
||||||
|
}
|
||||||
|
if (databaseId != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.sqlFragments.containsKey(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// skip this fragment if there is a previous one with a not null databaseId
|
||||||
|
XNode context = this.sqlFragments.get(id);
|
||||||
|
return context.getStringAttribute("databaseId") == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) {
|
||||||
|
String property;
|
||||||
|
if (flags.contains(ResultFlag.CONSTRUCTOR)) {
|
||||||
|
property = context.getStringAttribute("name");
|
||||||
|
} else {
|
||||||
|
property = context.getStringAttribute("property");
|
||||||
|
}
|
||||||
|
String column = context.getStringAttribute("column");
|
||||||
|
String javaType = context.getStringAttribute("javaType");
|
||||||
|
String jdbcType = context.getStringAttribute("jdbcType");
|
||||||
|
String nestedSelect = context.getStringAttribute("select");
|
||||||
|
String nestedResultMap = context.getStringAttribute("resultMap",
|
||||||
|
() -> processNestedResultMappings(context, Collections.emptyList(), resultType));
|
||||||
|
String notNullColumn = context.getStringAttribute("notNullColumn");
|
||||||
|
String columnPrefix = context.getStringAttribute("columnPrefix");
|
||||||
|
String typeHandler = context.getStringAttribute("typeHandler");
|
||||||
|
String resultSet = context.getStringAttribute("resultSet");
|
||||||
|
String foreignColumn = context.getStringAttribute("foreignColumn");
|
||||||
|
boolean lazy = "lazy"
|
||||||
|
.equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
|
||||||
|
Class<?> javaTypeClass = resolveClass(javaType);
|
||||||
|
Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
|
||||||
|
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
|
||||||
|
return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect,
|
||||||
|
nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet, foreignColumn, lazy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String processNestedResultMappings(XNode context, List<ResultMapping> resultMappings,
|
||||||
|
Class<?> enclosingType) {
|
||||||
|
if (Arrays.asList("association", "collection", "case").contains(context.getName())
|
||||||
|
&& context.getStringAttribute("select") == null) {
|
||||||
|
validateCollection(context, enclosingType);
|
||||||
|
ResultMap resultMap = resultMapElement(context, resultMappings, enclosingType);
|
||||||
|
return resultMap.getId();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateCollection(XNode context, Class<?> enclosingType) {
|
||||||
|
if ("collection".equals(context.getName()) && context.getStringAttribute("resultMap") == null
|
||||||
|
&& context.getStringAttribute("javaType") == null) {
|
||||||
|
MetaClass metaResultType = MetaClass.forClass(enclosingType, configuration.getReflectorFactory());
|
||||||
|
String property = context.getStringAttribute("property");
|
||||||
|
if (!metaResultType.hasSetter(property)) {
|
||||||
|
throw new BuilderException(
|
||||||
|
"Ambiguous collection type for property '" + property + "'. You must specify 'javaType' or 'resultMap'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindMapperForNamespace() {
|
||||||
|
String namespace = builderAssistant.getCurrentNamespace();
|
||||||
|
if (namespace != null) {
|
||||||
|
Class<?> boundType = null;
|
||||||
|
try {
|
||||||
|
boundType = Resources.classForName(namespace);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// ignore, bound type is not required
|
||||||
|
}
|
||||||
|
if (boundType != null && !configuration.hasMapper(boundType)) {
|
||||||
|
// Spring may not know the real resource name so we set a flag
|
||||||
|
// to prevent loading again this resource from the mapper interface
|
||||||
|
// look at MapperAnnotationBuilder#loadXmlResource
|
||||||
|
configuration.addLoadedResource("namespace:" + namespace);
|
||||||
|
configuration.addMapper(boundType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,9 +19,13 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Json类型处理器接口(实现类确保为多例状态).
|
* Json类型处理器接口(实现类确保为多例状态).
|
||||||
|
* <p>
|
||||||
|
* 注意:查询返回时需要使用resultMap
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @author nieqiurong 2024年3月4日
|
* @author nieqiurong 2024年3月4日
|
||||||
* @see TableName#autoResultMap()
|
* @see TableName#autoResultMap() 自动构建
|
||||||
|
* @see TableName#resultMap() 手动指定
|
||||||
* @since 3.5.6
|
* @since 3.5.6
|
||||||
*/
|
*/
|
||||||
public interface IJsonTypeHandler<T> {
|
public interface IJsonTypeHandler<T> {
|
||||||
|
@ -25,6 +25,7 @@ import com.baomidou.mybatisplus.annotation.Version;
|
|||||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||||
import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
|
import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.MybatisUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
|
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
@ -563,12 +564,7 @@ public class TableFieldInfo implements Constants {
|
|||||||
TypeHandler<?> typeHandler = registry.getMappingTypeHandler(this.typeHandler);
|
TypeHandler<?> typeHandler = registry.getMappingTypeHandler(this.typeHandler);
|
||||||
if (IJsonTypeHandler.class.isAssignableFrom(this.typeHandler)) {
|
if (IJsonTypeHandler.class.isAssignableFrom(this.typeHandler)) {
|
||||||
// 保证每次实例化
|
// 保证每次实例化
|
||||||
try {
|
typeHandler = MybatisUtils.newJsonTypeHandler(this.typeHandler, this.propertyType, this.field);
|
||||||
//TODO 后面想一下怎么支持原生的方式,目前只支持自动生成的情况.
|
|
||||||
typeHandler = this.typeHandler.getDeclaredConstructor(Class.class, Field.class).newInstance(this.propertyType, this.field);
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (typeHandler == null) {
|
if (typeHandler == null) {
|
||||||
typeHandler = registry.getInstance(this.propertyType, this.typeHandler);
|
typeHandler = registry.getInstance(this.propertyType, this.typeHandler);
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.baomidou.mybatisplus.core.toolkit;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.ibatis.type.TypeException;
|
||||||
|
import org.apache.ibatis.type.TypeHandler;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author nieqiurong
|
||||||
|
* @since 3.5.6
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@UtilityClass
|
||||||
|
public class MybatisUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化Json类型处理器
|
||||||
|
* <p>
|
||||||
|
* 1.子类需要包含构造(Class,Field)
|
||||||
|
* 2.如果无上述构造或者无属性字段,则使用默认构造(Class)进行实例化
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param typeHandler 类型处理器 {@link IJsonTypeHandler}
|
||||||
|
* @param javaTypeClass java类型信息
|
||||||
|
* @param field 属性字段
|
||||||
|
* @return 实例化类型处理器
|
||||||
|
*/
|
||||||
|
public static TypeHandler<?> newJsonTypeHandler(Class<? extends TypeHandler<?>> typeHandler, Class<?> javaTypeClass, Field field) {
|
||||||
|
TypeHandler<?> result = null;
|
||||||
|
if (IJsonTypeHandler.class.isAssignableFrom(typeHandler)) {
|
||||||
|
if (field != null) {
|
||||||
|
try {
|
||||||
|
result = typeHandler.getConstructor(Class.class, Field.class).newInstance(javaTypeClass, field);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == null) {
|
||||||
|
try {
|
||||||
|
result = typeHandler.getConstructor(Class.class).newInstance(javaTypeClass);
|
||||||
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
throw new TypeException("Failed invoking constructor for handler " + typeHandler, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,11 +19,11 @@ import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
|||||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||||
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
|
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
|
||||||
import com.baomidou.mybatisplus.core.MybatisXMLConfigBuilder;
|
import com.baomidou.mybatisplus.core.MybatisXMLConfigBuilder;
|
||||||
|
import com.baomidou.mybatisplus.core.MybatisXMLMapperBuilder;
|
||||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
|
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
|
||||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
|
|
||||||
import org.apache.ibatis.cache.Cache;
|
import org.apache.ibatis.cache.Cache;
|
||||||
import org.apache.ibatis.executor.ErrorContext;
|
import org.apache.ibatis.executor.ErrorContext;
|
||||||
import org.apache.ibatis.io.Resources;
|
import org.apache.ibatis.io.Resources;
|
||||||
@ -557,7 +557,7 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
|
MybatisXMLMapperBuilder xmlMapperBuilder = new MybatisXMLMapperBuilder(mapperLocation.getInputStream(),
|
||||||
targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
|
targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
|
||||||
xmlMapperBuilder.parse();
|
xmlMapperBuilder.parse();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -2,13 +2,13 @@ package com.baomidou.mybatisplus.test.kotlin
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.MybatisConfiguration
|
import com.baomidou.mybatisplus.core.MybatisConfiguration
|
||||||
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder
|
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder
|
||||||
|
import com.baomidou.mybatisplus.core.MybatisXMLMapperBuilder
|
||||||
import com.baomidou.mybatisplus.core.config.GlobalConfig
|
import com.baomidou.mybatisplus.core.config.GlobalConfig
|
||||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils
|
||||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils
|
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils
|
||||||
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils
|
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils
|
||||||
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner
|
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner
|
||||||
import org.apache.ibatis.builder.xml.XMLMapperBuilder
|
|
||||||
import org.apache.ibatis.io.Resources
|
import org.apache.ibatis.io.Resources
|
||||||
import org.apache.ibatis.logging.slf4j.Slf4jImpl
|
import org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||||
import org.apache.ibatis.mapping.Environment
|
import org.apache.ibatis.mapping.Environment
|
||||||
@ -65,7 +65,7 @@ abstract class BaseDbTest<T> : TypeReference<T>() {
|
|||||||
if (StringUtils.isNotBlank(mapperXml)) {
|
if (StringUtils.isNotBlank(mapperXml)) {
|
||||||
try {
|
try {
|
||||||
val inputStream = Resources.getResourceAsStream(mapperXml)
|
val inputStream = Resources.getResourceAsStream(mapperXml)
|
||||||
val xmlMapperBuilder = XMLMapperBuilder(
|
val xmlMapperBuilder = MybatisXMLMapperBuilder(
|
||||||
inputStream,
|
inputStream,
|
||||||
configuration, mapperXml, configuration.sqlFragments
|
configuration, mapperXml, configuration.sqlFragments
|
||||||
)
|
)
|
||||||
|
@ -2,12 +2,12 @@ package com.baomidou.mybatisplus.test;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||||
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
|
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
|
||||||
|
import com.baomidou.mybatisplus.core.MybatisXMLMapperBuilder;
|
||||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
|
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
|
|
||||||
import org.apache.ibatis.io.Resources;
|
import org.apache.ibatis.io.Resources;
|
||||||
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
|
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
|
||||||
import org.apache.ibatis.mapping.Environment;
|
import org.apache.ibatis.mapping.Environment;
|
||||||
@ -73,7 +73,7 @@ public abstract class BaseDbTest<T> extends TypeReference<T> {
|
|||||||
if (StringUtils.isNotBlank(mapperXml)) {
|
if (StringUtils.isNotBlank(mapperXml)) {
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = Resources.getResourceAsStream(mapperXml);
|
InputStream inputStream = Resources.getResourceAsStream(mapperXml);
|
||||||
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(inputStream,
|
MybatisXMLMapperBuilder xmlMapperBuilder = new MybatisXMLMapperBuilder(inputStream,
|
||||||
configuration, mapperXml, configuration.getSqlFragments());
|
configuration, mapperXml, configuration.getSqlFragments());
|
||||||
xmlMapperBuilder.parse();
|
xmlMapperBuilder.parse();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -9,6 +9,8 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author miemie
|
* @author miemie
|
||||||
@ -28,10 +30,30 @@ public class Entity implements Serializable {
|
|||||||
@TableField(typeHandler = GsonTypeHandler.class)
|
@TableField(typeHandler = GsonTypeHandler.class)
|
||||||
private Gg gg2;
|
private Gg gg2;
|
||||||
|
|
||||||
|
@TableField(typeHandler = GsonTypeHandler.class)
|
||||||
|
private List<Gg> gg3;
|
||||||
|
|
||||||
|
@TableField(typeHandler = GsonTypeHandler.class)
|
||||||
|
private List<Gg4> gg4;
|
||||||
|
|
||||||
|
@TableField(typeHandler = GsonTypeHandler.class)
|
||||||
|
private String[] str;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public static class Gg {
|
public static class Gg {
|
||||||
private String name;
|
private String name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Gg4 {
|
||||||
|
private String name;
|
||||||
|
private Gg gg;
|
||||||
|
private List<Gg> ggList;
|
||||||
|
private Map<String,Gg> ggMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ -17,7 +18,11 @@ public class ResultMapTest extends BaseDbTest<EntityMapper> {
|
|||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
doTestAutoCommit(m -> m.insert(new Entity().setGg1(new Entity.Gg("老王"))
|
doTestAutoCommit(m -> m.insert(new Entity().setGg1(new Entity.Gg("老王"))
|
||||||
.setGg2(new Entity.Gg("老李"))));
|
.setStr(new String[]{"hello"})
|
||||||
|
.setGg2(new Entity.Gg("老李"))
|
||||||
|
.setGg3(List.of(new Entity.Gg("老张")))
|
||||||
|
.setGg4(List.of(new Entity.Gg4("秋秋", new Entity.Gg("小红"), List.of(new Entity.Gg("小猫")), Map.of("test", new Entity.Gg("小明")))))
|
||||||
|
));
|
||||||
|
|
||||||
doTest(m -> {
|
doTest(m -> {
|
||||||
Entity entity = m.selectOne(null);
|
Entity entity = m.selectOne(null);
|
||||||
@ -27,6 +32,18 @@ public class ResultMapTest extends BaseDbTest<EntityMapper> {
|
|||||||
|
|
||||||
assertThat(entity.getGg2()).as("typeHandler正常").isNotNull();
|
assertThat(entity.getGg2()).as("typeHandler正常").isNotNull();
|
||||||
assertThat(entity.getGg2().getName()).as("是老李").isEqualTo("老李");
|
assertThat(entity.getGg2().getName()).as("是老李").isEqualTo("老李");
|
||||||
|
|
||||||
|
assertThat(entity.getGg3()).as("typeHandler正常").isNotNull();
|
||||||
|
assertThat(entity.getGg3().getFirst().getName()).as("是老张").isEqualTo("老张");
|
||||||
|
|
||||||
|
assertThat(entity.getGg4()).as("typeHandler正常").isNotNull();
|
||||||
|
assertThat(entity.getGg4().getFirst().getName()).as("是秋秋").isEqualTo("秋秋");
|
||||||
|
assertThat(entity.getGg4().getFirst().getGg().getName()).as("是小红").isEqualTo("小红");
|
||||||
|
assertThat(entity.getGg4().getFirst().getGgList().getFirst().getName()).as("是小猫").isEqualTo("小猫");
|
||||||
|
assertThat(entity.getGg4().getFirst().getGgMap().get("test").getName()).as("是小明").isEqualTo("小明");
|
||||||
|
|
||||||
|
assertThat(entity.getStr()).as("typeHandler正常").isNotNull();
|
||||||
|
assertThat(entity.getStr()[0]).isEqualTo("hello");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +54,9 @@ public class ResultMapTest extends BaseDbTest<EntityMapper> {
|
|||||||
"id BIGINT(20) NOT NULL,\n" +
|
"id BIGINT(20) NOT NULL,\n" +
|
||||||
"gg1 VARCHAR(255) NULL DEFAULT NULL,\n" +
|
"gg1 VARCHAR(255) NULL DEFAULT NULL,\n" +
|
||||||
"gg2 VARCHAR(255) NULL DEFAULT NULL,\n" +
|
"gg2 VARCHAR(255) NULL DEFAULT NULL,\n" +
|
||||||
|
"gg3 VARCHAR(255) NULL DEFAULT NULL,\n" +
|
||||||
|
"gg4 VARCHAR(255) NULL DEFAULT NULL,\n" +
|
||||||
|
"str VARCHAR(255) NULL DEFAULT NULL,\n" +
|
||||||
"PRIMARY KEY (id)" +
|
"PRIMARY KEY (id)" +
|
||||||
")");
|
")");
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,8 @@
|
|||||||
|
|
||||||
<resultMap id="resultMap" type="com.baomidou.mybatisplus.test.resultmap.Entity" extends="baseResult">
|
<resultMap id="resultMap" type="com.baomidou.mybatisplus.test.resultmap.Entity" extends="baseResult">
|
||||||
<result column="gg2" property="gg2" typeHandler="com.baomidou.mybatisplus.extension.handlers.GsonTypeHandler"/>
|
<result column="gg2" property="gg2" typeHandler="com.baomidou.mybatisplus.extension.handlers.GsonTypeHandler"/>
|
||||||
|
<result property="gg3" column="gg3" typeHandler="com.baomidou.mybatisplus.extension.handlers.GsonTypeHandler"/>
|
||||||
|
<result property="gg4" column="gg4" javaType="list" typeHandler="com.baomidou.mybatisplus.extension.handlers.GsonTypeHandler"/>
|
||||||
|
<result property="str" column="str" typeHandler="com.baomidou.mybatisplus.extension.handlers.GsonTypeHandler"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
@ -75,7 +75,7 @@ class GeneratePomTest {
|
|||||||
Dependency bom = dependenciesMap.get("spring-boot-dependencies");
|
Dependency bom = dependenciesMap.get("spring-boot-dependencies");
|
||||||
Assertions.assertEquals("import", bom.getScope());
|
Assertions.assertEquals("import", bom.getScope());
|
||||||
Assertions.assertFalse(bom.isOptional());
|
Assertions.assertFalse(bom.isOptional());
|
||||||
Assertions.assertEquals(dependenciesMap.get("spring-cloud-commons").getVersion(), "3.1.1");
|
Assertions.assertEquals(dependenciesMap.get("spring-cloud-commons").getVersion(), "3.1.8");
|
||||||
Assertions.assertEquals(dependenciesMap.get("mybatis-spring").getVersion(), "2.1.2");
|
Assertions.assertEquals(dependenciesMap.get("mybatis-spring").getVersion(), "2.1.2");
|
||||||
Assertions.assertEquals(dependenciesMap.get("spring-boot-dependencies").getVersion(), "2.7.15");
|
Assertions.assertEquals(dependenciesMap.get("spring-boot-dependencies").getVersion(), "2.7.15");
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class GeneratePomTest {
|
|||||||
Dependency bom = dependenciesMap.get("spring-boot-dependencies");
|
Dependency bom = dependenciesMap.get("spring-boot-dependencies");
|
||||||
Assertions.assertEquals("import", bom.getScope());
|
Assertions.assertEquals("import", bom.getScope());
|
||||||
Assertions.assertFalse(bom.isOptional());
|
Assertions.assertFalse(bom.isOptional());
|
||||||
Assertions.assertEquals(dependenciesMap.get("spring-cloud-commons").getVersion(), "4.0.4");
|
Assertions.assertEquals(dependenciesMap.get("spring-cloud-commons").getVersion(), "4.1.1");
|
||||||
Assertions.assertEquals(dependenciesMap.get("mybatis-spring").getVersion(), "3.0.3");
|
Assertions.assertEquals(dependenciesMap.get("mybatis-spring").getVersion(), "3.0.3");
|
||||||
Assertions.assertEquals(dependenciesMap.get("spring-boot-dependencies").getVersion(), "3.2.0");
|
Assertions.assertEquals(dependenciesMap.get("spring-boot-dependencies").getVersion(), "3.2.0");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user