From bb9c8f1e84cf4e1272a1f405e9ec26a750bda4fb Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Fri, 7 Nov 2025 16:41:58 -0500 Subject: [PATCH 1/2] Failing test for Type Handler Parsing This is a very simple failing test for #3562. --- .../ibatis/submitted/uuid_test/Mapper.java | 7 ++++++- .../ibatis/submitted/uuid_test/UUIDTest.java | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/ibatis/submitted/uuid_test/Mapper.java b/src/test/java/org/apache/ibatis/submitted/uuid_test/Mapper.java index e7797aa3f0b..f305cd8ad50 100644 --- a/src/test/java/org/apache/ibatis/submitted/uuid_test/Mapper.java +++ b/src/test/java/org/apache/ibatis/submitted/uuid_test/Mapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2022 the original author or authors. + * Copyright 2009-2025 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. @@ -15,12 +15,17 @@ */ package org.apache.ibatis.submitted.uuid_test; +import java.util.Map; import java.util.UUID; +import org.apache.ibatis.annotations.Insert; + public interface Mapper { User getUser(UUID id); void insertUser(User user); + @Insert("${sql}") + int insertDynamicUser(String sql, Map parameters); } diff --git a/src/test/java/org/apache/ibatis/submitted/uuid_test/UUIDTest.java b/src/test/java/org/apache/ibatis/submitted/uuid_test/UUIDTest.java index 745a8446d8a..195d033ea56 100644 --- a/src/test/java/org/apache/ibatis/submitted/uuid_test/UUIDTest.java +++ b/src/test/java/org/apache/ibatis/submitted/uuid_test/UUIDTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2024 the original author or authors. + * Copyright 2009-2025 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.uuid_test; import java.io.Reader; +import java.util.Map; import java.util.UUID; import org.apache.ibatis.BaseDataTest; @@ -64,4 +65,18 @@ void shouldInsertAUser() { } } + @Test + void shouldInsertAUserFullyDynamic() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Map parameters = Map.of("p1", UUID.randomUUID(), "p2", "User3"); + String sql = "insert into users values(" + + "#{parameters.p1,typeHandler=org.apache.ibatis.submitted.uuid_test.UUIDTypeHandler}, " + + "#{parameters.p2})"; + + int rows = mapper.insertDynamicUser(sql, parameters); + Assertions.assertEquals(1, rows); + } + } + } From 164a96cacfe84d604e5c9c98fd421edc55617a0c Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Mon, 10 Nov 2025 03:01:31 +0900 Subject: [PATCH 2/2] Respect the specified type handler Essentially reverting the condition back to the 3.5.x version. Plus, a minor refactoring (removed an unused method arg). --- src/main/java/org/apache/ibatis/builder/BaseBuilder.java | 5 ++--- .../apache/ibatis/builder/ParameterMappingTokenHandler.java | 4 ++-- .../java/org/apache/ibatis/builder/XmlMapperBuilderTest.java | 4 ++-- .../ibatis/submitted/language/VelocitySqlSourceBuilder.java | 2 +- .../LocallySpecifiedTypeHandlerResolutionTest.java | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/apache/ibatis/builder/BaseBuilder.java b/src/main/java/org/apache/ibatis/builder/BaseBuilder.java index 0bc49151406..8caec75d7a3 100644 --- a/src/main/java/org/apache/ibatis/builder/BaseBuilder.java +++ b/src/main/java/org/apache/ibatis/builder/BaseBuilder.java @@ -107,7 +107,7 @@ protected Class resolveClass(String alias) { @Deprecated(since = "3.6.0", forRemoval = true) protected TypeHandler resolveTypeHandler(Class javaType, String typeHandlerAlias) { - return resolveTypeHandler(null, javaType, null, typeHandlerAlias); + return resolveTypeHandler(javaType, null, typeHandlerAlias); } @Deprecated(since = "3.6.0", forRemoval = true) @@ -115,8 +115,7 @@ protected TypeHandler resolveTypeHandler(Class javaType, Class resolveTypeHandler(Class parameterType, Type propertyType, JdbcType jdbcType, - String typeHandlerAlias) { + protected TypeHandler resolveTypeHandler(Type propertyType, JdbcType jdbcType, String typeHandlerAlias) { Class> typeHandlerType = null; typeHandlerType = resolveClass(typeHandlerAlias); if (typeHandlerType != null && !TypeHandler.class.isAssignableFrom(typeHandlerType)) { diff --git a/src/main/java/org/apache/ibatis/builder/ParameterMappingTokenHandler.java b/src/main/java/org/apache/ibatis/builder/ParameterMappingTokenHandler.java index c9946a76949..84ee5d74628 100644 --- a/src/main/java/org/apache/ibatis/builder/ParameterMappingTokenHandler.java +++ b/src/main/java/org/apache/ibatis/builder/ParameterMappingTokenHandler.java @@ -95,8 +95,8 @@ private ParameterMapping buildParameterMapping(String content) { if (genericType == null) { genericType = javaType; } - if ((typeHandler == null || typeHandlerAlias != null) && genericType != null && genericType != Object.class) { - typeHandler = resolveTypeHandler(parameterType, genericType, jdbcType, typeHandlerAlias); + if (typeHandler == null || typeHandlerAlias != null) { + typeHandler = resolveTypeHandler(genericType, jdbcType, typeHandlerAlias); } builder.typeHandler(typeHandler); diff --git a/src/test/java/org/apache/ibatis/builder/XmlMapperBuilderTest.java b/src/test/java/org/apache/ibatis/builder/XmlMapperBuilderTest.java index 125253d28e7..267e0876e71 100644 --- a/src/test/java/org/apache/ibatis/builder/XmlMapperBuilderTest.java +++ b/src/test/java/org/apache/ibatis/builder/XmlMapperBuilderTest.java @@ -153,7 +153,7 @@ void resolveTypeHandlerTypeHandlerAliasIsNull() { { } }; - TypeHandler typeHandler = builder.resolveTypeHandler(String.class, null, null, (String) null); + TypeHandler typeHandler = builder.resolveTypeHandler(null, null, (String) null); assertThat(typeHandler).isNull(); } @@ -163,7 +163,7 @@ void resolveTypeHandlerNoAssignable() { { } }; - when(() -> builder.resolveTypeHandler(String.class, null, null, "integer")); + when(() -> builder.resolveTypeHandler(null, null, "integer")); then(caughtException()).isInstanceOf(BuilderException.class).hasMessage( "Type java.lang.Integer is not a valid TypeHandler because it does not implement TypeHandler interface"); } diff --git a/src/test/java/org/apache/ibatis/submitted/language/VelocitySqlSourceBuilder.java b/src/test/java/org/apache/ibatis/submitted/language/VelocitySqlSourceBuilder.java index 7c9fc1b8ef1..aac7f8b5bbd 100644 --- a/src/test/java/org/apache/ibatis/submitted/language/VelocitySqlSourceBuilder.java +++ b/src/test/java/org/apache/ibatis/submitted/language/VelocitySqlSourceBuilder.java @@ -134,7 +134,7 @@ private ParameterMapping buildParameterMapping(String content) { } } if (typeHandlerAlias != null) { - builder.typeHandler(resolveTypeHandler(javaType, propertyType, jdbcType, typeHandlerAlias)); + builder.typeHandler(resolveTypeHandler(propertyType, jdbcType, typeHandlerAlias)); } return builder.build(); } diff --git a/src/test/java/org/apache/ibatis/submitted/typebasedtypehandlerresolution/LocallySpecifiedTypeHandlerResolutionTest.java b/src/test/java/org/apache/ibatis/submitted/typebasedtypehandlerresolution/LocallySpecifiedTypeHandlerResolutionTest.java index 78de67d3b65..6ffff5f9898 100644 --- a/src/test/java/org/apache/ibatis/submitted/typebasedtypehandlerresolution/LocallySpecifiedTypeHandlerResolutionTest.java +++ b/src/test/java/org/apache/ibatis/submitted/typebasedtypehandlerresolution/LocallySpecifiedTypeHandlerResolutionTest.java @@ -309,7 +309,7 @@ void specifyHandlerInXmlParameterWithoutParameterType() { // There is no way to obtain info about type parameters. assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> sqlSession.insert( "org.apache.ibatis.submitted.typebasedtypehandlerresolution.LocallySpecifiedHandlerMapper.insertXmlWithoutParameterType", - user)).withMessageContaining("FuzzyBean cannot be cast to class java.lang.String"); + user)).withMessageContaining("Unknown rawType : class java.lang.Object"); } } }