From 3a7438399441222b4f098fbc4bd00399e4177073 Mon Sep 17 00:00:00 2001 From: Kazuki Shimizu Date: Fri, 30 Mar 2018 03:17:25 +0900 Subject: [PATCH] Allow using actual argument name as bind parameter on a single collection #1237 --- .../ibatis/reflection/ParamNameResolver.java | 11 ++- .../session/defaults/DefaultSqlSession.java | 23 +++++- .../submitted/param_name_resolve/CreateDB.sql | 2 +- .../submitted/param_name_resolve/Mapper.java | 7 -- .../submitted/param_name_resolve/Mapper.xml | 30 ++++---- .../ParamNameResolveTest.java | 70 ++++++++++++------- .../submitted/param_name_resolve/User.java | 22 ------ .../param_name_resolve/mybatis-config.xml | 36 +++++----- 8 files changed, 109 insertions(+), 92 deletions(-) delete mode 100644 src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.java delete mode 100644 src/test/java/org/apache/ibatis/submitted/param_name_resolve/User.java diff --git a/src/main/java/org/apache/ibatis/reflection/ParamNameResolver.java b/src/main/java/org/apache/ibatis/reflection/ParamNameResolver.java index 1a5d4408be3..26e2c1709cf 100644 --- a/src/main/java/org/apache/ibatis/reflection/ParamNameResolver.java +++ b/src/main/java/org/apache/ibatis/reflection/ParamNameResolver.java @@ -27,6 +27,7 @@ import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.defaults.DefaultSqlSession; public class ParamNameResolver { @@ -48,6 +49,7 @@ public class ParamNameResolver { private final SortedMap names; private boolean hasParamAnnotation; + private boolean useActualParamName; public ParamNameResolver(Configuration config, Method method) { final Class[] paramTypes = method.getParameterTypes(); @@ -77,6 +79,8 @@ public ParamNameResolver(Configuration config, Method method) { // use the parameter index as the name ("0", "1", ...) // gcode issue #71 name = String.valueOf(map.size()); + } else { + useActualParamName = true; } } map.put(paramIndex, name); @@ -115,7 +119,12 @@ public Object getNamedParams(Object[] args) { if (args == null || paramCount == 0) { return null; } else if (!hasParamAnnotation && paramCount == 1) { - return args[names.firstKey()]; + Object value = args[names.firstKey()]; + if (useActualParamName) { + return DefaultSqlSession.wrapCollection(value, map -> map.put(names.get(0), value)); + } else { + return value; + } } else { final Map param = new ParamMap(); int i = 0; diff --git a/src/main/java/org/apache/ibatis/session/defaults/DefaultSqlSession.java b/src/main/java/org/apache/ibatis/session/defaults/DefaultSqlSession.java index b736d42b9fa..323ab8f1863 100644 --- a/src/main/java/org/apache/ibatis/session/defaults/DefaultSqlSession.java +++ b/src/main/java/org/apache/ibatis/session/defaults/DefaultSqlSession.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2017 the original author or authors. + * Copyright 2009-2018 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. @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import org.apache.ibatis.binding.BindingException; import org.apache.ibatis.cursor.Cursor; @@ -318,8 +319,25 @@ private boolean isCommitOrRollbackRequired(boolean force) { } private Object wrapCollection(final Object object) { + return wrapCollection(object, null); + } + + /** + * Wrap a collection and array into {@link Map}. + * + * @param object a target parameter object + * @param mapConsumer consumer function for a map that wrapped collection and array. If + * {@code object} is collection or array, this function will be called. + * @return If {@code object} is collection or array, return a map that wrapped collection and + * array. Otherwise return a argument object. + * @since 3.5.0 + */ + public static Object wrapCollection(final Object object, final Consumer> mapConsumer) { if (object instanceof Collection) { StrictMap map = new StrictMap(); + if (mapConsumer != null) { + mapConsumer.accept(map); + } map.put("collection", object); if (object instanceof List) { map.put("list", object); @@ -327,6 +345,9 @@ private Object wrapCollection(final Object object) { return map; } else if (object != null && object.getClass().isArray()) { StrictMap map = new StrictMap(); + if (mapConsumer != null) { + mapConsumer.accept(map); + } map.put("array", object); return map; } diff --git a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/CreateDB.sql b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/CreateDB.sql index d5b2c1ea6e9..04f85367c0d 100644 --- a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/CreateDB.sql +++ b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/CreateDB.sql @@ -1,5 +1,5 @@ -- --- Copyright 2009-2016 the original author or authors. +-- Copyright 2009-2018 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. diff --git a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.java b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.java deleted file mode 100644 index 7f12c11cd2d..00000000000 --- a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.apache.ibatis.submitted.param_name_resolve; - -import java.util.List; - -public interface Mapper { - Long getUserCount(List ids); -} diff --git a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.xml b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.xml index fa2dea6dac4..c0d2620fc49 100644 --- a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.xml +++ b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/Mapper.xml @@ -1,7 +1,7 @@ + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - + + + + + diff --git a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/ParamNameResolveTest.java b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/ParamNameResolveTest.java index 1d8c0bd951b..8d733247726 100644 --- a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/ParamNameResolveTest.java +++ b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/ParamNameResolveTest.java @@ -1,3 +1,18 @@ +/** + * Copyright 2009-2018 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. + * 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 org.apache.ibatis.submitted.param_name_resolve; import org.apache.ibatis.io.Resources; @@ -11,40 +26,43 @@ import java.io.Reader; import java.sql.Connection; import java.util.Arrays; +import java.util.List; import static org.junit.Assert.assertEquals; public class ParamNameResolveTest { - private static SqlSessionFactory sqlSessionFactory; + private static SqlSessionFactory sqlSessionFactory; - @BeforeClass - public static void setUp() throws Exception { - // create an SqlSessionFactory - Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/param_name_resolve/mybatis-config.xml"); - sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); - reader.close(); + @BeforeClass + public static void setUp() throws Exception { + // create an SqlSessionFactory + try (Reader reader = Resources + .getResourceAsReader("org/apache/ibatis/submitted/param_name_resolve/mybatis-config.xml")) { + sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + } - // populate in-memory database - SqlSession session = sqlSessionFactory.openSession(); + // populate in-memory database + try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); - reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/param_name_resolve/CreateDB.sql"); - ScriptRunner runner = new ScriptRunner(conn); - runner.setLogWriter(null); - runner.runScript(reader); - conn.close(); - reader.close(); - session.close(); + Reader reader = Resources + .getResourceAsReader("org/apache/ibatis/submitted/param_name_resolve/CreateDB.sql")) { + ScriptRunner runner = new ScriptRunner(conn); + runner.setLogWriter(null); + runner.runScript(reader); } + } - @Test - public void testSingleParameter() { - SqlSession sqlSession = sqlSessionFactory.openSession(); - try { - Mapper mapper = sqlSession.getMapper(Mapper.class); - long count = mapper.getUserCount(Arrays.asList(1, 2)); - assertEquals(2, count); - } finally { - sqlSession.close(); - } + @Test + public void testSingleParameterWhenUseActualParamNameIsTrue() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + long count = mapper.getUserCount(Arrays.asList(1, 2)); + assertEquals(2, count); } + } + + interface Mapper { + Long getUserCount(List ids); + } + } diff --git a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/User.java b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/User.java deleted file mode 100644 index fb95f8075b5..00000000000 --- a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/User.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apache.ibatis.submitted.param_name_resolve; - -public class User { - private int id; - private String name; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/mybatis-config.xml b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/mybatis-config.xml index 45512c05fed..0d896298b5e 100644 --- a/src/test/java/org/apache/ibatis/submitted/param_name_resolve/mybatis-config.xml +++ b/src/test/java/org/apache/ibatis/submitted/param_name_resolve/mybatis-config.xml @@ -1,7 +1,7 @@ + PUBLIC "-//mybatis.org//DTD Config 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-config.dtd"> - - - - - - - - - - - - - - - - + + + + + + + + + + + + + +