This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 192c99a5376 IGNITE-27963 Support fields from superclasses in manual 
mapping using MapperBuilder#map (#7658)
192c99a5376 is described below

commit 192c99a53768ae80b4941c083a9a3980cc2dc8a6
Author: Tiago Marques Godinho <[email protected]>
AuthorDate: Thu Feb 26 10:56:41 2026 +0000

    IGNITE-27963 Support fields from superclasses in manual mapping using 
MapperBuilder#map (#7658)
---
 .../apache/ignite/table/mapper/MapperBuilder.java  | 26 ++++++----
 .../internal/schema/marshaller/MarshallerTest.java |  1 +
 .../inheritance/parentwithprivatefield/Child.java  | 55 ++++++++++++++++++++++
 .../inheritance/parentwithprivatefield/Parent.java | 45 ++++++++++++++++++
 .../ignite/internal/marshaller/FieldAccessor.java  |  2 +-
 .../internal/schema/marshaller/MapperTest.java     | 20 ++++++++
 6 files changed, 139 insertions(+), 10 deletions(-)

diff --git 
a/modules/api/src/main/java/org/apache/ignite/table/mapper/MapperBuilder.java 
b/modules/api/src/main/java/org/apache/ignite/table/mapper/MapperBuilder.java
index 21038eb9000..06b69229bec 100644
--- 
a/modules/api/src/main/java/org/apache/ignite/table/mapper/MapperBuilder.java
+++ 
b/modules/api/src/main/java/org/apache/ignite/table/mapper/MapperBuilder.java
@@ -145,23 +145,31 @@ public final class MapperBuilder<T> {
     }
 
     /**
-     * Ensures a field name is valid and a field with the specified name 
exists.
+     * Ensures a field name is valid and a field with the specified name 
exists in the class hierarchy.
      *
      * @param fieldName Field name.
      * @return Field name for chaining.
      * @throws IllegalArgumentException If a field is {@code null} or if the 
class has no declared field with the given name.
      */
     private String requireValidField(String fieldName) {
-        try {
-            if (fieldName == null || targetType.getDeclaredField(fieldName) == 
null) {
-                throw new IllegalArgumentException("Mapping for a column 
already exists: " + fieldName);
-            }
-        } catch (NoSuchFieldException e) {
-            throw new IllegalArgumentException(
-                    String.format("Field not found for class: field=%s, 
class=%s", fieldName, targetType.getName()));
+        if (fieldName == null) {
+            throw new IllegalArgumentException("Mapping for a column already 
exists: " + fieldName);
         }
 
-        return fieldName;
+        Class<?> currType = targetType;
+        do {
+            try {
+                currType.getDeclaredField(fieldName);
+                return fieldName;
+            } catch (NoSuchFieldException ignored) {
+                // Intentionally left blank.
+            }
+
+            currType = currType.getSuperclass();
+        } while (currType != Object.class && currType != null);
+
+        throw new IllegalArgumentException(
+                String.format("Field not found for class: field=%s, class=%s", 
fieldName, targetType.getName()));
     }
 
     /**
diff --git 
a/modules/java-records-tests/src/test/java/org/apache/ignite/internal/schema/marshaller/MarshallerTest.java
 
b/modules/java-records-tests/src/test/java/org/apache/ignite/internal/schema/marshaller/MarshallerTest.java
index 3402948d238..cd5a2a4b9c3 100644
--- 
a/modules/java-records-tests/src/test/java/org/apache/ignite/internal/schema/marshaller/MarshallerTest.java
+++ 
b/modules/java-records-tests/src/test/java/org/apache/ignite/internal/schema/marshaller/MarshallerTest.java
@@ -181,6 +181,7 @@ class MarshallerTest extends BaseIgniteAbstractTest {
         assertMarshaller(new Inheritance.RegularParent.Child(1, "a", "b"));
         assertMarshaller(new Inheritance.MultipleParent.Child(1, "a", "b"));
         assertMarshaller(new Inheritance.ParentWithPrivateField.Child(1, "a", 
"b"));
+        assertMarshaller(new 
org.apache.ignite.internal.schema.marshaller.inheritance.parentwithprivatefield.Child(1,
 "a", "b"));
 
         // kvView
         assertMarshaller(new Kv.Key(1), new ChildV("a", "b"));
diff --git 
a/modules/java-records-tests/src/testFixtures/java/org/apache/ignite/internal/schema/marshaller/inheritance/parentwithprivatefield/Child.java
 
b/modules/java-records-tests/src/testFixtures/java/org/apache/ignite/internal/schema/marshaller/inheritance/parentwithprivatefield/Child.java
new file mode 100644
index 00000000000..67db8404d4d
--- /dev/null
+++ 
b/modules/java-records-tests/src/testFixtures/java/org/apache/ignite/internal/schema/marshaller/inheritance/parentwithprivatefield/Child.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ignite.internal.schema.marshaller.inheritance.parentwithprivatefield;
+
+import java.util.Objects;
+import org.apache.ignite.catalog.annotations.Column;
+
+/** Test class. */
+public class Child extends Parent {
+    @Column("val2")
+    String val2;
+
+    private Child() {
+    }
+
+    public Child(Integer key, String val, String val2) {
+        super(key, val);
+        this.val2 = val2;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        Child that = (Child) o;
+        return Objects.equals(getKey(), that.getKey())
+                && Objects.equals(this.getVal(), that.getVal())
+                && Objects.equals(this.val2, that.val2);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getKey(), getVal(), val2);
+    }
+}
diff --git 
a/modules/java-records-tests/src/testFixtures/java/org/apache/ignite/internal/schema/marshaller/inheritance/parentwithprivatefield/Parent.java
 
b/modules/java-records-tests/src/testFixtures/java/org/apache/ignite/internal/schema/marshaller/inheritance/parentwithprivatefield/Parent.java
new file mode 100644
index 00000000000..da9a0918073
--- /dev/null
+++ 
b/modules/java-records-tests/src/testFixtures/java/org/apache/ignite/internal/schema/marshaller/inheritance/parentwithprivatefield/Parent.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ignite.internal.schema.marshaller.inheritance.parentwithprivatefield;
+
+import org.apache.ignite.catalog.annotations.Column;
+
+/** Test class. */
+public class Parent {
+    @Column("key")
+    private Integer key;
+
+    @Column("val")
+    private String val;
+
+    Parent() {
+    }
+
+    Parent(Integer key, String val) {
+        this.key = key;
+        this.val = val;
+    }
+
+    Integer getKey() {
+        return key;
+    }
+
+    String getVal() {
+        return val;
+    }
+}
diff --git 
a/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java
 
b/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java
index f74b0360c29..a628736cf3b 100644
--- 
a/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java
+++ 
b/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java
@@ -92,7 +92,7 @@ abstract class FieldAccessor {
                 validateColumnType(col, field.getType());
             }
 
-            MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(type, 
MethodHandles.lookup());
+            MethodHandles.Lookup lookup = 
MethodHandles.privateLookupIn(field.getDeclaringClass(), 
MethodHandles.lookup());
             VarHandle varHandle = lookup.unreflectVarHandle(field);
 
             // Optimization for primitive types to avoid boxing/unboxing.
diff --git 
a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/MapperTest.java
 
b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/MapperTest.java
index ffc0fa73655..ef0c3552dd8 100644
--- 
a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/MapperTest.java
+++ 
b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/MapperTest.java
@@ -190,6 +190,20 @@ public class MapperTest {
             assertNull(mapper.fieldForColumn("STRINGCOL"));
             assertNull(mapper.fieldForColumn("VAL"));
         }
+
+        {
+            PojoMapper<TestObjectExt> mapper = (PojoMapper<TestObjectExt>) 
Mapper.of(
+                    TestObjectExt.class,
+                    "id", "col1",
+                    "ext", "col2"
+            );
+
+            assertEquals("id", mapper.fieldForColumn("COL1"));
+            assertEquals("ext", mapper.fieldForColumn("COL2"));
+            assertNull(mapper.fieldForColumn("STRINGCOL"));
+            assertNull(mapper.fieldForColumn("LONGCOL"));
+            assertNull(mapper.fieldForColumn("VAL"));
+        }
     }
 
     @Test
@@ -200,6 +214,7 @@ public class MapperTest {
 
         Function anonymous = (i) -> i;
 
+        Mapper.builder(TestObjectExt.class);
         Mapper.builder(TestOuterObject.class);
         Mapper.builder(NestedObject.class);
 
@@ -441,6 +456,11 @@ public class MapperTest {
         private String stringCol;
     }
 
+    @SuppressWarnings({"InstanceVariableMayNotBeInitialized", "unused"})
+    static class TestObjectExt extends TestObject {
+        private int ext;
+    }
+
     /**
      * Test object.
      */

Reply via email to