From 6393e0c631b10859f9591a02f1b531c007e54872 Mon Sep 17 00:00:00 2001 From: guanchengang <1620522809@qq.com> Date: Thu, 16 Oct 2025 16:42:10 +0800 Subject: [PATCH 1/2] fix: Reflector should reflect record --- .../apache/ibatis/reflection/Reflector.java | 19 ++++++++++++++----- .../ibatis/reflection/ReflectorTest.java | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/apache/ibatis/reflection/Reflector.java b/src/main/java/org/apache/ibatis/reflection/Reflector.java index 35f1a93c14f..515cace7941 100644 --- a/src/main/java/org/apache/ibatis/reflection/Reflector.java +++ b/src/main/java/org/apache/ibatis/reflection/Reflector.java @@ -76,10 +76,10 @@ public Reflector(Type type) { this.clazz = (Class) type; } addDefaultConstructor(clazz); - Method[] classMethods = getClassMethods(clazz); if (isRecord(clazz)) { - addRecordGetMethods(classMethods); + addRecordGetMethods(clazz); } else { + Method[] classMethods = getClassMethods(clazz); addGetMethods(classMethods); addSetMethods(classMethods); addFields(clazz); @@ -94,9 +94,18 @@ public Reflector(Type type) { } } - private void addRecordGetMethods(Method[] methods) { - Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0) - .forEach(m -> addGetMethod(m.getName(), m, false)); + private void addRecordGetMethods(Class recordClass) { + Arrays.stream(recordClass.getDeclaredFields()).filter(field -> !Modifier.isStatic(field.getModifiers())) + .forEach(field -> { + try { + String fieldName = field.getName(); + // record's get method and field have the same name + Method m = recordClass.getMethod(fieldName); + addGetMethod(fieldName, m, false); + } catch (NoSuchMethodException ignore) { + // A standard record can never throw this exception + } + }); } private void addDefaultConstructor(Class clazz) { diff --git a/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java b/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java index 1b09ba18c1e..63c94e551c6 100644 --- a/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java +++ b/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java @@ -406,4 +406,20 @@ public Foo getFoo() { assertEquals(Foo.class, setter.getRawType()); assertArrayEquals(new Type[] { String.class }, setter.getActualTypeArguments()); } + + @Test + void shouldReflectRecord() throws Exception { + record User(Long id, String name, List props) { + @SuppressWarnings("unused") + public int foo() { + return 1; + } + } + + ReflectorFactory reflectorFactory = new DefaultReflectorFactory(); + Reflector reflector = reflectorFactory.findForClass(User.class); + List property = Arrays.asList(reflector.getGetablePropertyNames()); + assertEquals(3, property.size()); + assertTrue(property.containsAll(Arrays.asList("id", "name", "props"))); + } } From c9c637dc227cce579313454945bd4ddd178e9c5f Mon Sep 17 00:00:00 2001 From: guanchengang <1620522809@qq.com> Date: Sat, 13 Dec 2025 16:29:43 +0800 Subject: [PATCH 2/2] add an extra check for shouldReflectRecord --- src/test/java/org/apache/ibatis/reflection/ReflectorTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java b/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java index 63c94e551c6..27255d015ab 100644 --- a/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java +++ b/src/test/java/org/apache/ibatis/reflection/ReflectorTest.java @@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; import java.io.Serializable; import java.lang.reflect.ParameterizedType; @@ -421,5 +422,8 @@ public int foo() { List property = Arrays.asList(reflector.getGetablePropertyNames()); assertEquals(3, property.size()); assertTrue(property.containsAll(Arrays.asList("id", "name", "props"))); + assertFalse(property.contains("toString")); + assertFalse(property.contains("hashCode")); + assertFalse(property.contains("foo")); } }