123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- /**
- * Copyright 2009-2016 the original author or authors.
- * <p>
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Array;
- import java.lang.reflect.GenericArrayType;
- import java.lang.reflect.Method;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Locale;
- import java.util.Map;
- import java.util.Properties;
- import java.util.Set;
- import org.apache.ibatis.annotations.Arg;
- import org.apache.ibatis.annotations.CacheNamespace;
- import org.apache.ibatis.annotations.CacheNamespaceRef;
- import org.apache.ibatis.annotations.Case;
- import org.apache.ibatis.annotations.ConstructorArgs;
- import org.apache.ibatis.annotations.Delete;
- import org.apache.ibatis.annotations.DeleteProvider;
- import org.apache.ibatis.annotations.Insert;
- import org.apache.ibatis.annotations.InsertProvider;
- import org.apache.ibatis.annotations.Lang;
- import org.apache.ibatis.annotations.MapKey;
- import org.apache.ibatis.annotations.Options;
- import org.apache.ibatis.annotations.Options.FlushCachePolicy;
- import org.apache.ibatis.annotations.Property;
- import org.apache.ibatis.annotations.Result;
- import org.apache.ibatis.annotations.ResultMap;
- import org.apache.ibatis.annotations.ResultType;
- import org.apache.ibatis.annotations.Results;
- import org.apache.ibatis.annotations.Select;
- import org.apache.ibatis.annotations.SelectKey;
- import org.apache.ibatis.annotations.SelectProvider;
- import org.apache.ibatis.annotations.TypeDiscriminator;
- import org.apache.ibatis.annotations.Update;
- import org.apache.ibatis.annotations.UpdateProvider;
- import org.apache.ibatis.binding.BindingException;
- import org.apache.ibatis.binding.MapperMethod.ParamMap;
- import org.apache.ibatis.builder.BuilderException;
- 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.MethodResolver;
- import org.apache.ibatis.builder.annotation.ProviderSqlSource;
- import org.apache.ibatis.builder.xml.XMLMapperBuilder;
- import org.apache.ibatis.cursor.Cursor;
- import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
- import org.apache.ibatis.executor.keygen.KeyGenerator;
- import org.apache.ibatis.executor.keygen.NoKeyGenerator;
- import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.mapping.Discriminator;
- import org.apache.ibatis.mapping.FetchType;
- import org.apache.ibatis.mapping.MappedStatement;
- import org.apache.ibatis.mapping.ResultFlag;
- import org.apache.ibatis.mapping.ResultMapping;
- import org.apache.ibatis.mapping.ResultSetType;
- import org.apache.ibatis.mapping.SqlCommandType;
- import org.apache.ibatis.mapping.SqlSource;
- import org.apache.ibatis.mapping.StatementType;
- import org.apache.ibatis.parsing.PropertyParser;
- import org.apache.ibatis.reflection.TypeParameterResolver;
- import org.apache.ibatis.scripting.LanguageDriver;
- import org.apache.ibatis.session.Configuration;
- import org.apache.ibatis.session.ResultHandler;
- import org.apache.ibatis.session.RowBounds;
- import org.apache.ibatis.type.JdbcType;
- import org.apache.ibatis.type.TypeHandler;
- import org.apache.ibatis.type.UnknownTypeHandler;
- import com.baomidou.mybatisplus.entity.GlobalConfiguration;
- import com.baomidou.mybatisplus.mapper.BaseMapper;
- /**
- * <p>
- * 继承 MapperAnnotationBuilder 没有XML配置文件注入基础CRUD方法
- * </p>
- *
- * @author Caratacus
- * @Date 2017-01-04
- */
- public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
- private final Set<Class<? extends Annotation>> sqlAnnotationTypes = new HashSet<>();
- private final Set<Class<? extends Annotation>> sqlProviderAnnotationTypes = new HashSet<>();
- private Configuration configuration;
- private MapperBuilderAssistant assistant;
- private Class<?> type;
- public MybatisMapperAnnotationBuilder(Configuration configuration, Class<?> type) {
- // TODO 执行父类
- super(configuration, type);
- String resource = type.getName().replace('.', '/') + ".java (best guess)";
- this.assistant = new MapperBuilderAssistant(configuration, resource);
- this.configuration = configuration;
- this.type = type;
- sqlAnnotationTypes.add(Select.class);
- sqlAnnotationTypes.add(Insert.class);
- sqlAnnotationTypes.add(Update.class);
- sqlAnnotationTypes.add(Delete.class);
- sqlProviderAnnotationTypes.add(SelectProvider.class);
- sqlProviderAnnotationTypes.add(InsertProvider.class);
- sqlProviderAnnotationTypes.add(UpdateProvider.class);
- sqlProviderAnnotationTypes.add(DeleteProvider.class);
- }
- public void parse() {
- String resource = type.toString();
- if (!configuration.isResourceLoaded(resource)) {
- loadXmlResource();
- configuration.addLoadedResource(resource);
- assistant.setCurrentNamespace(type.getName());
- parseCache();
- parseCacheRef();
- Method[] methods = type.getMethods();
- // TODO 注入 CURD 动态 SQL (应该在注解之前注入)
- if (BaseMapper.class.isAssignableFrom(type)) {
- GlobalConfiguration.getSqlInjector(configuration).inspectInject(assistant, type);
- }
- for (Method method : methods) {
- try {
- // issue #237
- if (!method.isBridge()) {
- parseStatement(method);
- }
- } catch (IncompleteElementException e) {
- configuration.addIncompleteMethod(new MethodResolver(this, method));
- }
- }
- }
- parsePendingMethods();
- }
- private void parsePendingMethods() {
- Collection<MethodResolver> incompleteMethods = configuration.getIncompleteMethods();
- synchronized (incompleteMethods) {
- Iterator<MethodResolver> iter = incompleteMethods.iterator();
- while (iter.hasNext()) {
- try {
- iter.next().resolve();
- iter.remove();
- } catch (IncompleteElementException e) {
- // This method is still missing a resource
- }
- }
- }
- }
- private void loadXmlResource() {
- // Spring may not know the real resource name so we check a flag
- // to prevent loading again a resource twice
- // this flag is set at XMLMapperBuilder#bindMapperForNamespace
- if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
- String xmlResource = type.getName().replace('.', '/') + ".xml";
- InputStream inputStream = null;
- try {
- inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
- } catch (IOException e) {
- // ignore, resource is not required
- }
- if (inputStream != null) {
- XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
- xmlParser.parse();
- }
- }
- }
- private void parseCache() {
- CacheNamespace cacheDomain = type.getAnnotation(CacheNamespace.class);
- if (cacheDomain != null) {
- Integer size = cacheDomain.size() == 0 ? null : cacheDomain.size();
- Long flushInterval = cacheDomain.flushInterval() == 0 ? null : cacheDomain.flushInterval();
- Properties props = convertToProperties(cacheDomain.properties());
- assistant.useNewCache(cacheDomain.implementation(), cacheDomain.eviction(), flushInterval, size,
- cacheDomain.readWrite(), cacheDomain.blocking(), props);
- }
- }
- private Properties convertToProperties(Property[] properties) {
- if (properties.length == 0) {
- return null;
- }
- Properties props = new Properties();
- for (Property property : properties) {
- props.setProperty(property.name(), PropertyParser.parse(property.value(), configuration.getVariables()));
- }
- return props;
- }
- private void parseCacheRef() {
- CacheNamespaceRef cacheDomainRef = type.getAnnotation(CacheNamespaceRef.class);
- if (cacheDomainRef != null) {
- Class<?> refType = cacheDomainRef.value();
- String refName = cacheDomainRef.name();
- if (refType == void.class && refName.isEmpty()) {
- throw new BuilderException("Should be specified either value() or name() attribute in the @CacheNamespaceRef");
- }
- if (refType != void.class && !refName.isEmpty()) {
- throw new BuilderException("Cannot use both value() and name() attribute in the @CacheNamespaceRef");
- }
- String namespace = (refType != void.class) ? refType.getName() : refName;
- assistant.useCacheRef(namespace);
- }
- }
- private String parseResultMap(Method method) {
- Class<?> returnType = getReturnType(method);
- ConstructorArgs args = method.getAnnotation(ConstructorArgs.class);
- Results results = method.getAnnotation(Results.class);
- TypeDiscriminator typeDiscriminator = method.getAnnotation(TypeDiscriminator.class);
- String resultMapId = generateResultMapName(method);
- applyResultMap(resultMapId, returnType, argsIf(args), resultsIf(results), typeDiscriminator);
- return resultMapId;
- }
- private String generateResultMapName(Method method) {
- Results results = method.getAnnotation(Results.class);
- if (results != null && !results.id().isEmpty()) {
- return type.getName() + "." + results.id();
- }
- StringBuilder suffix = new StringBuilder();
- for (Class<?> c : method.getParameterTypes()) {
- suffix.append("-");
- suffix.append(c.getSimpleName());
- }
- if (suffix.length() < 1) {
- suffix.append("-void");
- }
- return type.getName() + "." + method.getName() + suffix;
- }
- private void applyResultMap(String resultMapId, Class<?> returnType, Arg[] args, Result[] results,
- TypeDiscriminator discriminator) {
- List<ResultMapping> resultMappings = new ArrayList<>();
- applyConstructorArgs(args, returnType, resultMappings);
- applyResults(results, returnType, resultMappings);
- Discriminator disc = applyDiscriminator(resultMapId, returnType, discriminator);
- // TODO add AutoMappingBehaviour
- assistant.addResultMap(resultMapId, returnType, null, disc, resultMappings, null);
- createDiscriminatorResultMaps(resultMapId, returnType, discriminator);
- }
- private void createDiscriminatorResultMaps(String resultMapId, Class<?> resultType, TypeDiscriminator discriminator) {
- if (discriminator != null) {
- for (Case c : discriminator.cases()) {
- String caseResultMapId = resultMapId + "-" + c.value();
- List<ResultMapping> resultMappings = new ArrayList<>();
- // issue #136
- applyConstructorArgs(c.constructArgs(), resultType, resultMappings);
- applyResults(c.results(), resultType, resultMappings);
- // TODO add AutoMappingBehaviour
- assistant.addResultMap(caseResultMapId, c.type(), resultMapId, null, resultMappings, null);
- }
- }
- }
- private Discriminator applyDiscriminator(String resultMapId, Class<?> resultType, TypeDiscriminator discriminator) {
- if (discriminator != null) {
- String column = discriminator.column();
- Class<?> javaType = discriminator.javaType() == void.class ? String.class : discriminator.javaType();
- JdbcType jdbcType = discriminator.jdbcType() == JdbcType.UNDEFINED ? null : discriminator.jdbcType();
- @SuppressWarnings("unchecked")
- Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>) (discriminator.typeHandler() == UnknownTypeHandler.class ? null
- : discriminator.typeHandler());
- Case[] cases = discriminator.cases();
- Map<String, String> discriminatorMap = new HashMap<>();
- for (Case c : cases) {
- String value = c.value();
- String caseResultMapId = resultMapId + "-" + value;
- discriminatorMap.put(value, caseResultMapId);
- }
- return assistant.buildDiscriminator(resultType, column, javaType, jdbcType, typeHandler, discriminatorMap);
- }
- return null;
- }
- void parseStatement(Method method) {
- Class<?> parameterTypeClass = getParameterType(method);
- LanguageDriver languageDriver = getLanguageDriver(method);
- SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver);
- if (sqlSource != null) {
- Options options = method.getAnnotation(Options.class);
- final String mappedStatementId = type.getName() + "." + method.getName();
- Integer fetchSize = null;
- Integer timeout = null;
- StatementType statementType = StatementType.PREPARED;
- ResultSetType resultSetType = ResultSetType.FORWARD_ONLY;
- SqlCommandType sqlCommandType = getSqlCommandType(method);
- boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
- boolean flushCache = !isSelect;
- boolean useCache = isSelect;
- KeyGenerator keyGenerator;
- String keyProperty = "id";
- String keyColumn = null;
- if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
- // first check for SelectKey annotation - that overrides everything else
- SelectKey selectKey = method.getAnnotation(SelectKey.class);
- if (selectKey != null) {
- keyGenerator = handleSelectKeyAnnotation(selectKey, mappedStatementId, getParameterType(method), languageDriver);
- keyProperty = selectKey.keyProperty();
- } else if (options == null) {
- keyGenerator = configuration.isUseGeneratedKeys() ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
- } else {
- keyGenerator = options.useGeneratedKeys() ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
- keyProperty = options.keyProperty();
- keyColumn = options.keyColumn();
- }
- } else {
- keyGenerator = NoKeyGenerator.INSTANCE;
- }
- if (options != null) {
- if (FlushCachePolicy.TRUE.equals(options.flushCache())) {
- flushCache = true;
- } else if (FlushCachePolicy.FALSE.equals(options.flushCache())) {
- flushCache = false;
- }
- useCache = options.useCache();
- fetchSize = options.fetchSize() > -1 || options.fetchSize() == Integer.MIN_VALUE ? options.fetchSize() : null; //issue #348
- timeout = options.timeout() > -1 ? options.timeout() : null;
- statementType = options.statementType();
- resultSetType = options.resultSetType();
- }
- String resultMapId = null;
- ResultMap resultMapAnnotation = method.getAnnotation(ResultMap.class);
- if (resultMapAnnotation != null) {
- String[] resultMaps = resultMapAnnotation.value();
- StringBuilder sb = new StringBuilder();
- for (String resultMap : resultMaps) {
- if (sb.length() > 0) {
- sb.append(",");
- }
- sb.append(resultMap);
- }
- resultMapId = sb.toString();
- } else if (isSelect) {
- resultMapId = parseResultMap(method);
- }
- assistant.addMappedStatement(
- mappedStatementId,
- sqlSource,
- statementType,
- sqlCommandType,
- fetchSize,
- timeout,
- // ParameterMapID
- null,
- parameterTypeClass,
- resultMapId,
- getReturnType(method),
- resultSetType,
- flushCache,
- useCache,
- // TODO gcode issue #577
- false,
- keyGenerator,
- keyProperty,
- keyColumn,
- // DatabaseID
- null,
- languageDriver,
- // ResultSets
- options != null ? nullOrEmpty(options.resultSets()) : null);
- }
- }
- private LanguageDriver getLanguageDriver(Method method) {
- Lang lang = method.getAnnotation(Lang.class);
- Class<?> langClass = null;
- if (lang != null) {
- langClass = lang.value();
- }
- return assistant.getLanguageDriver(langClass);
- }
- private Class<?> getParameterType(Method method) {
- Class<?> parameterType = null;
- Class<?>[] parameterTypes = method.getParameterTypes();
- for (Class<?> currentParameterType : parameterTypes) {
- if (!RowBounds.class.isAssignableFrom(currentParameterType)
- && !ResultHandler.class.isAssignableFrom(currentParameterType)) {
- if (parameterType == null) {
- parameterType = currentParameterType;
- } else {
- // issue #135
- parameterType = ParamMap.class;
- }
- }
- }
- return parameterType;
- }
- private Class<?> getReturnType(Method method) {
- Class<?> returnType = method.getReturnType();
- Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, type);
- if (resolvedReturnType instanceof Class) {
- returnType = (Class<?>) resolvedReturnType;
- if (returnType.isArray()) {
- returnType = returnType.getComponentType();
- }
- // gcode issue #508
- if (void.class.equals(returnType)) {
- ResultType rt = method.getAnnotation(ResultType.class);
- if (rt != null) {
- returnType = rt.value();
- }
- }
- } else if (resolvedReturnType instanceof ParameterizedType) {
- ParameterizedType parameterizedType = (ParameterizedType) resolvedReturnType;
- Class<?> rawType = (Class<?>) parameterizedType.getRawType();
- if (Collection.class.isAssignableFrom(rawType) || Cursor.class.isAssignableFrom(rawType)) {
- Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
- if (actualTypeArguments != null && actualTypeArguments.length == 1) {
- Type returnTypeParameter = actualTypeArguments[0];
- if (returnTypeParameter instanceof Class<?>) {
- returnType = (Class<?>) returnTypeParameter;
- } else if (returnTypeParameter instanceof ParameterizedType) {
- // (gcode issue #443) actual type can be a also a parameterized type
- returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
- } else if (returnTypeParameter instanceof GenericArrayType) {
- Class<?> componentType = (Class<?>) ((GenericArrayType) returnTypeParameter).getGenericComponentType();
- // (gcode issue #525) support List<byte[]>
- returnType = Array.newInstance(componentType, 0).getClass();
- }
- }
- } else if (method.isAnnotationPresent(MapKey.class) && Map.class.isAssignableFrom(rawType)) {
- // (gcode issue 504) Do not look into Maps if there is not MapKey annotation
- Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
- if (actualTypeArguments != null && actualTypeArguments.length == 2) {
- Type returnTypeParameter = actualTypeArguments[1];
- if (returnTypeParameter instanceof Class<?>) {
- returnType = (Class<?>) returnTypeParameter;
- } else if (returnTypeParameter instanceof ParameterizedType) {
- // (gcode issue 443) actual type can be a also a parameterized type
- returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
- }
- }
- }
- }
- return returnType;
- }
- private SqlSource getSqlSourceFromAnnotations(Method method, Class<?> parameterType, LanguageDriver languageDriver) {
- try {
- Class<? extends Annotation> sqlAnnotationType = getSqlAnnotationType(method);
- Class<? extends Annotation> sqlProviderAnnotationType = getSqlProviderAnnotationType(method);
- if (sqlAnnotationType != null) {
- if (sqlProviderAnnotationType != null) {
- throw new BindingException("You cannot supply both a static SQL and SqlProvider to method named " + method.getName());
- }
- Annotation sqlAnnotation = method.getAnnotation(sqlAnnotationType);
- final String[] strings = (String[]) sqlAnnotation.getClass().getMethod("value").invoke(sqlAnnotation);
- return buildSqlSourceFromStrings(strings, parameterType, languageDriver);
- } else if (sqlProviderAnnotationType != null) {
- Annotation sqlProviderAnnotation = method.getAnnotation(sqlProviderAnnotationType);
- return new ProviderSqlSource(assistant.getConfiguration(), sqlProviderAnnotation);
- }
- return null;
- } catch (Exception e) {
- throw new BuilderException("Could not find value method on SQL annotation. Cause: " + e, e);
- }
- }
- private SqlSource buildSqlSourceFromStrings(String[] strings, Class<?> parameterTypeClass, LanguageDriver languageDriver) {
- final StringBuilder sql = new StringBuilder();
- for (String fragment : strings) {
- sql.append(fragment);
- sql.append(" ");
- }
- return languageDriver.createSqlSource(configuration, sql.toString().trim(), parameterTypeClass);
- }
- private SqlCommandType getSqlCommandType(Method method) {
- Class<? extends Annotation> type = getSqlAnnotationType(method);
- if (type == null) {
- type = getSqlProviderAnnotationType(method);
- if (type == null) {
- return SqlCommandType.UNKNOWN;
- }
- if (type == SelectProvider.class) {
- type = Select.class;
- } else if (type == InsertProvider.class) {
- type = Insert.class;
- } else if (type == UpdateProvider.class) {
- type = Update.class;
- } else if (type == DeleteProvider.class) {
- type = Delete.class;
- }
- }
- return SqlCommandType.valueOf(type.getSimpleName().toUpperCase(Locale.ENGLISH));
- }
- private Class<? extends Annotation> getSqlAnnotationType(Method method) {
- return chooseAnnotationType(method, sqlAnnotationTypes);
- }
- private Class<? extends Annotation> getSqlProviderAnnotationType(Method method) {
- return chooseAnnotationType(method, sqlProviderAnnotationTypes);
- }
- private Class<? extends Annotation> chooseAnnotationType(Method method, Set<Class<? extends Annotation>> types) {
- for (Class<? extends Annotation> type : types) {
- Annotation annotation = method.getAnnotation(type);
- if (annotation != null) {
- return type;
- }
- }
- return null;
- }
- private void applyResults(Result[] results, Class<?> resultType, List<ResultMapping> resultMappings) {
- for (Result result : results) {
- List<ResultFlag> flags = new ArrayList<>();
- if (result.id()) {
- flags.add(ResultFlag.ID);
- }
- @SuppressWarnings("unchecked")
- Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>)
- ((result.typeHandler() == UnknownTypeHandler.class) ? null : result.typeHandler());
- ResultMapping resultMapping = assistant.buildResultMapping(
- resultType,
- nullOrEmpty(result.property()),
- nullOrEmpty(result.column()),
- result.javaType() == void.class ? null : result.javaType(),
- result.jdbcType() == JdbcType.UNDEFINED ? null : result.jdbcType(),
- hasNestedSelect(result) ? nestedSelectId(result) : null,
- null,
- null,
- null,
- typeHandler,
- flags,
- null,
- null,
- isLazy(result));
- resultMappings.add(resultMapping);
- }
- }
- private String nestedSelectId(Result result) {
- String nestedSelect = result.one().select();
- if (nestedSelect.length() < 1) {
- nestedSelect = result.many().select();
- }
- if (!nestedSelect.contains(".")) {
- nestedSelect = type.getName() + "." + nestedSelect;
- }
- return nestedSelect;
- }
- private boolean isLazy(Result result) {
- boolean isLazy = configuration.isLazyLoadingEnabled();
- if (result.one().select().length() > 0 && FetchType.DEFAULT != result.one().fetchType()) {
- isLazy = (result.one().fetchType() == FetchType.LAZY);
- } else if (result.many().select().length() > 0 && FetchType.DEFAULT != result.many().fetchType()) {
- isLazy = (result.many().fetchType() == FetchType.LAZY);
- }
- return isLazy;
- }
- private boolean hasNestedSelect(Result result) {
- if (result.one().select().length() > 0 && result.many().select().length() > 0) {
- throw new BuilderException("Cannot use both @One and @Many annotations in the same @Result");
- }
- return result.one().select().length() > 0 || result.many().select().length() > 0;
- }
- private void applyConstructorArgs(Arg[] args, Class<?> resultType, List<ResultMapping> resultMappings) {
- for (Arg arg : args) {
- List<ResultFlag> flags = new ArrayList<>();
- flags.add(ResultFlag.CONSTRUCTOR);
- if (arg.id()) {
- flags.add(ResultFlag.ID);
- }
- @SuppressWarnings("unchecked")
- Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>)
- (arg.typeHandler() == UnknownTypeHandler.class ? null : arg.typeHandler());
- ResultMapping resultMapping = assistant.buildResultMapping(
- resultType,
- nullOrEmpty(arg.name()),
- nullOrEmpty(arg.column()),
- arg.javaType() == void.class ? null : arg.javaType(),
- arg.jdbcType() == JdbcType.UNDEFINED ? null : arg.jdbcType(),
- nullOrEmpty(arg.select()),
- nullOrEmpty(arg.resultMap()),
- null,
- null,
- typeHandler,
- flags,
- null,
- null,
- false);
- resultMappings.add(resultMapping);
- }
- }
- private String nullOrEmpty(String value) {
- return value == null || value.trim().length() == 0 ? null : value;
- }
- private Result[] resultsIf(Results results) {
- return results == null ? new Result[0] : results.value();
- }
- private Arg[] argsIf(ConstructorArgs args) {
- return args == null ? new Arg[0] : args.value();
- }
- private KeyGenerator handleSelectKeyAnnotation(SelectKey selectKeyAnnotation, String baseStatementId, Class<?> parameterTypeClass, LanguageDriver languageDriver) {
- String id = baseStatementId + SelectKeyGenerator.SELECT_KEY_SUFFIX;
- Class<?> resultTypeClass = selectKeyAnnotation.resultType();
- StatementType statementType = selectKeyAnnotation.statementType();
- String keyProperty = selectKeyAnnotation.keyProperty();
- String keyColumn = selectKeyAnnotation.keyColumn();
- boolean executeBefore = selectKeyAnnotation.before();
- // defaults
- boolean useCache = false;
- KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
- Integer fetchSize = null;
- Integer timeout = null;
- boolean flushCache = false;
- String parameterMap = null;
- String resultMap = null;
- ResultSetType resultSetTypeEnum = null;
- SqlSource sqlSource = buildSqlSourceFromStrings(selectKeyAnnotation.statement(), parameterTypeClass, languageDriver);
- SqlCommandType sqlCommandType = SqlCommandType.SELECT;
- assistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum,
- flushCache, useCache, false,
- keyGenerator, keyProperty, keyColumn, null, languageDriver, null);
- id = assistant.applyCurrentNamespace(id, false);
- MappedStatement keyStatement = configuration.getMappedStatement(id, false);
- SelectKeyGenerator answer = new SelectKeyGenerator(keyStatement, executeBefore);
- configuration.addKeyGenerator(id, answer);
- return answer;
- }
- }
|