diff --git a/src/main/java/org/apache/ibatis/builder/SqlSourceBuilder.java b/src/main/java/org/apache/ibatis/builder/SqlSourceBuilder.java
index 3a643ccf8cc..6e39aa6a61c 100644
--- a/src/main/java/org/apache/ibatis/builder/SqlSourceBuilder.java
+++ b/src/main/java/org/apache/ibatis/builder/SqlSourceBuilder.java
@@ -34,7 +34,7 @@
*/
public class SqlSourceBuilder extends BaseBuilder {
- private static final String PARAMETER_PROPERTIES = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";
+ private static final String PARAMETER_PROPERTIES = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName,like";
public SqlSourceBuilder(Configuration configuration) {
super(configuration);
@@ -131,6 +131,8 @@ private ParameterMapping buildParameterMapping(String content) {
typeHandlerAlias = value;
} else if ("jdbcTypeName".equals(name)) {
builder.jdbcTypeName(value);
+ } else if ("like".equals(name)) {
+ builder.like(value);
} else if ("property".equals(name)) {
// Do Nothing
} else if ("expression".equals(name)) {
diff --git a/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java b/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java
index 040e182a8cd..04771be0a96 100644
--- a/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java
+++ b/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java
@@ -16,6 +16,7 @@
package org.apache.ibatis.mapping;
import java.sql.ResultSet;
+import java.util.Optional;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.JdbcType;
@@ -37,11 +38,42 @@ public class ParameterMapping {
private TypeHandler> typeHandler;
private String resultMapId;
private String jdbcTypeName;
+ private LikeEnum like;
private String expression;
private ParameterMapping() {
}
+ public enum LikeEnum {
+
+ NONE,
+
+ LEFT {
+ @Override
+ public String format(String source) {
+ return "%" + source;
+ }
+ },
+
+ RIGHT {
+ @Override
+ public String format(String source) {
+ return source + "%";
+ }
+ },
+
+ ALL {
+ @Override
+ public String format(String source) {
+ return RIGHT.format(LEFT.format(source));
+ }
+ };
+
+ public String format(String source) {
+ return source;
+ }
+ }
+
public static class Builder {
private final ParameterMapping parameterMapping = new ParameterMapping();
@@ -94,6 +126,18 @@ public Builder jdbcTypeName(String jdbcTypeName) {
return this;
}
+ public Builder like(String likeMode) {
+ LikeEnum likeEnum = null;
+ for (LikeEnum value : LikeEnum.values()) {
+ if (value.name().equalsIgnoreCase(likeMode)) {
+ likeEnum = value;
+ break;
+ }
+ }
+ parameterMapping.like = Optional.ofNullable(likeEnum).orElse(LikeEnum.NONE);
+ return this;
+ }
+
public Builder expression(String expression) {
parameterMapping.expression = expression;
return this;
@@ -196,6 +240,15 @@ public String getJdbcTypeName() {
return jdbcTypeName;
}
+ /**
+ * Used for handling concat parameter with %.
+ *
+ * @return like pattern
+ */
+ public LikeEnum getLike() {
+ return like;
+ }
+
/**
* Expression 'Not used'.
*
@@ -217,6 +270,7 @@ public String toString() {
// sb.append(", typeHandler=").append(typeHandler); // typeHandler also doesn't have a useful .toString()
sb.append(", resultMapId='").append(resultMapId).append('\'');
sb.append(", jdbcTypeName='").append(jdbcTypeName).append('\'');
+ sb.append(", like='").append(like).append('\'');
sb.append(", expression='").append(expression).append('\'');
sb.append('}');
return sb.toString();
diff --git a/src/main/java/org/apache/ibatis/scripting/defaults/DefaultParameterHandler.java b/src/main/java/org/apache/ibatis/scripting/defaults/DefaultParameterHandler.java
index a9f5a91a0b8..60c1693c0be 100644
--- a/src/main/java/org/apache/ibatis/scripting/defaults/DefaultParameterHandler.java
+++ b/src/main/java/org/apache/ibatis/scripting/defaults/DefaultParameterHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2022 the original author or authors.
+ * Copyright 2009-2023 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.
@@ -83,6 +83,9 @@ public void setParameters(PreparedStatement ps) {
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
+ if (parameterMapping.getLike() != null && value instanceof String) {
+ value = parameterMapping.getLike().format((String) value);
+ }
try {
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
diff --git a/src/test/java/org/apache/ibatis/submitted/select_with_like/Mapper.java b/src/test/java/org/apache/ibatis/submitted/select_with_like/Mapper.java
new file mode 100644
index 00000000000..c997a793738
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/submitted/select_with_like/Mapper.java
@@ -0,0 +1,16 @@
+package org.apache.ibatis.submitted.select_with_like;
+
+import org.apache.ibatis.annotations.Insert;
+
+interface Mapper {
+
+ @Insert({ "" })
+ void selectWithLikeRight(String name);
+
+ @Insert({ "" })
+ void selectWithNoLike(String name);
+
+ @Insert({ "" })
+ void selectWithOodLike(String name);
+
+ }
diff --git a/src/test/java/org/apache/ibatis/submitted/select_with_like/SelectWithLikeTest.java b/src/test/java/org/apache/ibatis/submitted/select_with_like/SelectWithLikeTest.java
new file mode 100644
index 00000000000..50b8aa43a45
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/submitted/select_with_like/SelectWithLikeTest.java
@@ -0,0 +1,77 @@
+package org.apache.ibatis.submitted.select_with_like;
+
+
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
+import org.apache.ibatis.session.Configuration;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Proxy;
+import java.sql.PreparedStatement;
+
+public class SelectWithLikeTest {
+
+
+ private static Configuration configuration;
+
+ @BeforeAll
+ static void setUp() {
+ configuration = new Configuration();
+ configuration.addMapper(Mapper.class);
+ }
+
+
+ @Test
+ void testSelectWithLikeLeft() {
+ Object parameterObject = "jack";
+ MappedStatement mappedStatement = configuration.getMappedStatement("selectWithLikeRight");
+ PreparedStatement preparedStatement = (PreparedStatement) Proxy.newProxyInstance(
+ SelectWithLikeTest.class.getClassLoader(), new Class[] { PreparedStatement.class }, (proxy, method, args) -> {
+ if (method.getName().equals("setString")) {
+ Assertions.assertEquals(args[1], parameterObject + "%");
+ }
+ return null;
+ });
+
+ BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
+ DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
+ parameterHandler.setParameters(preparedStatement);
+ }
+
+ @Test
+ void testSelectWithNoLike() {
+ Object parameterObject = "jack";
+ MappedStatement mappedStatement = configuration.getMappedStatement("selectWithNoLike");
+ PreparedStatement preparedStatement = (PreparedStatement) Proxy.newProxyInstance(
+ SelectWithLikeTest.class.getClassLoader(), new Class[] { PreparedStatement.class }, (proxy, method, args) -> {
+ if (method.getName().equals("setString")) {
+ Assertions.assertEquals(args[1], parameterObject);
+ }
+ return null;
+ });
+
+ BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
+ DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
+ parameterHandler.setParameters(preparedStatement);
+ }
+
+ @Test
+ void testSelectWithOodLike() {
+ Object parameterObject = "jack";
+ MappedStatement mappedStatement = configuration.getMappedStatement("selectWithOodLike");
+ PreparedStatement preparedStatement = (PreparedStatement) Proxy.newProxyInstance(
+ SelectWithLikeTest.class.getClassLoader(), new Class[] { PreparedStatement.class }, (proxy, method, args) -> {
+ if (method.getName().equals("setString")) {
+ Assertions.assertEquals(args[1], parameterObject);
+ }
+ return null;
+ });
+
+ BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
+ DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
+ parameterHandler.setParameters(preparedStatement);
+ }
+}