From b30d260d4a044353a4ae2989c362ba1896357209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=92=A9=E5=92=A9?= <469517790@qq.com> Date: Wed, 31 Mar 2021 16:43:59 +0800 Subject: [PATCH 1/4] give TypeHandler a chance to get class type of result --- .../result/ResultClassTypeHolder.java | 19 ++++++ .../resultset/DefaultResultSetHandler.java | 3 + .../ibatis/builder/CustomLongTypeHandler.java | 5 ++ .../type/CostomLongTypeHandlerTest.java | 68 +++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 src/main/java/org/apache/ibatis/executor/result/ResultClassTypeHolder.java create mode 100644 src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java diff --git a/src/main/java/org/apache/ibatis/executor/result/ResultClassTypeHolder.java b/src/main/java/org/apache/ibatis/executor/result/ResultClassTypeHolder.java new file mode 100644 index 00000000000..c689f268672 --- /dev/null +++ b/src/main/java/org/apache/ibatis/executor/result/ResultClassTypeHolder.java @@ -0,0 +1,19 @@ +package org.apache.ibatis.executor.result; + +public class ResultClassTypeHolder { + + // hold the the class type of result + private static final ThreadLocal resultTypeTl = new ThreadLocal(); + + public static void setResultType(Class clazz) { + resultTypeTl.set(clazz); + } + + public static Class getResultType() { + return resultTypeTl.get(); + } + + public static void clean() { + resultTypeTl.remove(); + } +} diff --git a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java index 5e5461b3b71..5a8b844c883 100644 --- a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java +++ b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java @@ -41,6 +41,7 @@ import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.executor.result.DefaultResultContext; import org.apache.ibatis.executor.result.DefaultResultHandler; +import org.apache.ibatis.executor.result.ResultClassTypeHolder; import org.apache.ibatis.executor.result.ResultMapException; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.Discriminator; @@ -293,6 +294,7 @@ private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) { private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List multipleResults, ResultMapping parentMapping) throws SQLException { try { + ResultClassTypeHolder.setResultType(resultMap.getType()); if (parentMapping != null) { handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping); } else { @@ -307,6 +309,7 @@ private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List { @@ -34,6 +38,7 @@ public void setParameter(PreparedStatement ps, int i, Long parameter, JdbcType j @Override public Long getResult(ResultSet rs, String columnName) throws SQLException { + assertNull(ResultClassTypeHolder.getResultType()); return rs.getLong(columnName); } diff --git a/src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java b/src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java new file mode 100644 index 00000000000..2e8b8173780 --- /dev/null +++ b/src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java @@ -0,0 +1,68 @@ +package org.apache.ibatis.type; + +import org.apache.ibatis.builder.CustomLongTypeHandler; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class CostomLongTypeHandlerTest extends BaseTypeHandlerTest{ + private static final TypeHandler TYPE_HANDLER = new CustomLongTypeHandler(); + + @Override + @Test + public void shouldSetParameter() throws Exception { + TYPE_HANDLER.setParameter(ps, 1, 100L, null); + verify(ps).setLong(1, 100L); + } + + @Override + @Test + public void shouldGetResultFromResultSetByName() throws Exception { + when(rs.getLong("column")).thenReturn(100L, 0L); + assertEquals(Long.valueOf(100L), TYPE_HANDLER.getResult(rs, "column")); + assertEquals(Long.valueOf(0L), TYPE_HANDLER.getResult(rs, "column")); + } + + @Override + @Test + public void shouldGetResultNullFromResultSetByName() throws Exception { + when(rs.getLong("column")).thenReturn(0L); + when(rs.wasNull()).thenReturn(true); + assertNull(TYPE_HANDLER.getResult(rs, "column")); + } + + @Override + @Test + public void shouldGetResultFromResultSetByPosition() throws Exception { + when(rs.getLong(1)).thenReturn(100L, 0L); + assertEquals(Long.valueOf(100L), TYPE_HANDLER.getResult(rs, 1)); + assertEquals(Long.valueOf(0L), TYPE_HANDLER.getResult(rs, 1)); + } + + @Override + @Test + public void shouldGetResultNullFromResultSetByPosition() throws Exception { + when(rs.getLong(1)).thenReturn(0L); + when(rs.wasNull()).thenReturn(true); + assertNull(TYPE_HANDLER.getResult(rs, 1)); + } + + @Override + @Test + public void shouldGetResultFromCallableStatement() throws Exception { + when(cs.getLong(1)).thenReturn(100L, 0L); + assertEquals(Long.valueOf(100L), TYPE_HANDLER.getResult(cs, 1)); + assertEquals(Long.valueOf(0L), TYPE_HANDLER.getResult(cs, 1)); + } + + @Override + @Test + public void shouldGetResultNullFromCallableStatement() throws Exception { + when(cs.getLong(1)).thenReturn(0L); + when(cs.wasNull()).thenReturn(true); + assertNull(TYPE_HANDLER.getResult(cs, 1)); + } +} From ca188a2504ed34237873515a4596bb755b07b49c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=92=A9=E5=92=A9?= <469517790@qq.com> Date: Wed, 31 Mar 2021 18:41:47 +0800 Subject: [PATCH 2/4] test case --- .../autoconstructor/AutoConstructorTest.java | 6 ++++ .../ibatis/autoconstructor/BadSubject.java | 8 ++++- .../ibatis/autoconstructor/CreateDB.sql | 9 ++--- .../ibatis/builder/CustomLongTypeHandler.java | 13 +++---- .../builder/typehandler/WidthTypeHandler.java | 36 +++++++++++++++++++ 5 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 src/test/java/org/apache/ibatis/builder/typehandler/WidthTypeHandler.java diff --git a/src/test/java/org/apache/ibatis/autoconstructor/AutoConstructorTest.java b/src/test/java/org/apache/ibatis/autoconstructor/AutoConstructorTest.java index 4516e1bedb8..8429bf22a6f 100644 --- a/src/test/java/org/apache/ibatis/autoconstructor/AutoConstructorTest.java +++ b/src/test/java/org/apache/ibatis/autoconstructor/AutoConstructorTest.java @@ -22,11 +22,14 @@ import java.util.List; import org.apache.ibatis.BaseDataTest; +import org.apache.ibatis.builder.typehandler.WidthTypeHandler; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.io.Resources; +import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.apache.ibatis.type.TypeHandlerRegistry; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -73,6 +76,9 @@ void annotatedSubject() { @Test void badSubject() { + Configuration configuration = sqlSessionFactory.getConfiguration(); + final TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry(); + registry.register(BadSubject.Width.class, WidthTypeHandler.class); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { final AutoConstructorMapper mapper = sqlSession.getMapper(AutoConstructorMapper.class); assertThrows(PersistenceException.class, mapper::getBadSubjects); diff --git a/src/test/java/org/apache/ibatis/autoconstructor/BadSubject.java b/src/test/java/org/apache/ibatis/autoconstructor/BadSubject.java index 33e2481fef7..91e95178d63 100644 --- a/src/test/java/org/apache/ibatis/autoconstructor/BadSubject.java +++ b/src/test/java/org/apache/ibatis/autoconstructor/BadSubject.java @@ -21,16 +21,22 @@ public class BadSubject { private final int age; private final Height height; private final Double weight; + private final Width width; - public BadSubject(final int id, final String name, final int age, final Height height, final Double weight) { + public BadSubject(final int id, final String name, final int age, final Height height, final Double weight, final Width width) { this.id = id; this.name = name; this.age = age; this.height = height; this.weight = weight == null ? 0 : weight; + this.width = width; } private class Height { } + + public static class Width { + + } } diff --git a/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql b/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql index 9f885c25b31..65da84a342d 100644 --- a/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql +++ b/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql @@ -26,6 +26,7 @@ CREATE TABLE subject ( age INT NOT NULL, height INT, weight INT, + width INT, active BIT, dt TIMESTAMP ); @@ -47,12 +48,12 @@ CREATE TABLE extensive_subject ( ); INSERT INTO subject VALUES - (1, 'a', 10, 100, 45, 1, CURRENT_TIMESTAMP), - (2, 'b', 10, NULL, 45, 1, CURRENT_TIMESTAMP), - (2, 'c', 10, NULL, NULL, 0, CURRENT_TIMESTAMP); + (1, 'a', 10, 100, 45, 50, 1, CURRENT_TIMESTAMP), + (2, 'b', 10, NULL, 45, 50, 1, CURRENT_TIMESTAMP), + (2, 'c', 10, NULL, NULL,Null, 0, CURRENT_TIMESTAMP); INSERT INTO extensive_subject VALUES (1, 1, 'a', 1, 1, 1, 1.0, 1, 'a', 'AVALUE', 'ACLOB', 'aaaaaabbbbbb', CURRENT_TIMESTAMP), (2, 2, 'b', 2, 2, 2, 2.0, 2, 'b', 'BVALUE', 'BCLOB', '010101010101', CURRENT_TIMESTAMP), - (3, 3, 'c', 3, 3, 3, 3.0, 3, 'c', 'CVALUE', 'CCLOB', '777d010078da', CURRENT_TIMESTAMP); \ No newline at end of file + (3, 3, 'c', 3, 3, 3, 3.0, 3, 'c', 'CVALUE', 'CCLOB', '777d010078da', CURRENT_TIMESTAMP); diff --git a/src/test/java/org/apache/ibatis/builder/CustomLongTypeHandler.java b/src/test/java/org/apache/ibatis/builder/CustomLongTypeHandler.java index 644ef24e207..3f1491ef96a 100644 --- a/src/test/java/org/apache/ibatis/builder/CustomLongTypeHandler.java +++ b/src/test/java/org/apache/ibatis/builder/CustomLongTypeHandler.java @@ -15,18 +15,14 @@ */ package org.apache.ibatis.builder; -import java.lang.reflect.Field; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.apache.ibatis.executor.result.ResultClassTypeHolder; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedTypes; import org.apache.ibatis.type.TypeHandler; -import static org.junit.jupiter.api.Assertions.assertNull; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; @MappedTypes(Long.class) public class CustomLongTypeHandler implements TypeHandler { @@ -38,7 +34,6 @@ public void setParameter(PreparedStatement ps, int i, Long parameter, JdbcType j @Override public Long getResult(ResultSet rs, String columnName) throws SQLException { - assertNull(ResultClassTypeHolder.getResultType()); return rs.getLong(columnName); } diff --git a/src/test/java/org/apache/ibatis/builder/typehandler/WidthTypeHandler.java b/src/test/java/org/apache/ibatis/builder/typehandler/WidthTypeHandler.java new file mode 100644 index 00000000000..a2321d0a399 --- /dev/null +++ b/src/test/java/org/apache/ibatis/builder/typehandler/WidthTypeHandler.java @@ -0,0 +1,36 @@ +package org.apache.ibatis.builder.typehandler; + +import org.apache.ibatis.autoconstructor.BadSubject; +import org.apache.ibatis.executor.result.ResultClassTypeHolder; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.junit.Assert; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class WidthTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, BadSubject.Width parameter, JdbcType jdbcType) throws SQLException { + + } + + @Override + public BadSubject.Width getNullableResult(ResultSet rs, String columnName) throws SQLException { + Assert.assertNotNull(ResultClassTypeHolder.getResultType()); + return new BadSubject.Width(); + } + + @Override + public BadSubject.Width getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return new BadSubject.Width(); + } + + @Override + public BadSubject.Width getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return new BadSubject.Width(); + } +} From af3908c88bf9e0f34713c589942f82c22aaf4c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=92=A9=E5=92=A9?= <469517790@qq.com> Date: Wed, 31 Mar 2021 18:53:00 +0800 Subject: [PATCH 3/4] test case --- .../ibatis/autoconstructor/CreateDB.sql | 10 +-- .../type/CostomLongTypeHandlerTest.java | 68 ------------------- 2 files changed, 5 insertions(+), 73 deletions(-) delete mode 100644 src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java diff --git a/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql b/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql index 65da84a342d..ffc66b13e18 100644 --- a/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql +++ b/src/test/java/org/apache/ibatis/autoconstructor/CreateDB.sql @@ -26,9 +26,9 @@ CREATE TABLE subject ( age INT NOT NULL, height INT, weight INT, - width INT, active BIT, - dt TIMESTAMP + dt TIMESTAMP, + width INT ); CREATE TABLE extensive_subject ( @@ -48,9 +48,9 @@ CREATE TABLE extensive_subject ( ); INSERT INTO subject VALUES - (1, 'a', 10, 100, 45, 50, 1, CURRENT_TIMESTAMP), - (2, 'b', 10, NULL, 45, 50, 1, CURRENT_TIMESTAMP), - (2, 'c', 10, NULL, NULL,Null, 0, CURRENT_TIMESTAMP); + (1, 'a', 10, 100, 45, 1, CURRENT_TIMESTAMP, 50), + (2, 'b', 10, NULL, 45, 1, CURRENT_TIMESTAMP, 50), + (2, 'c', 10, NULL, NULL, 0, CURRENT_TIMESTAMP, 50); INSERT INTO extensive_subject VALUES diff --git a/src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java b/src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java deleted file mode 100644 index 2e8b8173780..00000000000 --- a/src/test/java/org/apache/ibatis/type/CostomLongTypeHandlerTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.apache.ibatis.type; - -import org.apache.ibatis.builder.CustomLongTypeHandler; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class CostomLongTypeHandlerTest extends BaseTypeHandlerTest{ - private static final TypeHandler TYPE_HANDLER = new CustomLongTypeHandler(); - - @Override - @Test - public void shouldSetParameter() throws Exception { - TYPE_HANDLER.setParameter(ps, 1, 100L, null); - verify(ps).setLong(1, 100L); - } - - @Override - @Test - public void shouldGetResultFromResultSetByName() throws Exception { - when(rs.getLong("column")).thenReturn(100L, 0L); - assertEquals(Long.valueOf(100L), TYPE_HANDLER.getResult(rs, "column")); - assertEquals(Long.valueOf(0L), TYPE_HANDLER.getResult(rs, "column")); - } - - @Override - @Test - public void shouldGetResultNullFromResultSetByName() throws Exception { - when(rs.getLong("column")).thenReturn(0L); - when(rs.wasNull()).thenReturn(true); - assertNull(TYPE_HANDLER.getResult(rs, "column")); - } - - @Override - @Test - public void shouldGetResultFromResultSetByPosition() throws Exception { - when(rs.getLong(1)).thenReturn(100L, 0L); - assertEquals(Long.valueOf(100L), TYPE_HANDLER.getResult(rs, 1)); - assertEquals(Long.valueOf(0L), TYPE_HANDLER.getResult(rs, 1)); - } - - @Override - @Test - public void shouldGetResultNullFromResultSetByPosition() throws Exception { - when(rs.getLong(1)).thenReturn(0L); - when(rs.wasNull()).thenReturn(true); - assertNull(TYPE_HANDLER.getResult(rs, 1)); - } - - @Override - @Test - public void shouldGetResultFromCallableStatement() throws Exception { - when(cs.getLong(1)).thenReturn(100L, 0L); - assertEquals(Long.valueOf(100L), TYPE_HANDLER.getResult(cs, 1)); - assertEquals(Long.valueOf(0L), TYPE_HANDLER.getResult(cs, 1)); - } - - @Override - @Test - public void shouldGetResultNullFromCallableStatement() throws Exception { - when(cs.getLong(1)).thenReturn(0L); - when(cs.wasNull()).thenReturn(true); - assertNull(TYPE_HANDLER.getResult(cs, 1)); - } -} From 65a3c24e4b59ae53b569cb7f157dd974b5e85879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=92=A9=E5=92=A9?= <469517790@qq.com> Date: Thu, 1 Apr 2021 09:11:51 +0800 Subject: [PATCH 4/4] test case --- .../executor/ResultClassTypeHolderTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/java/org/apache/ibatis/executor/ResultClassTypeHolderTest.java diff --git a/src/test/java/org/apache/ibatis/executor/ResultClassTypeHolderTest.java b/src/test/java/org/apache/ibatis/executor/ResultClassTypeHolderTest.java new file mode 100644 index 00000000000..0335cd98c87 --- /dev/null +++ b/src/test/java/org/apache/ibatis/executor/ResultClassTypeHolderTest.java @@ -0,0 +1,25 @@ +package org.apache.ibatis.executor; + +import org.apache.ibatis.executor.result.ResultClassTypeHolder; +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +public class ResultClassTypeHolderTest { + + @Test + public void getResultClassFromTl() { + try { + ResultClassTypeHolder.setResultType(Object.class); + getResultClass(); + }finally { + ResultClassTypeHolder.clean(); + } + + } + + private void getResultClass() { + Class aClass = ResultClassTypeHolder.getResultType(); + Assert.assertNotNull(aClass); + } + +}