From a3b11b24c89dd71e4bbc424d143f17453793ad6e Mon Sep 17 00:00:00 2001 From: Kazuki Shimizu Date: Tue, 25 Jul 2017 10:56:26 +0900 Subject: [PATCH 1/2] Support ProviderContext on sql provider method A ProviderContext instance holds type of mapper interface and mapper method that specified an sql provider annotation. Fixes gh-1013 --- .../annotation/MapperAnnotationBuilder.java | 2 +- .../builder/annotation/ProviderContext.java | 60 ++++++++++++ .../builder/annotation/ProviderSqlSource.java | 55 ++++++++++- .../submitted/sqlprovider/BaseMapper.java | 69 ++++++++++++++ .../ibatis/submitted/sqlprovider/CreateDB.sql | 7 +- .../ibatis/submitted/sqlprovider/Mapper.java | 5 +- .../submitted/sqlprovider/OurSqlBuilder.java | 67 +++++++++++++- .../sqlprovider/SqlProviderTest.java | 92 +++++++++++++++++-- 8 files changed, 339 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/apache/ibatis/builder/annotation/ProviderContext.java create mode 100644 src/test/java/org/apache/ibatis/submitted/sqlprovider/BaseMapper.java diff --git a/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java b/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java index 54cd9a644d1..353ef7ee89a 100644 --- a/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java +++ b/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java @@ -465,7 +465,7 @@ private SqlSource getSqlSourceFromAnnotations(Method method, Class parameterT return buildSqlSourceFromStrings(strings, parameterType, languageDriver); } else if (sqlProviderAnnotationType != null) { Annotation sqlProviderAnnotation = method.getAnnotation(sqlProviderAnnotationType); - return new ProviderSqlSource(assistant.getConfiguration(), sqlProviderAnnotation); + return new ProviderSqlSource(assistant.getConfiguration(), sqlProviderAnnotation, type, method); } return null; } catch (Exception e) { diff --git a/src/main/java/org/apache/ibatis/builder/annotation/ProviderContext.java b/src/main/java/org/apache/ibatis/builder/annotation/ProviderContext.java new file mode 100644 index 00000000000..38f0d46d427 --- /dev/null +++ b/src/main/java/org/apache/ibatis/builder/annotation/ProviderContext.java @@ -0,0 +1,60 @@ +/** + * Copyright 2009-2017 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.builder.annotation; + +import java.lang.reflect.Method; + +/** + * The context object for sql provider method. + * + * @author Kazuki Shimizu + * @since 3.4.5 + */ +public final class ProviderContext { + + private final Class mapperType; + private final Method mapperMethod; + + /** + * Constructor. + * + * @param mapperType A mapper interface type that specified provider + * @param mapperMethod A mapper method that specified provider + */ + ProviderContext(Class mapperType, Method mapperMethod) { + this.mapperType = mapperType; + this.mapperMethod = mapperMethod; + } + + /** + * Get a mapper interface type that specified provider. + * + * @return A mapper interface type that specified provider + */ + public Class getMapperType() { + return mapperType; + } + + /** + * Get a mapper method that specified provider. + * + * @return A mapper method that specified provider + */ + public Method getMapperMethod() { + return mapperMethod; + } + +} diff --git a/src/main/java/org/apache/ibatis/builder/annotation/ProviderSqlSource.java b/src/main/java/org/apache/ibatis/builder/annotation/ProviderSqlSource.java index aa4132d99a6..438a6267621 100644 --- a/src/main/java/org/apache/ibatis/builder/annotation/ProviderSqlSource.java +++ b/src/main/java/org/apache/ibatis/builder/annotation/ProviderSqlSource.java @@ -36,8 +36,22 @@ public class ProviderSqlSource implements SqlSource { private final Class providerType; private Method providerMethod; private String[] providerMethodArgumentNames; + private Class[] providerMethodParameterTypes; + private ProviderContext providerContext; + private Integer providerContextIndex; + /** + * @deprecated Please use the {@link #ProviderSqlSource(Configuration, Object, Class, Method)} instead of this. + */ + @Deprecated public ProviderSqlSource(Configuration config, Object provider) { + this(config, provider, null, null); + } + + /** + * @since 3.4.5 + */ + public ProviderSqlSource(Configuration config, Object provider, Class mapperType, Method mapperMethod) { String providerMethodName; try { this.sqlSourceParser = new SqlSourceBuilder(config); @@ -54,6 +68,7 @@ public ProviderSqlSource(Configuration config, Object provider) { } this.providerMethod = m; this.providerMethodArgumentNames = new ParamNameResolver(config, m).getNames(); + this.providerMethodParameterTypes = m.getParameterTypes(); } } } @@ -66,6 +81,18 @@ public ProviderSqlSource(Configuration config, Object provider) { throw new BuilderException("Error creating SqlSource for SqlProvider. Method '" + providerMethodName + "' not found in SqlProvider '" + this.providerType.getName() + "'."); } + for (int i = 0; i< this.providerMethodParameterTypes.length; i++) { + Class parameterType = this.providerMethodParameterTypes[i]; + if (parameterType == ProviderContext.class) { + if (this.providerContext != null){ + throw new BuilderException("Error creating SqlSource for SqlProvider. ProviderContext found multiple in SqlProvider method (" + + this.providerType.getName() + "." + providerMethod.getName() + + "). ProviderContext can not define multiple in SqlProvider method argument."); + } + this.providerContext = new ProviderContext(mapperType, mapperMethod); + this.providerContextIndex = i; + } + } } @Override @@ -77,12 +104,15 @@ public BoundSql getBoundSql(Object parameterObject) { private SqlSource createSqlSource(Object parameterObject) { try { Class[] parameterTypes = providerMethod.getParameterTypes(); + int bindParameterCount = parameterTypes.length - (providerContext == null ? 0 : 1); String sql; if (parameterTypes.length == 0) { sql = (String) providerMethod.invoke(providerType.newInstance()); - } else if (parameterTypes.length == 1 && - (parameterObject == null || parameterTypes[0].isAssignableFrom(parameterObject.getClass()))) { - sql = (String) providerMethod.invoke(providerType.newInstance(), parameterObject); + } else if (bindParameterCount == 0) { + sql = (String) providerMethod.invoke(providerType.newInstance(), providerContext); + } else if (bindParameterCount == 1 && + (parameterObject == null || parameterTypes[(providerContextIndex == null || providerContextIndex == 1) ? 0 : 1].isAssignableFrom(parameterObject.getClass()))) { + sql = (String) providerMethod.invoke(providerType.newInstance(), extractProviderMethodArguments(parameterObject)); } else if (parameterObject instanceof Map) { @SuppressWarnings("unchecked") Map params = (Map) parameterObject; @@ -91,7 +121,7 @@ private SqlSource createSqlSource(Object parameterObject) { throw new BuilderException("Error invoking SqlProvider method (" + providerType.getName() + "." + providerMethod.getName() + "). Cannot invoke a method that holds " - + (parameterTypes.length == 1 ? "named argument(@Param)": "multiple arguments") + + (bindParameterCount == 1 ? "named argument(@Param)": "multiple arguments") + " using a specifying parameterObject. In this case, please specify a 'java.util.Map' object."); } Class parameterType = parameterObject == null ? Object.class : parameterObject.getClass(); @@ -105,10 +135,25 @@ private SqlSource createSqlSource(Object parameterObject) { } } + private Object[] extractProviderMethodArguments(Object parameterObject) { + if (providerContext != null) { + Object[] args = new Object[2]; + args[providerContextIndex == 0 ? 1 : 0] = parameterObject; + args[providerContextIndex] = providerContext; + return args; + } else { + return new Object[] { parameterObject }; + } + } + private Object[] extractProviderMethodArguments(Map params, String[] argumentNames) { Object[] args = new Object[argumentNames.length]; for (int i = 0; i < args.length; i++) { - args[i] = params.get(argumentNames[i]); + if (providerContextIndex != null && providerContextIndex == i) { + args[i] = providerContext; + } else { + args[i] = params.get(argumentNames[i]); + } } return args; } diff --git a/src/test/java/org/apache/ibatis/submitted/sqlprovider/BaseMapper.java b/src/test/java/org/apache/ibatis/submitted/sqlprovider/BaseMapper.java new file mode 100644 index 00000000000..babebb472d8 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/sqlprovider/BaseMapper.java @@ -0,0 +1,69 @@ +/** + * Copyright 2009-2017 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.sqlprovider; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.SelectProvider; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.List; + +public interface BaseMapper { + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByIdProviderContextOnly") + @ContainsLogicalDelete + T selectById(Integer id); + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByIdProviderContextOnly") + T selectActiveById(Integer id); + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByNameOneParamAndProviderContext") + @ContainsLogicalDelete + List selectByName(String name); + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByNameOneParamAndProviderContext") + List selectActiveByName(String name); + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByIdAndNameMultipleParamAndProviderContextWithAtParam") + @ContainsLogicalDelete + List selectByIdAndNameWithAtParam(@Param("id") Integer id, @Param("name") String name); + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByIdAndNameMultipleParamAndProviderContextWithAtParam") + List selectActiveByIdAndNameWithAtParam(@Param("id") Integer id, @Param("name") String name); + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByIdAndNameMultipleParamAndProviderContext") + @ContainsLogicalDelete + List selectByIdAndName(Integer id, String name); + + @SelectProvider(type= OurSqlBuilder.class, method= "buildSelectByIdAndNameMultipleParamAndProviderContext") + List selectActiveByIdAndName(Integer id, String name); + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + @interface ContainsLogicalDelete { + boolean value() default false; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @interface Meta { + String tableName(); + } + +} diff --git a/src/test/java/org/apache/ibatis/submitted/sqlprovider/CreateDB.sql b/src/test/java/org/apache/ibatis/submitted/sqlprovider/CreateDB.sql index 5098c70d2b5..5b9447bc93b 100644 --- a/src/test/java/org/apache/ibatis/submitted/sqlprovider/CreateDB.sql +++ b/src/test/java/org/apache/ibatis/submitted/sqlprovider/CreateDB.sql @@ -1,5 +1,5 @@ -- --- Copyright 2009-2016 the original author or authors. +-- Copyright 2009-2017 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. @@ -18,11 +18,12 @@ drop table users if exists; create table users ( id int, - name varchar(20) + name varchar(20), + logical_delete boolean default false ); insert into users (id, name) values(1, 'User1'); insert into users (id, name) values(2, 'User2'); insert into users (id, name) values(3, 'User3'); -insert into users (id, name) values(4, 'User4'); +insert into users (id, name, logical_delete) values(4, 'User4', true); diff --git a/src/test/java/org/apache/ibatis/submitted/sqlprovider/Mapper.java b/src/test/java/org/apache/ibatis/submitted/sqlprovider/Mapper.java index ceaccbc36ee..6eb54b56907 100644 --- a/src/test/java/org/apache/ibatis/submitted/sqlprovider/Mapper.java +++ b/src/test/java/org/apache/ibatis/submitted/sqlprovider/Mapper.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -24,7 +24,8 @@ import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.annotations.UpdateProvider; -public interface Mapper { +@BaseMapper.Meta(tableName = "users") +public interface Mapper extends BaseMapper { @SelectProvider(type = OurSqlBuilder.class, method = "buildGetUsersQuery") List getUsers(List allFilterIds); diff --git a/src/test/java/org/apache/ibatis/submitted/sqlprovider/OurSqlBuilder.java b/src/test/java/org/apache/ibatis/submitted/sqlprovider/OurSqlBuilder.java index 15638d2cff4..ea2b766774f 100644 --- a/src/test/java/org/apache/ibatis/submitted/sqlprovider/OurSqlBuilder.java +++ b/src/test/java/org/apache/ibatis/submitted/sqlprovider/OurSqlBuilder.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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,6 +16,7 @@ package org.apache.ibatis.submitted.sqlprovider; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.builder.annotation.ProviderContext; import org.apache.ibatis.jdbc.SQL; import java.util.List; @@ -148,4 +149,68 @@ public String buildDelete() { return "delete from users where id = #{id}"; } + public String buildSelectByIdProviderContextOnly(ProviderContext context) { + final boolean containsLogicalDelete = context.getMapperMethod().getAnnotation(BaseMapper.ContainsLogicalDelete.class) != null; + final String tableName = context.getMapperType().getAnnotation(BaseMapper.Meta.class).tableName(); + return new SQL(){{ + SELECT("*"); + FROM(tableName); + WHERE("id = #{id}"); + if (!containsLogicalDelete){ + WHERE("logical_delete = false"); + } + }}.toString(); + } + + public String buildSelectByNameOneParamAndProviderContext(ProviderContext context, final String name) { + final boolean containsLogicalDelete = context.getMapperMethod().getAnnotation(BaseMapper.ContainsLogicalDelete.class) != null; + final String tableName = context.getMapperType().getAnnotation(BaseMapper.Meta.class).tableName(); + return new SQL(){{ + SELECT("*"); + FROM(tableName); + if (name != null) { + WHERE("name like #{name} || '%'"); + } + if (!containsLogicalDelete){ + WHERE("logical_delete = false"); + } + }}.toString(); + } + + public String buildSelectByIdAndNameMultipleParamAndProviderContextWithAtParam(@Param("id") final Integer id, ProviderContext context, @Param("name") final String name) { + final boolean containsLogicalDelete = context.getMapperMethod().getAnnotation(BaseMapper.ContainsLogicalDelete.class) != null; + final String tableName = context.getMapperType().getAnnotation(BaseMapper.Meta.class).tableName(); + return new SQL(){{ + SELECT("*"); + FROM(tableName); + if (id != null) { + WHERE("id = #{id}"); + } + if (name != null) { + WHERE("name like #{name} || '%'"); + } + if (!containsLogicalDelete){ + WHERE("logical_delete = false"); + } + }}.toString(); + } + + public String buildSelectByIdAndNameMultipleParamAndProviderContext(final Integer id, final String name, ProviderContext context) { + final boolean containsLogicalDelete = context.getMapperMethod().getAnnotation(BaseMapper.ContainsLogicalDelete.class) != null; + final String tableName = context.getMapperType().getAnnotation(BaseMapper.Meta.class).tableName(); + return new SQL(){{ + SELECT("*"); + FROM(tableName); + if (id != null) { + WHERE("id = #{param1}"); + } + if (name != null) { + WHERE("name like #{param2} || '%'"); + } + if (!containsLogicalDelete){ + WHERE("logical_delete = false"); + } + }}.toString(); + } + } diff --git a/src/test/java/org/apache/ibatis/submitted/sqlprovider/SqlProviderTest.java b/src/test/java/org/apache/ibatis/submitted/sqlprovider/SqlProviderTest.java index d8acc1af4a3..f28434422b2 100644 --- a/src/test/java/org/apache/ibatis/submitted/sqlprovider/SqlProviderTest.java +++ b/src/test/java/org/apache/ibatis/submitted/sqlprovider/SqlProviderTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.fail; import java.io.Reader; +import java.lang.reflect.Method; import java.sql.Connection; import java.util.ArrayList; import java.util.HashMap; @@ -30,6 +31,7 @@ import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.builder.BuilderException; +import org.apache.ibatis.builder.annotation.ProviderContext; import org.apache.ibatis.builder.annotation.ProviderSqlSource; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; @@ -274,8 +276,10 @@ public void shouldGetUsersByNameWithParamName() { @Test public void methodNotFound() throws NoSuchMethodException { try { + Class mapperType = ErrorMapper.class; + Method mapperMethod = mapperType.getMethod("methodNotFound"); new ProviderSqlSource(new Configuration(), - ErrorMapper.class.getMethod("methodNotFound").getAnnotation(SelectProvider.class)); + mapperMethod.getAnnotation(SelectProvider.class), mapperType, mapperMethod); fail(); } catch (BuilderException e) { assertTrue(e.getMessage().contains("Error creating SqlSource for SqlProvider. Method 'methodNotFound' not found in SqlProvider 'org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder'.")); @@ -285,8 +289,10 @@ public void methodNotFound() throws NoSuchMethodException { @Test public void methodOverload() throws NoSuchMethodException { try { + Class mapperType = ErrorMapper.class; + Method mapperMethod = mapperType.getMethod("methodOverload", String.class); new ProviderSqlSource(new Configuration(), - ErrorMapper.class.getMethod("methodOverload", String.class).getAnnotation(SelectProvider.class)); + mapperMethod.getAnnotation(SelectProvider.class), mapperType, mapperMethod); fail(); } catch (BuilderException e) { assertTrue(e.getMessage().contains("Error creating SqlSource for SqlProvider. Method 'overload' is found multiple in SqlProvider 'org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder'. Sql provider method can not overload.")); @@ -296,18 +302,33 @@ public void methodOverload() throws NoSuchMethodException { @Test public void notSqlProvider() throws NoSuchMethodException { try { - new ProviderSqlSource(new Configuration(), new Object()); + new ProviderSqlSource(new Configuration(), new Object(), null, null); fail(); } catch (BuilderException e) { assertTrue(e.getMessage().contains("Error creating SqlSource for SqlProvider. Cause: java.lang.NoSuchMethodException: java.lang.Object.type()")); } } + @Test + public void multipleProviderContext() throws NoSuchMethodException { + try { + Class mapperType = ErrorMapper.class; + Method mapperMethod = mapperType.getMethod("multipleProviderContext"); + new ProviderSqlSource(new Configuration(), + mapperMethod.getAnnotation(SelectProvider.class), mapperType, mapperMethod); + fail(); + } catch (BuilderException e) { + assertTrue(e.getMessage().contains("Error creating SqlSource for SqlProvider. ProviderContext found multiple in SqlProvider method (org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder.multipleProviderContext). ProviderContext can not define multiple in SqlProvider method argument.")); + } + } + @Test public void notSupportParameterObjectOnMultipleArguments() throws NoSuchMethodException { try { + Class mapperType = Mapper.class; + Method mapperMethod = mapperType.getMethod("getUsersByName", String.class, String.class); new ProviderSqlSource(new Configuration(), - Mapper.class.getMethod("getUsersByName", String.class, String.class).getAnnotation(SelectProvider.class)) + mapperMethod.getAnnotation(SelectProvider.class), mapperType, mapperMethod) .getBoundSql(new Object()); fail(); } catch (BuilderException e) { @@ -318,8 +339,10 @@ public void notSupportParameterObjectOnMultipleArguments() throws NoSuchMethodEx @Test public void notSupportParameterObjectOnNamedArgument() throws NoSuchMethodException { try { + Class mapperType = Mapper.class; + Method mapperMethod = mapperType.getMethod("getUsersByNameWithParamName", String.class); new ProviderSqlSource(new Configuration(), - Mapper.class.getMethod("getUsersByNameWithParamName", String.class).getAnnotation(SelectProvider.class)) + mapperMethod.getAnnotation(SelectProvider.class), mapperType, mapperMethod) .getBoundSql(new Object()); fail(); } catch (BuilderException e) { @@ -330,8 +353,10 @@ public void notSupportParameterObjectOnNamedArgument() throws NoSuchMethodExcept @Test public void invokeError() throws NoSuchMethodException { try { + Class mapperType = ErrorMapper.class; + Method mapperMethod = mapperType.getMethod("invokeError"); new ProviderSqlSource(new Configuration(), - ErrorMapper.class.getMethod("invokeError").getAnnotation(SelectProvider.class)) + mapperMethod.getAnnotation(SelectProvider.class), mapperType, mapperMethod) .getBoundSql(new Object()); fail(); } catch (BuilderException e) { @@ -399,6 +424,54 @@ public void shouldDeleteUser() { } } + @Test + public void mapperProviderContextOnly() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + assertEquals("User4", mapper.selectById(4).getName()); + assertNull(mapper.selectActiveById(4)); + } finally { + sqlSession.close(); + } + } + + @Test + public void mapperOneParamAndProviderContext() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + assertEquals(1, mapper.selectByName("User4").size()); + assertEquals(0, mapper.selectActiveByName("User4").size()); + } finally { + sqlSession.close(); + } + } + + @Test + public void mapperMultipleParamAndProviderContextWithAtParam() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + assertEquals(1, mapper.selectByIdAndNameWithAtParam(4,"User4").size()); + assertEquals(0, mapper.selectActiveByIdAndNameWithAtParam(4,"User4").size()); + } finally { + sqlSession.close(); + } + } + + @Test + public void mapperMultipleParamAndProviderContext() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + assertEquals(1, mapper.selectByIdAndName(4,"User4").size()); + assertEquals(0, mapper.selectActiveByIdAndName(4,"User4").size()); + } finally { + sqlSession.close(); + } + } + public interface ErrorMapper { @SelectProvider(type = ErrorSqlBuilder.class, method = "methodNotFound") void methodNotFound(); @@ -408,6 +481,9 @@ public interface ErrorMapper { @SelectProvider(type = ErrorSqlBuilder.class, method = "invokeError") void invokeError(); + + @SelectProvider(type = ErrorSqlBuilder.class, method = "multipleProviderContext") + void multipleProviderContext(); } public static class ErrorSqlBuilder { @@ -426,6 +502,10 @@ public String overload(String value) { public String invokeError() { throw new UnsupportedOperationException("invokeError"); } + + public String multipleProviderContext(ProviderContext providerContext1, ProviderContext providerContext2) { + throw new UnsupportedOperationException("multipleProviderContext"); + } } } From eeed7a47852600dfb163f5b7c43db23d83029b18 Mon Sep 17 00:00:00 2001 From: Kazuki Shimizu Date: Thu, 27 Jul 2017 05:44:58 +0900 Subject: [PATCH 2/2] Add explanation for gh-1013 --- src/site/es/xdoc/java-api.xml | 5 +++-- src/site/ja/xdoc/java-api.xml | 4 ++-- src/site/ko/xdoc/java-api.xml | 7 ++++--- src/site/xdoc/java-api.xml | 6 ++++-- src/site/zh/xdoc/java-api.xml | 6 ++++-- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/site/es/xdoc/java-api.xml b/src/site/es/xdoc/java-api.xml index 3a6104eb3e0..3d00c479f03 100644 --- a/src/site/es/xdoc/java-api.xml +++ b/src/site/es/xdoc/java-api.xml @@ -1,7 +1,7 @@