Bean-Mapping mit MapStruct

Ähnliche Dokumente
Bean-Mapping mit MapStruct

Einfache Bean-Mappings mit MapStruct 1.2

Bean Mappings mit MapStruct 1.2

WER ERZÄHLT DIE NÄCHSTEN 55+ MINUTEN ETWAS?

Enterprise JavaBeans Überblick

Informatik II Übung 6

Java-Schulung Grundlagen

Properties und Proxies

Persistenz unter Kontrolle mit JDBI für Java

II.4.2 Abstrakte Klassen und Interfaces - 1 -

Programmiermethodik 3. Klausur Lösung

Rene Böing, Alexander Kuhn, Marc Wilmes Einführung in Spring und Hibernate

Java I Vorlesung 6 Referenz-Datentypen

Auszug aus JAX-WS Folien

Institut für Programmierung und Reaktive Systeme. Java 7. Markus Reschke

Gebundene Typparameter

Meta Programming and Reflection in Java

12 Abstrakte Klassen, finale Klassen und Interfaces

Einstieg in die Informatik mit Java

Programmieren in Java

Programmieren in Java

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen

Lambda Expressions in Java 8

Einstieg in die Informatik mit Java

FH D. Objektorientierte Programmierung in Java FH D FH D. Prof. Dr. Ing. André Stuhlsatz. Wiederholung: Gerüstbeispiel. Vererbungshierarchie: Typ 0

Programmieren I. Dr. Klaus Höppner. Hochschule Darmstadt Wintersemester 2009/ / 22

Faulheit professionell: Fertige Datenbehälter. Das Java-Collections-Framework Typsicherheit Generische Klassen

Oliver Paulus, 7. Februar Spring Framework Einführung. Oliver Paulus, Was ist Spring?

Kapitel 5: Interfaces

Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types)

Wie entwerfe ich ein Programm?

Übung 1: Object Inspector

EINFÜHRUNG IN DIE PROGRAMMIERUNG

Vererbung. CoMa-Übung XI TU Berlin. CoMa-Übung XI (TU Berlin) Vererbung / 47

Analyse und praktischer Vergleich von neuen Access- Layer-Technologien in modernen Webanwendungen unter Java. Oliver Kalz

Enterprise JavaBeans Überblick

Dynamische Typinformation A01 OOP. Dynamische Typinformation

Java Concurrency Utilities

Programmierung Nachklausurtutorium

Integration von Web Services in J EE Anwendungen mit XFire. 1/26 André Janus - Integration von Web Services in J EE Anwendungen mit XFire

ADT: Java Collections und ArrayList

Persistenz von Objekten relationale Datenbank Eigene Datenstruktur XML (JAXB) Proprietäre Dateiformate (Lochkarten)

Informatik II Übung 06. Benjamin Hepp 5 April 2017

Generisches Programmieren. Generisches Programmieren

14 Abstrakte Klassen, finale Klassen, Interfaces

Gliederung der Folien

Einführung in C# Teil 3. Matthias Nübling

Teil 5 - Java. Programmstruktur Operatoren Schlüsselwörter Datentypen

14 Abstrakte Klassen, finale Klassen, Interfaces. Auswertung von Ausdrücken. Beispiel. Abstrakte Methoden und Klassen

Theorie zu Übung 8 Implementierung in Java

14 Abstrakte Klassen, finale Klassen, Interfaces

Vorausgesetzte Grundkenntnisse. Inhalt. Klassenhierarchie und Vererbung. Vererbung. Klassenhierarchie und Vererbung. Einführung in C# Teil 3

EINFÜHRUNG IN DIE PROGRAMMIERUNG

Java Beans von Christian Beck-Wörner. Inhalt. Was ist ein Bean Konzept von Beans Entwicklung eines Beans Eigenschaften von Beans Testumgebung: BDK

II.4.5 Generische Datentypen - 1 -

4. Vererbung Die Klasse Object. Die Klasse Object

Java Reflection. Meta-Programmierung mit der java.lang.reflection API. Prof. Dr. Nikolaus Wulff

Java Idioms. Basic und Advanced Java Coding Style. Prof. Dr. Nikolaus Wulff

! 1. Unterklassen und Vererbung! 2. Abstrakte Klassen und Interfaces! 3. Modularität und Pakete. II.4.2 Abstrakte Klassen und Interfaces - 1 -

Universität Karlsruhe (TH)

Objektorientierte Programmierung. Kapitel 14: Interfaces

Übungsaufgabe Transaktion als Middleware

Übung 1 mit C# 6.0 MATTHIAS RONCORONI

JdbcTemplate

Klassen und Objekte. Einführung in Java. Folie 1 von Mai Ivo Kronenberg

Objektorientierte PL/SQL-Entwicklung Ein Erfahrungsbericht aus Sicht von JAVA-Entwicklern

Objektorientierte Programmierung Studiengang Medieninformatik

Methoden und Wrapperklassen

Programmierkurs Java

Polymorphie. 15. Java Objektorientierung II

Workshop Java Webentwicklung Einführung in Hibernate. Ulrich Stärk

1 Abstrakte Klassen, finale Klassen und Interfaces

Type Erasure in Java 5. Helmi Jouini Institut für Theoretische Informatik Universität Karlsruhe

Wie kann man es verhindern das Rad immer wieder erneut erfinden zu müssen?

Transkript:

Bean-Mapping mit MapStruct Thomas Much @thmuch www.muchsoft.com www.jughh.de 1

Java und Beans, eine lange Geschichte 1995 Form Beans 1998 DTOs 1999 POJOs 2000 JPA- Entities 2006 Typsicheres, schnelles Bean- Mapping! 1997 JavaBeans 2005 JAXB- Entities 2015 2

Alte Architekturen (J2EE) 3

Was Java EE 5+ und JPA versprechen 4

Die moderne Realität 5

Das erforderliche Mapping @Entity @Table(name = "KUNDEN") public class Kunde { @Id Long id; long kundennummer; String name; @Enumerated KundenArt kundenart; public class KundeDTO { long id; String kundennummer; String name; String kundenart; Getter und Setter! Getter und Setter! 6

kann aufwendig werden DTO JPA- Entity REST- Entity JAXB- Entity View- Bean 7

Mapping-Implementation wie? Selbst programmiert alle Getter/Setter von Hand aufrufen eigene Reflection-Routinen Reflection-Bibliotheken: Apache BeanUtils http://commons.apache.org/proper/commons-beanutils/ Dozer http://dozer.sourceforge.net/ Probleme: Aufwand, fehlende Typsicherheit, Performance 8

Performance Performance! https://twitter.com/joao_b_reis/status/559780053979250688 9

MapStruct MapStruct: http://mapstruct.org/ Annotations-Prozessor, der Mapping-Code generiert Keine Reflection! Typsicher und schnell Mind. Java 6, spezielle Unterstützung für Java 8 Minimale Laufzeitabhängigkeit (< 20 K) Je nach Komponentenmodell gar keine Abhängigkeit 10

Artefakte (Dependencies) http://mvnrepository.com/artifact/org.mapstruct http://sourceforge.net/projects/mapstruct/files/ 11

Beispiel JPA-Entity nach DTO Alle public-properties sollen gemappt werden (auch aus Oberklassen) @Entity @Table(name = "KUNDEN") public class Kunde { @Id Long id; long kundennummer; String name; @Enumerated KundenArt kundenart; public class KundeDTO { long id; String kundennummer; String name; String kundenart; Getter und Setter! Getter und Setter! 12

Beispiel Wünsch Dir was! import org.mapstruct.mapper; @Mapper(componentModel = "cdi") public interface KundeMapper { Kann global per Property festgelegt werden. Auch z.b. für Spring. KundeDTO kunde2kundedto(kunde kunde); @Inject private KundeMapper mapper; KundeDTO dto = mapper.kunde2kundedto( kunde ); 13

Beispiel Implementierung? Wie erzeugen wir aus dem Interface die Mapping-Implementierung? Speichern z.b. in Eclipse. Genauer: Compiler-Aufruf (geht also auch bei javac) Annotations-Prozessor erledigt den Rest! 14

Beispiel Live-Demo! Wie erzeugen wir aus dem Interface die Mapping-Implementierung? Speichern z.b. in Eclipse. Genauer: Compiler-Aufruf (geht also auch bei javac) Annotations-Prozessor erledigt den Rest! Live Demo 15

Beispiel generierter Code @Generated( value = "org.mapstruct.ap.mappingprocessor", date = "2016-03-04T21:56:55+0100", comments = "version: 1.0.0.Final, compiler: Eclipse JDT (IDE) " ) @ApplicationScoped public class KundeMapperImpl implements KundeMapper { @Override public KundeDTO kunde2kundedto(kunde kunde) { if ( kunde == null ) { return null; date- und comments- Attribute können unterdrückt werden Mapper sind Thread-sicher! KundeDTO kundedto = new KundeDTO(); kundedto.setname( kunde.getname() ); kundedto.setkundennummer( String.valueOf( kunde.getkundennummer() ) ); if ( kunde.getkundenart()!= null ) { kundedto.setkundenart( kunde.getkundenart().tostring() ); if ( kunde.getid()!= null ) { kundedto.setid( kunde.getid() ); return kundedto; 16

Kein Injection-Container? Kein Problem! import org.mapstruct.mapper; import org.mapstruct.factory.mappers; Dann wird ein kleines Runtime-JAR (ca. 16 K) benötigt. @Mapper(componentModel = "default") public interface KundeMapper { KundeMapper INSTANCE = Mappers.getMapper(KundeMapper.class); KundeDTO kunde2kundedto(kunde kunde); KundeDTO dto = KundeMapper.INSTANCE.kunde2KundeDto( kunde ); 17

Typsicherheit WARN/ERROR/IGNORE konfigurierbar (pro Mapper bzw. global) 18

Properties umbenennen, ignorieren, formatieren @Mapper public interface KundeMapper { @Mappings({ @Mapping(target = "kundennummer", source = "knr"), @Mapping(target = "name", ignore = true), @Mapping(target = "datum", dateformat = "dd.mm.yyyy") ) KundeDTO kunde2kundedto(kunde kunde); 19

Setter-Reihenfolge @Mapper public interface KundeMapper { @Mapping( target="kundennummer", dependson="kundenart") @Mapping( target="name", dependson={"vorname","nachname") KundeDTO kunde2kundedto(kunde kunde); setkundennummer() wird nach setkundenart() aufgerufen Keine zugesicherte Reihenfolge innerhalb des Arrays 20

Updates und Reverse Mappings @Mapper public interface KundeMapper { Alternativ Target- Typ als Rückgabe (für fluent-aufrufe) @Mappings({ ) KundeDTO kunde2kundedto(kunde kunde); void updatekundedto( Kunde kunde, @MappingTarget KundeDTO dto); Max. ein Mapping-Target Kunde kundedto2kunde(kundedto dto); 21

Mappings wiederverwenden @Mapper public interface KundeMapper { @Mappings({ ) KundeDTO kunde2kundedto(kunde kunde); @InheritConfiguration(name = "kunde2kundedto") @Mappings({ ) void updatekundedto( Kunde kunde, @MappingTarget KundeDTO dto); @InheritInverseConfiguration(name = "kunde2kundedto") @Mappings({ ) Kunde kundedto2kunde(kundedto dto); 22

Mappings (Konfigurationen) zentral definieren @MapperConfig( mappinginheritancestrategy= MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG ) public interface MeineKonfiguration { @Mappings({ ) BasisDTO entity2dto(basisentity entity); Hier wird noch kein Mapping-Code generiert! @Mapper(config=MeineKonfiguration.class) public interface KundeMapper { @Mappings({ ) KundeDTO kunde2kundedto(kunde kunde); 23

Objektgraphen mappen public class Kunde { Adresse adresse; public class KundeDTO { AdressDTO adresse; Getter und Setter! Getter und Setter! @Mapper public interface KundeMapper { KundeDTO kunde2kundedto(kunde kunde); AdresseDTO adresse2adressedto(adresse adresse); 24

Eigener Mapping-Code (1) @Mapper public abstract class KundeMapper { @Mappings({ ) public abstract KundeDTO kunde2kundedto(kunde k); public AdresseDTO adresse2adressedto(adresse adr) { eigener Mapping-Code Alternativ mit Interface und Java-8-Default-Methoden. 25

Eigener Mapping-Code (2) Eigene Mapping-Klasse muss dasselbe Komponentenmodell wie der MapStruct-Mapper verwenden oder einen Default-Konstruktor anbieten. @Mapper(uses=MeinAdresseMapper.class) public interface KundeMapper { @Mappings({ ) KundeDTO kunde2kundedto(kunde kunde); 26

Exceptions beim Mapping public class MeinAdresseMapper { public AdresseDTO adressetoadressedto(adresse adresse) throws AdresseException, SchwereException { Nicht deklarierte Checked-Exceptions werden als RuntimeExceptions weiter geworfen @Mapper(uses=MeinAdresseMapper.class) public interface KundeMapper { KundeDTO kunde2kundedto(kunde k) throws AdresseException; 27

Bean-Fabriken public class DtoFactory { public KundeDTO createkundedto() { return new KundeDTO(); public class EntityFactory { public <T extends BaseEntity> T createentity(@targettype Class<T> entityclass) { return entityclass.newinstance(); @Mapper(uses={DtoFactory.class, EntityFactory.class) public interface KundeMapper { KundeDTO kunde2kundedto(kunde kunde); Kunde kundedto2kunde(kundedto dto); 28

Mehrere Quell-Objekte Beans mixen @Mapper public interface KundeMapper { Bel. Verschachtelungstiefe (null-checks bei jedem Sprung) @Mapping(target="empfaengerName", source="kunde.name") @Mapping(target="postleitzahl", source="adresse.plz") @Mapping(target="gewichtInKg", source="gewicht") Lieferanschrift buildlieferanschrift( Kunde kunde, Adresse adresse, Integer gewicht); Bel. viele Quell-Parameter 29

null-mapping anpassen Bei null-quell-wert wird im Ziel standardmäßig null gesetzt. Mit nullvaluemappingstrategy = NullValueMappingStrategy.RETURN_DEFAULT werden stattdessen Default-Werte gesetzt (für primitive Type, Listen etc.) Verfügbar bei @Mapper etc. 30

Default-Werte und Konstanten @Mapper public interface KundeMapper { @Mapping(target="name", default="undefiniert") @Mapping(target="kundennummer", default="-1") @Mapping( target="beschreibung", constant="mein String") KundeDTO kunde2kundedto(kunde kunde); Auch für Zahlen, formatierte Datumswerte und selbstgeschriebene String2xxx-Mapper 31

Autom. (implizite) Typumwandlung Primitive Typen Wrapper (inkl. null-checks) int Integer etc. int/long/byte Integer etc. Primitive Typen & Wrapper String int/integer/boolean String etc. enum String BigInteger/BigDecimal Primitive/Wrapper/String 32

Autom. Typumwandlung (JAXB) JAXBElement<T> T List<JAXBElement<T>> List<T> XMLGregorianCalendar Date/Calendar 33

Autom. Typumwandlung (Datum+Zeit) Date/Calendar/XMLGregorianCalendar String / dateformat Joda String / dateformat Joda Date, Calendar java.time String / dateformat java.time Date, Calendar 34

Formatierung (Datum+Zeit) @Mapper public interface KundeMapper { @Mapping(source="geburtsdatum", dateformat="dd.mm.yyyy") KundeDTO kunde2kundedto(kunde kunde); @IterableMapping(dateFormat="dd.MM.yyyy") List<String> datelist2stringlist(list<date> list); Ebenso keydateformat @MapMapping(valueDateFormat="dd.MM.yyyy") Map<String,String> mapknrdatum(map<long,date> map); 35

Arrays und Collections @Mapper public interface KundeMapper { KundeDTO kunde2kundedto(kunde kunde); List<KundeDTO> kunden2dtos(list<kunde> kunden); KundeDTO[] kunden2dtos(kunde[] kunden); KundeDTO[] kundenlist2dtoarray(list<kunde> kunden); List<KundeDTO> kundenarray2dtolist(kunde[] kunden); Set<String> ints2strings(set<integer> ints); 36

Enum-Werte abbilden @Mapper public interface KundeMapper { KundeDTO kunde2kundedto(kunde kunde); @Mapping(target="EXPRESS", source="premium") @Mapping(target="EXPRESS", source="aktion") @Mapping(target="STANDARD", source="normal") DtoKundenArt kundenart2dtokundenart(kundenart art); 37

Viele weitere Möglichkeiten Anpassbar: Namen der generierten Packages und Impl-Klassen Namen der verwendeten Zugriffsmethoden (Getter/Setter/Adder etc.) Java-Expressions zur Target-Wert-Berechnung. Mehrdeutige Target-Bean-Typen per Qualifier auswählbar. Hooks für den Mapping-Lebenszyklus Decorators für Mapper (CDI, Spring) @BeforeMapping, @AfterMapping 38

Eclipse-Plugin https://github.com/mapstruct/mapstruct-eclipse/ Derzeit Code-Completion und einige Quick-Fixes. Refactoring-Support ist geplant. 39

MapStruct Fazit Hervorragend produktiv einsetzbar! Und wer Code-Generatoren nicht traut, kann zur Not den generierten Mapping-Code einchecken und von Hand weiterentwickeln. Generierter Code ist performant, einfach und lesbar. Flexible (Custom-)Mappings. Einfache Einbindung in div. Komponentenmodelle. Gute Dokumentation. 40

Neugierig geworden? http://mapstruct.org/ 41

Danke! 42

Fragen? Vielen Dank! thomas@muchsoft.com www.javabarista.de @thmuch 43