Mapping into existing object

MoxxiManagarm

Top Contributor
Hi,

ich suche ein Framework, welches mir erlaubt Daten von einem Objekt in ein anderes bestehendes zu kopieren und zu überschreiben. Ich habe viele Mapping Frameworks gefunden, aber die scheinen mir auf dem flüchtigen Blick nur neue Objekte zu erstellen jedoch nicht das gewünschte Update zu machen. Kennt jemand ein solches Framework?

Zum Verständnis nochmal...
Ich habe ein Objekt
Java:
class MyObject {
  private Long id;
  private String name;
  private EType type;
  // getter & setter...
}
Eine Instanz dieses Objects soll mir den Werten eines anderen Objects befüllt werden
Java:
class MyUpdateObject {
  private String name;
  // getter & setter...
}

Sinngemäß:
Java:
MyObject myObj = new MyObject(1000l, "foo", EType.AWESOME);
MyUpdateObject myUObj = new MyUpdateObject("bar");
someMapper.update(myObj, myUObj );
System.out.println(myObj); //--> 1000l, "bar", EType.AWESOME

Natürlich könnte ich die Methode selbst definieren. Aber da sich die Attribute ändern können und das für mehrere Objekte eingesetzt werden soll, würde ich gerne darauf verzichten wollen, bei jeder Änderung immer wieder auch das Mapping anpassen zu müssen. Die Änderungen sollten nur die Beans selbst betreffen.

Vielen dank im Voraus
MM
 
Wenn ich @MoxxiManagarm richtig verstanden habe, dann geht es doch nur darum, Werte deklarierter Felder eines Objekts in einem anderen Objekt zu setzen. Wäre das nicht einfacher, das selbst per Reflection zu schreiben, als sich MapStruct anzutun?
 
Ich hab das auch so verstanden, daß er Reflexion sucht.

Ich hab zwar keine Ahnung warum er das nicht über ordinäre Getter/Settermethoden macht (bzw. gehe ich bei Fremdcode davon aus, daß es seine Gründe hat, daß Membervariablen privat sind), aber seis drum.
 
Ich hab das auch so verstanden, daß er Reflexion sucht.

Ich hab zwar keine Ahnung warum er das nicht über ordinäre Getter/Settermethoden macht (bzw. gehe ich bei Fremdcode davon aus, daß es seine Gründe hat, daß Membervariablen privat sind), aber seis drum.
Du hast offenbar den Sinn der Frage nicht verstanden. Es geht darum Boilerplate Code zu sparen
 
Ich würde einen Einzeiler (mehr sind Getter/Setter ja in der Regel nicht) zwar nicht als Boilerplate Code bezeichnen, und sein letzter Absatz liest sich für mich auch nicht nach Vermeidung überflüssiger Redundanz, aber seis drum.

Und gerade wenn ich seinen Absatz noch einmal lese: Wäre ein Observermuster (bzw. dessen Implementierung) nicht sinnvoll?
 
Ich hab das auch so verstanden, daß er Reflexion sucht.
BTW: Er ist eine Sie 🙂

Zu MapStruct habe ich mittlerweile eine eigene Meinung (https://www.java-forum.org/thema/mapstruct-gruppierung-von-mapping.183919/). Entweder ist das Mapping so simpel, dass ich keine Lib brauche oder es ist so kompliziert, dass ich mir mit MapStruct nur zusätzliche Arbeit hole. Eine Klasse, die einfach Felder von einem Objekt in ein anderes kopiert, ist gleich geschrieben.

Und gerade wenn ich seinen Absatz noch einmal lese: Wäre ein Observermuster (bzw. dessen Implementierung) nicht sinnvoll?
Der Observer müsste ja angepasst werden. Es geht mMn einfach darum, Werte aus einem Objekt in ein anderes zu kopieren, ohne jedesmal Code schreiben oder anpassen zu müssen.
 
Ich wundere mich, warum der Dozermapper bisher nicht erwähnt wurde? Verstehe ich die Frage falsch oder ist die Technologie veraltet? Damit kann man auch in bestehnde Objekte reinschreiben.
 
BTW: Er ist eine Sie 🙂
Ganz genau 😀

Zu MapStruct habe ich mittlerweile eine eigene Meinung (https://www.java-forum.org/thema/mapstruct-gruppierung-von-mapping.183919/). Entweder ist das Mapping so simpel, dass ich keine Lib brauche oder es ist so kompliziert, dass ich mir mit MapStruct nur zusätzliche Arbeit hole. Eine Klasse, die einfach Felder von einem Objekt in ein anderes kopiert, ist gleich geschrieben.
Ich habe die letzte Woche genutzt hier ein wenig rumzuspielen und muss sagen ich bin auch kurz davor auf die Variante "ich schreib mir schnell eine Reflexion-basierte Klasse" umzusteigen. Ich kann für dieses spezielle Projekt ohne Probleme davon ausgehen, dass die Felder (und somit auch die getter/setter) sowohl in der Quelle als auch im Ziel den gleichen Namen haben. Ich danke aber allen für die Diskussion 🙂
 
Könnte so funktionieren:

Java:
import java.lang.reflect.*;

public class Mapper {

    private static Field findField(Class<?> clazz, Field field) {
        Class<?> c = clazz;
        do {
            for (Field f : c.getDeclaredFields()) {
                if (f.getName().equals(field.getName()) && 
                        f.getType().equals(field.getType())) {
                    return f;
                }
            }                
            c = c.getSuperclass();
        } while (c != null);
        return null;
    }

    private static void copy(Object source, Field sourceField,
            Object dest, Field destField) throws IllegalAccessException {
        if (sourceField.isSynthetic() || destField.isSynthetic() || 
                (destField.getModifiers() & Modifier.STATIC) != 0) {
            return;
        }

        boolean sourceAccessible = sourceField.isAccessible();
        boolean destAccessible = destField.isAccessible();
        sourceField.setAccessible(true);
        destField.setAccessible(true);
        try {
            destField.set(dest, sourceField.get(source));
        } finally {
            sourceField.setAccessible(sourceAccessible);
            destField.setAccessible(destAccessible);
        }
    }

    public static void update(Object source, Object dest) 
            throws IllegalAccessException {
        Class<?> sc = source.getClass();
        Class<?> dc = dest.getClass();
        for (Field sourceField : sc.getDeclaredFields()) {
            Field destField = findField(dc, sourceField);
            if (destField != null) {
                copy(source, sourceField, dest, destField);
            }
        }
    }
}
 
Ugh dann nimmst du mir ja sogar schon Arbeit ab 😀 Ich komme leider aktuell nicht dazu es einzubauen. Ich geb dir Rückmeldung dazu bei Gelegenheit 🙂
 

Zurück
Oben