diff --git a/pom.xml b/pom.xml
index d0e8532d..a279bcf3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@
- 3.5.19
+ 3.6.0-SNAPSHOT
3.1.3.RELEASE
@@ -214,4 +214,12 @@
+
+
+ sonatype-oss-snapshots
+ Sonatype OSS Snapshots Repository
+ https://central.sonatype.com/repository/maven-snapshots/
+
+
+
diff --git a/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafLanguageDriver.java b/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafLanguageDriver.java
index 38d1caa6..9ec40de7 100644
--- a/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafLanguageDriver.java
+++ b/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafLanguageDriver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2022 the original author or authors.
+ * Copyright 2018-2026 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.
@@ -20,6 +20,7 @@
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.parsing.XNode;
+import org.apache.ibatis.reflection.ParamNameResolver;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.Configuration;
@@ -84,7 +85,7 @@ public ParameterHandler createParameterHandler(MappedStatement mappedStatement,
*/
@Override
public SqlSource createSqlSource(Configuration configuration, XNode script, Class> parameterType) {
- return createSqlSource(configuration, script.getNode().getTextContent(), parameterType);
+ return createSqlSource(configuration, script.getNode().getTextContent(), parameterType, null);
}
/**
@@ -92,7 +93,19 @@ public SqlSource createSqlSource(Configuration configuration, XNode script, Clas
*/
@Override
public SqlSource createSqlSource(Configuration configuration, String script, Class> parameterType) {
- return new ThymeleafSqlSource(configuration, sqlGenerator, script.trim(), parameterType);
+ return createSqlSource(configuration, script, parameterType, null);
+ }
+
+ @Override
+ public SqlSource createSqlSource(Configuration configuration, XNode script, Class> parameterType,
+ ParamNameResolver paramNameResolver) {
+ return createSqlSource(configuration, script.getNode().getTextContent(), parameterType, paramNameResolver);
+ }
+
+ @Override
+ public SqlSource createSqlSource(Configuration configuration, String script, Class> parameterType,
+ ParamNameResolver paramNameResolver) {
+ return new ThymeleafSqlSource(configuration, sqlGenerator, script.trim(), parameterType, paramNameResolver);
}
}
diff --git a/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java b/src/main/java/org/mybatis/scripting/thymeleaf/ThymeleafSqlSource.java
index 3d26f4ea..4c24a03e 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-2026 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,9 +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;
@@ -26,10 +29,14 @@
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.reflection.ParamNameResolver;
import org.apache.ibatis.scripting.xmltags.DynamicContext;
import org.apache.ibatis.session.Configuration;
import org.thymeleaf.context.IContext;
@@ -53,9 +60,9 @@ private static class TemporaryTakeoverKeys {
private final Configuration configuration;
private final SqlGenerator sqlGenerator;
- private final SqlSourceBuilder sqlSourceBuilder;
private final String sqlTemplate;
private final Class> parameterType;
+ private final ParamNameResolver paramNameResolver;
/**
* Constructor for for integrating with template engine provide by Thymeleaf.
@@ -69,13 +76,23 @@ private static class TemporaryTakeoverKeys {
* @param parameterType
* A parameter type that specified at mapper method argument or xml element
*/
+ ThymeleafSqlSource(Configuration configuration, SqlGenerator sqlGenerator, String sqlTemplate, Class> parameterType,
+ ParamNameResolver paramNameResolver) {
+ this.configuration = configuration;
+ this.sqlGenerator = sqlGenerator;
+ this.sqlTemplate = sqlTemplate;
+ this.parameterType = parameterType;
+ this.paramNameResolver = paramNameResolver;
+ }
+
+ @Deprecated
ThymeleafSqlSource(Configuration configuration, SqlGenerator sqlGenerator, String sqlTemplate,
Class> parameterType) {
this.configuration = configuration;
this.sqlGenerator = sqlGenerator;
this.sqlTemplate = sqlTemplate;
this.parameterType = parameterType;
- this.sqlSourceBuilder = new SqlSourceBuilder(configuration);
+ this.paramNameResolver = null;
}
/**
@@ -90,20 +107,33 @@ 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 = parse(configuration, sql, parameterObject, bindings, paramNameResolver);
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
- dynamicContext.getBindings().forEach(boundSql::setAdditionalParameter);
+ bindings.forEach(boundSql::setAdditionalParameter);
return boundSql;
}
+ private static SqlSource parse(Configuration configuration, String originalSql, Object parameterObject,
+ Map additionalParameters, ParamNameResolver pnResolver) {
+ Class> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
+ List parameterMappings = new ArrayList<>();
+ ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(parameterMappings, configuration,
+ parameterObject, parameterType, additionalParameters, pnResolver, false);
+ GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
+ return SqlSourceBuilder.buildSqlSource(configuration, parser.parse(originalSql), parameterMappings);
+ }
+
/**
* The factory class for Thymeleaf's context.
*
@@ -116,20 +146,20 @@ static class ContextFactory implements BiFunction