From 0b4a7f0531d32fc824041501672e80942672cbf7 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Sat, 31 Dec 2022 14:21:32 +0900 Subject: [PATCH 1/2] Remove DynamicContext reference It's used as a Map. --- .../thymeleaf/ThymeleafSqlSource.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java b/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java index 3d26f4e..bf5a615 100644 --- a/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java +++ b/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java @@ -18,6 +18,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.Locale; import java.util.Map; @@ -90,16 +91,19 @@ public BoundSql getBoundSql(Object parameterObject) { processingParameterType = parameterType; } - DynamicContext dynamicContext = new DynamicContext(configuration, parameterObject); - Map customVariables = dynamicContext.getBindings(); + Map bindings = new HashMap<>(); + bindings.put(DynamicContext.PARAMETER_OBJECT_KEY, parameterObject); + bindings.put(DynamicContext.DATABASE_ID_KEY, configuration.getDatabaseId()); + + Map customVariables = bindings; customVariables.put(TemporaryTakeoverKeys.CONFIGURATION, configuration); - customVariables.put(TemporaryTakeoverKeys.DYNAMIC_CONTEXT, dynamicContext); + customVariables.put(TemporaryTakeoverKeys.DYNAMIC_CONTEXT, bindings); customVariables.put(TemporaryTakeoverKeys.PROCESSING_PARAMETER_TYPE, processingParameterType); - String sql = sqlGenerator.generate(sqlTemplate, parameterObject, dynamicContext::bind, customVariables); + String sql = sqlGenerator.generate(sqlTemplate, parameterObject, bindings::put, customVariables); - SqlSource sqlSource = sqlSourceBuilder.parse(sql, processingParameterType, dynamicContext.getBindings()); + SqlSource sqlSource = sqlSourceBuilder.parse(sql, processingParameterType, bindings); BoundSql boundSql = sqlSource.getBoundSql(parameterObject); - dynamicContext.getBindings().forEach(boundSql::setAdditionalParameter); + bindings.forEach(boundSql::setAdditionalParameter); return boundSql; } @@ -116,20 +120,20 @@ static class ContextFactory implements BiFunction, I @Override public IContext apply(Object parameter, Map customVariable) { Configuration configuration = (Configuration) customVariable.remove(TemporaryTakeoverKeys.CONFIGURATION); - DynamicContext dynamicContext = (DynamicContext) customVariable.remove(TemporaryTakeoverKeys.DYNAMIC_CONTEXT); + Map bindings = (Map) customVariable.remove(TemporaryTakeoverKeys.DYNAMIC_CONTEXT); Class processingParameterType = (Class) customVariable .remove(TemporaryTakeoverKeys.PROCESSING_PARAMETER_TYPE); MyBatisBindingContext bindingContext = new MyBatisBindingContext( parameter != null && configuration.getTypeHandlerRegistry().hasTypeHandler(processingParameterType)); - dynamicContext.bind(MyBatisBindingContext.CONTEXT_VARIABLE_NAME, bindingContext); + bindings.put(MyBatisBindingContext.CONTEXT_VARIABLE_NAME, bindingContext); IContext context; if (parameter instanceof Map) { @SuppressWarnings(value = "unchecked") Map map = (Map) parameter; - context = new MapBasedContext(map, dynamicContext, configuration.getVariables()); + context = new MapBasedContext(map, bindings, configuration.getVariables()); } else { MetaClass metaClass = MetaClass.forClass(processingParameterType, configuration.getReflectorFactory()); - context = new MetaClassBasedContext(parameter, metaClass, processingParameterType, dynamicContext, + context = new MetaClassBasedContext(parameter, metaClass, processingParameterType, bindings, configuration.getVariables()); } return context; @@ -138,15 +142,15 @@ public IContext apply(Object parameter, Map customVariable) { private abstract static class AbstractContext implements IContext { - private final DynamicContext dynamicContext; + private final Map dynamicContext; private final Properties configurationProperties; private final Set variableNames; - private AbstractContext(DynamicContext dynamicContext, Properties configurationProperties) { + private AbstractContext(Map dynamicContext, Properties configurationProperties) { this.dynamicContext = dynamicContext; this.configurationProperties = configurationProperties; this.variableNames = new HashSet<>(); - addVariableNames(dynamicContext.getBindings().keySet()); + addVariableNames(dynamicContext.keySet()); Optional.ofNullable(configurationProperties).ifPresent(v -> addVariableNames(v.stringPropertyNames())); } @@ -183,8 +187,8 @@ public Set getVariableNames() { */ @Override public Object getVariable(String name) { - if (dynamicContext.getBindings().containsKey(name)) { - return dynamicContext.getBindings().get(name); + if (dynamicContext.containsKey(name)) { + return dynamicContext.get(name); } if (configurationProperties != null && configurationProperties.containsKey(name)) { return configurationProperties.getProperty(name); @@ -200,7 +204,7 @@ private static class MapBasedContext extends AbstractContext { private final Map variables; - private MapBasedContext(Map parameterMap, DynamicContext dynamicContext, + private MapBasedContext(Map parameterMap, Map dynamicContext, Properties configurationProperties) { super(dynamicContext, configurationProperties); this.variables = parameterMap; @@ -224,7 +228,7 @@ private static class MetaClassBasedContext extends AbstractContext { private final Class parameterType; private MetaClassBasedContext(Object parameterObject, MetaClass parameterMetaClass, Class parameterType, - DynamicContext dynamicContext, Properties configurationProperties) { + Map dynamicContext, Properties configurationProperties) { super(dynamicContext, configurationProperties); this.parameterObject = parameterObject; this.parameterMetaClass = parameterMetaClass; From 21f590746b9ef49caeec88bf577b2075004c40af Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Sat, 31 Dec 2022 14:31:51 +0900 Subject: [PATCH 2/2] Adjustment for https://github.com/mybatis/mybatis-3/pull/2760 --- .../thymeleaf/ThymeleafSqlSource.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java b/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java index bf5a615..178073b 100644 --- a/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java +++ b/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 the original author or authors. + * Copyright 2018-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,12 @@ package org.mybatis.scripting.thymeleaf; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; @@ -27,9 +29,12 @@ import java.util.Set; import java.util.function.BiFunction; +import org.apache.ibatis.builder.ParameterMappingTokenHandler; import org.apache.ibatis.builder.SqlSourceBuilder; import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.mapping.SqlSource; +import org.apache.ibatis.parsing.GenericTokenParser; import org.apache.ibatis.reflection.MetaClass; import org.apache.ibatis.scripting.xmltags.DynamicContext; import org.apache.ibatis.session.Configuration; @@ -54,7 +59,6 @@ private static class TemporaryTakeoverKeys { private final Configuration configuration; private final SqlGenerator sqlGenerator; - private final SqlSourceBuilder sqlSourceBuilder; private final String sqlTemplate; private final Class parameterType; @@ -76,7 +80,6 @@ private static class TemporaryTakeoverKeys { this.sqlGenerator = sqlGenerator; this.sqlTemplate = sqlTemplate; this.parameterType = parameterType; - this.sqlSourceBuilder = new SqlSourceBuilder(configuration); } /** @@ -101,13 +104,23 @@ public BoundSql getBoundSql(Object parameterObject) { customVariables.put(TemporaryTakeoverKeys.PROCESSING_PARAMETER_TYPE, processingParameterType); String sql = sqlGenerator.generate(sqlTemplate, parameterObject, bindings::put, customVariables); - SqlSource sqlSource = sqlSourceBuilder.parse(sql, processingParameterType, bindings); + SqlSource sqlSource = parse(configuration, sql, parameterObject, bindings); BoundSql boundSql = sqlSource.getBoundSql(parameterObject); bindings.forEach(boundSql::setAdditionalParameter); return boundSql; } + private static SqlSource parse(Configuration configuration, String originalSql, Object parameterObject, + Map additionalParameters) { + Class parameterType = parameterObject == null ? Object.class : parameterObject.getClass(); + List parameterMappings = new ArrayList<>(); + ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(parameterMappings, configuration, + parameterObject, parameterType, additionalParameters, true); + GenericTokenParser parser = new GenericTokenParser("#{", "}", handler); + return SqlSourceBuilder.buildSqlSource(configuration, parser.parse(originalSql), parameterMappings); + } + /** * The factory class for Thymeleaf's context. * @@ -120,7 +133,7 @@ static class ContextFactory implements BiFunction, I @Override public IContext apply(Object parameter, Map customVariable) { Configuration configuration = (Configuration) customVariable.remove(TemporaryTakeoverKeys.CONFIGURATION); - Map bindings = (Map) customVariable.remove(TemporaryTakeoverKeys.DYNAMIC_CONTEXT); + Map bindings = (Map) customVariable.remove(TemporaryTakeoverKeys.DYNAMIC_CONTEXT); Class processingParameterType = (Class) customVariable .remove(TemporaryTakeoverKeys.PROCESSING_PARAMETER_TYPE); MyBatisBindingContext bindingContext = new MyBatisBindingContext(