From 452ba6b50f31e535ea0b4f513418b61894f2e141 Mon Sep 17 00:00:00 2001 From: Kazuki Shimizu Date: Sat, 8 Oct 2016 20:55:18 +0900 Subject: [PATCH 1/6] Support java.util.Optional as return type of mapper method --- .../apache/ibatis/binding/MapperMethod.java | 50 ++++++- .../annotation/MapperAnnotationBuilder.java | 9 ++ .../optional_on_mapper_method/CreateDB.sql | 25 ++++ .../optional_on_mapper_method/Mapper.java | 30 ++++ .../optional_on_mapper_method/Mapper.xml | 29 ++++ .../OptionalOnMapperMethodTest.java | 136 ++++++++++++++++++ .../optional_on_mapper_method/User.java | 38 +++++ .../mybatis-config.xml | 42 ++++++ 8 files changed, 354 insertions(+), 5 deletions(-) create mode 100644 src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/CreateDB.sql create mode 100644 src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.java create mode 100644 src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.xml create mode 100644 src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/OptionalOnMapperMethodTest.java create mode 100644 src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/User.java create mode 100644 src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/mybatis-config.xml diff --git a/src/main/java/org/apache/ibatis/binding/MapperMethod.java b/src/main/java/org/apache/ibatis/binding/MapperMethod.java index 6069c94c3c7..2fed2ea319f 100644 --- a/src/main/java/org/apache/ibatis/binding/MapperMethod.java +++ b/src/main/java/org/apache/ibatis/binding/MapperMethod.java @@ -18,6 +18,7 @@ import org.apache.ibatis.annotations.Flush; import org.apache.ibatis.annotations.MapKey; import org.apache.ibatis.cursor.Cursor; +import org.apache.ibatis.io.Resources; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.reflection.MetaObject; @@ -28,19 +29,29 @@ import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; +import java.lang.reflect.*; import java.util.*; /** * @author Clinton Begin * @author Eduardo Macarron * @author Lasse Voss + * @author Kazuki Shimizu */ public class MapperMethod { + private static Method optionalFactoryMethod = null; + + static { + try { + optionalFactoryMethod = Resources.classForName("java.util.Optional").getMethod("ofNullable", Object.class); + } catch (ClassNotFoundException e) { + // Ignore + } catch (NoSuchMethodException e) { + // Ignore + } + } + private final SqlCommand command; private final MethodSignature method; @@ -53,7 +64,7 @@ public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { case INSERT: { - Object param = method.convertArgsToSqlCommandParam(args); + Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); break; } @@ -80,6 +91,10 @@ public Object execute(SqlSession sqlSession, Object[] args) { } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); + if (method.returnsOptional() && + (result == null || !method.getReturnType().equals(result.getClass()))) { + result = wrapWithOptional(result); + } } break; case FLUSH: @@ -95,6 +110,20 @@ public Object execute(SqlSession sqlSession, Object[] args) { return result; } + private Object wrapWithOptional(Object result) { + if (optionalFactoryMethod == null) { + throw new BindingException("Can't use the java.util.Optional"); + } + try { + return optionalFactoryMethod.invoke(null, result); + } catch (IllegalAccessException e) { + throw new BindingException("Can't create a java.util.Optional instance.", e); + } catch (InvocationTargetException e) { + throw new BindingException("Can't create a java.util.Optional instance.", e); + } + } + + private Object rowCountResult(int rowCount) { final Object result; if (method.returnsVoid()) { @@ -246,6 +275,7 @@ public static class MethodSignature { private final boolean returnsMap; private final boolean returnsVoid; private final boolean returnsCursor; + private final boolean returnsOptional; private final Class returnType; private final String mapKey; private final Integer resultHandlerIndex; @@ -264,6 +294,7 @@ public MethodSignature(Configuration configuration, Class mapperInterface, Me this.returnsVoid = void.class.equals(this.returnType); this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray()); this.returnsCursor = Cursor.class.equals(this.returnType); + this.returnsOptional = "java.util.Optional".equals(this.returnType.getName()); this.mapKey = getMapKey(method); this.returnsMap = (this.mapKey != null); this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class); @@ -315,6 +346,15 @@ public boolean returnsCursor() { return returnsCursor; } + /** + * return whether return type is {@code java.util.Optional} + * @return return {@code true}, if return type is {@code java.util.Optional} + * @since 3.4.2 + */ + public boolean returnsOptional() { + return returnsOptional; + } + private Integer getUniqueParamIndex(Method method, Class paramType) { Integer index = null; final Class[] argTypes = method.getParameterTypes(); 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 629a0362918..1054370e475 100644 --- a/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java +++ b/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java @@ -88,6 +88,7 @@ /** * @author Clinton Begin + * @author Kazuki Shimizu */ public class MapperAnnotationBuilder { @@ -421,6 +422,14 @@ private Class getReturnType(Method method) { returnType = (Class) ((ParameterizedType) returnTypeParameter).getRawType(); } } + } else if ("java.util.Optional".equals(rawType.getName())) { + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + if (actualTypeArguments != null && actualTypeArguments.length == 1) { + Type returnTypeParameter = actualTypeArguments[0]; + if (returnTypeParameter instanceof Class) { + returnType = (Class) returnTypeParameter; + } + } } } diff --git a/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/CreateDB.sql b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/CreateDB.sql new file mode 100644 index 00000000000..54198b75f25 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/CreateDB.sql @@ -0,0 +1,25 @@ +-- +-- Copyright 2009-2016 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. +-- + +drop table users if exists; + +create table users ( + id int, + name varchar(20) +); + +insert into users (id, name) values +(1, 'User1'), (2, 'User2'); diff --git a/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.java b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.java new file mode 100644 index 00000000000..7944a7f7b6f --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.java @@ -0,0 +1,30 @@ +/** + * Copyright 2009-2016 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.usesjava8.optional_on_mapper_method; + +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Optional; + +public interface Mapper { + + @Select("select * from users where id = #{id}") + Optional getUserUsingAnnotation(Integer id); + + Optional getUserUsingXml(Integer id); + +} diff --git a/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.xml b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.xml new file mode 100644 index 00000000000..86622a9b590 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/Mapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/OptionalOnMapperMethodTest.java b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/OptionalOnMapperMethodTest.java new file mode 100644 index 00000000000..135e82a51c4 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/OptionalOnMapperMethodTest.java @@ -0,0 +1,136 @@ +/** + * Copyright 2009-2016 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.usesjava8.optional_on_mapper_method; + +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.jdbc.ScriptRunner; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.Reader; +import java.sql.Connection; +import java.util.Optional; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import static org.mockito.Mockito.*; + +/** + * Tests for support the {@code java.util.Optional} as return type of mapper method. + * + * @since 3.4.2 + * @author Kazuki Shimizu + */ +public class OptionalOnMapperMethodTest { + + private static SqlSessionFactory sqlSessionFactory; + + @BeforeClass + public static void setUp() throws Exception { + // create an SqlSessionFactory + Reader reader = Resources.getResourceAsReader( + "org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/mybatis-config.xml"); + sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + reader.close(); + + // populate in-memory database + SqlSession session = sqlSessionFactory.openSession(); + Connection conn = session.getConnection(); + reader = Resources.getResourceAsReader( + "org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/CreateDB.sql"); + ScriptRunner runner = new ScriptRunner(conn); + runner.setLogWriter(null); + runner.runScript(reader); + reader.close(); + session.close(); + } + + @Test + public void returnNotNullOnAnnotation() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Optional user = mapper.getUserUsingAnnotation(1); + assertTrue(user.isPresent()); + assertThat(user.get().getName(), is("User1")); + } finally { + sqlSession.close(); + } + } + + @Test + public void returnNullOnAnnotation() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Optional user = mapper.getUserUsingAnnotation(3); + assertFalse(user.isPresent()); + } finally { + sqlSession.close(); + } + } + + @Test + public void returnNotNullOnXml() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Optional user = mapper.getUserUsingXml(2); + assertTrue(user.isPresent()); + assertThat(user.get().getName(), is("User2")); + } finally { + sqlSession.close(); + } + } + + @Test + public void returnNullOnXml() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Optional user = mapper.getUserUsingXml(3); + assertFalse(user.isPresent()); + } finally { + sqlSession.close(); + } + } + + @Test + public void returnOptionalFromSqlSession() { + SqlSession sqlSession = Mockito.spy(sqlSessionFactory.openSession()); + + User mockUser = new User(); + mockUser.setName("mock user"); + Optional optionalMockUser = Optional.of(mockUser); + doReturn(optionalMockUser).when(sqlSession).selectOne(any(String.class), any(Object.class)); + + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Optional user = mapper.getUserUsingAnnotation(3); + assertTrue(user == optionalMockUser); + } finally { + sqlSession.close(); + } + } + +} diff --git a/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/User.java b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/User.java new file mode 100644 index 00000000000..5081c74c6cb --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/User.java @@ -0,0 +1,38 @@ +/** + * Copyright 2009-2016 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.usesjava8.optional_on_mapper_method; + +public class User { + + private Integer id; + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer 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/usesjava8/optional_on_mapper_method/mybatis-config.xml b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/mybatis-config.xml new file mode 100644 index 00000000000..e16f6850d12 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/usesjava8/optional_on_mapper_method/mybatis-config.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + From ad7101ef23f378aca358b945d79a477f3841025f Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 16 Jan 2018 02:22:48 +0900 Subject: [PATCH 2/6] Remove reflection. --- .../apache/ibatis/binding/MapperMethod.java | 38 +++---------------- .../org/apache/ibatis/reflection/Jdk.java | 16 +++++++- .../ibatis/reflection/OptionalUtil.java | 33 ++++++++++++++++ 3 files changed, 53 insertions(+), 34 deletions(-) create mode 100644 src/main/java/org/apache/ibatis/reflection/OptionalUtil.java diff --git a/src/main/java/org/apache/ibatis/binding/MapperMethod.java b/src/main/java/org/apache/ibatis/binding/MapperMethod.java index de7d102eb3b..1f0faa10ed2 100644 --- a/src/main/java/org/apache/ibatis/binding/MapperMethod.java +++ b/src/main/java/org/apache/ibatis/binding/MapperMethod.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. @@ -18,11 +18,12 @@ import org.apache.ibatis.annotations.Flush; import org.apache.ibatis.annotations.MapKey; import org.apache.ibatis.cursor.Cursor; -import org.apache.ibatis.io.Resources; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.mapping.StatementType; +import org.apache.ibatis.reflection.Jdk; import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.reflection.OptionalUtil; import org.apache.ibatis.reflection.ParamNameResolver; import org.apache.ibatis.reflection.TypeParameterResolver; import org.apache.ibatis.session.Configuration; @@ -44,18 +45,6 @@ */ public class MapperMethod { - private static Method optionalFactoryMethod = null; - - static { - try { - optionalFactoryMethod = Resources.classForName("java.util.Optional").getMethod("ofNullable", Object.class); - } catch (ClassNotFoundException e) { - // Ignore - } catch (NoSuchMethodException e) { - // Ignore - } - } - private final SqlCommand command; private final MethodSignature method; @@ -95,9 +84,8 @@ public Object execute(SqlSession sqlSession, Object[] args) { } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); - if (method.returnsOptional() && - (result == null || !method.getReturnType().equals(result.getClass()))) { - result = wrapWithOptional(result); + if (method.returnsOptional()) { + result = OptionalUtil.ofNullable(result); } } break; @@ -114,20 +102,6 @@ public Object execute(SqlSession sqlSession, Object[] args) { return result; } - private Object wrapWithOptional(Object result) { - if (optionalFactoryMethod == null) { - throw new BindingException("Can't use the java.util.Optional"); - } - try { - return optionalFactoryMethod.invoke(null, result); - } catch (IllegalAccessException e) { - throw new BindingException("Can't create a java.util.Optional instance.", e); - } catch (InvocationTargetException e) { - throw new BindingException("Can't create a java.util.Optional instance.", e); - } - } - - private Object rowCountResult(int rowCount) { final Object result; if (method.returnsVoid()) { @@ -321,7 +295,7 @@ public MethodSignature(Configuration configuration, Class mapperInterface, Me this.returnsVoid = void.class.equals(this.returnType); this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray(); this.returnsCursor = Cursor.class.equals(this.returnType); - this.returnsOptional = "java.util.Optional".equals(this.returnType.getName()); + this.returnsOptional = Jdk.optionalExists && Optional.class.equals(this.returnType); this.mapKey = getMapKey(method); this.returnsMap = this.mapKey != null; this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class); diff --git a/src/main/java/org/apache/ibatis/reflection/Jdk.java b/src/main/java/org/apache/ibatis/reflection/Jdk.java index f5b809badf6..a867dba6718 100644 --- a/src/main/java/org/apache/ibatis/reflection/Jdk.java +++ b/src/main/java/org/apache/ibatis/reflection/Jdk.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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.ibatis.reflection; import org.apache.ibatis.io.Resources; @@ -52,6 +51,19 @@ public class Jdk { dateAndTimeApiExists = available; } + public static final boolean optionalExists; + + static { + boolean available = false; + try { + Resources.classForName("java.util.Optional"); + available = true; + } catch (ClassNotFoundException e) { + // ignore + } + optionalExists = available; + } + private Jdk() { super(); } diff --git a/src/main/java/org/apache/ibatis/reflection/OptionalUtil.java b/src/main/java/org/apache/ibatis/reflection/OptionalUtil.java new file mode 100644 index 00000000000..699ccec6083 --- /dev/null +++ b/src/main/java/org/apache/ibatis/reflection/OptionalUtil.java @@ -0,0 +1,33 @@ +/** + * 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.reflection; + +import java.util.Optional; + +import org.apache.ibatis.lang.UsesJava8; + +public abstract class OptionalUtil { + + @UsesJava8 + public static Object ofNullable(Object value) { + return Optional.ofNullable(value); + } + + private OptionalUtil() { + super(); + } +} From 7ed1580a1c45989c3155ff7b4d20ae2f8df4c8ea Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 16 Jan 2018 02:32:10 +0900 Subject: [PATCH 3/6] Forgot to revert a line after local testing. --- src/main/java/org/apache/ibatis/binding/MapperMethod.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/ibatis/binding/MapperMethod.java b/src/main/java/org/apache/ibatis/binding/MapperMethod.java index 1f0faa10ed2..17678866a6c 100644 --- a/src/main/java/org/apache/ibatis/binding/MapperMethod.java +++ b/src/main/java/org/apache/ibatis/binding/MapperMethod.java @@ -84,7 +84,8 @@ public Object execute(SqlSession sqlSession, Object[] args) { } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); - if (method.returnsOptional()) { + if (method.returnsOptional() && + (result == null || !method.getReturnType().equals(result.getClass()))) { result = OptionalUtil.ofNullable(result); } } From 9ce0fcdce2ec30b5938cb07ccd26d8f5b7fd4a37 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 16 Jan 2018 03:13:58 +0900 Subject: [PATCH 4/6] Use clearer condition. --- src/main/java/org/apache/ibatis/binding/MapperMethod.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/ibatis/binding/MapperMethod.java b/src/main/java/org/apache/ibatis/binding/MapperMethod.java index 17678866a6c..25c704b932b 100644 --- a/src/main/java/org/apache/ibatis/binding/MapperMethod.java +++ b/src/main/java/org/apache/ibatis/binding/MapperMethod.java @@ -85,7 +85,7 @@ public Object execute(SqlSession sqlSession, Object[] args) { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); if (method.returnsOptional() && - (result == null || !method.getReturnType().equals(result.getClass()))) { + (result == null || !Optional.class.equals(result.getClass()))) { result = OptionalUtil.ofNullable(result); } } From 828d2830d2fca4f3db5e28572d99640c36917529 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 16 Jan 2018 04:13:34 +0900 Subject: [PATCH 5/6] Revert "Use clearer condition." This reverts commit 9ce0fcdce2ec30b5938cb07ccd26d8f5b7fd4a37. --- src/main/java/org/apache/ibatis/binding/MapperMethod.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/ibatis/binding/MapperMethod.java b/src/main/java/org/apache/ibatis/binding/MapperMethod.java index 25c704b932b..17678866a6c 100644 --- a/src/main/java/org/apache/ibatis/binding/MapperMethod.java +++ b/src/main/java/org/apache/ibatis/binding/MapperMethod.java @@ -85,7 +85,7 @@ public Object execute(SqlSession sqlSession, Object[] args) { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); if (method.returnsOptional() && - (result == null || !Optional.class.equals(result.getClass()))) { + (result == null || !method.getReturnType().equals(result.getClass()))) { result = OptionalUtil.ofNullable(result); } } From 091497365c9f5d01f482ee7d3184d8fc1a9c563e Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 16 Jan 2018 23:10:17 +0900 Subject: [PATCH 6/6] One more minor simplification. getActualTypeArguments() always returns an array with one element here, I think. --- .../annotation/MapperAnnotationBuilder.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 327bf35d815..0de88ae243e 100644 --- a/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java +++ b/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.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. @@ -31,6 +31,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Properties; import java.util.Set; @@ -80,6 +81,7 @@ import org.apache.ibatis.mapping.SqlSource; import org.apache.ibatis.mapping.StatementType; import org.apache.ibatis.parsing.PropertyParser; +import org.apache.ibatis.reflection.Jdk; import org.apache.ibatis.reflection.TypeParameterResolver; import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.session.Configuration; @@ -447,13 +449,11 @@ private Class getReturnType(Method method) { returnType = (Class) ((ParameterizedType) returnTypeParameter).getRawType(); } } - } else if ("java.util.Optional".equals(rawType.getName())) { + } else if (Jdk.optionalExists && Optional.class.equals(rawType)) { Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - if (actualTypeArguments != null && actualTypeArguments.length == 1) { - Type returnTypeParameter = actualTypeArguments[0]; - if (returnTypeParameter instanceof Class) { - returnType = (Class) returnTypeParameter; - } + Type returnTypeParameter = actualTypeArguments[0]; + if (returnTypeParameter instanceof Class) { + returnType = (Class) returnTypeParameter; } } }