UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Java】Java Bean Mappingライブラリ

Java Bean間のマッピングにMapStructを使っている

uga-box.hatenablog.com

他にどんなものがあるのか気になっていたが、下の記事にまとまっていたので、これをもとに自分でもまとめてみた

www.baeldung.com

Dozer

https://github.com/DozerMapper/dozer#what-is-dozer

Dozerは、再帰的に1つのオブジェクトから別のオブジェクトにデータをコピーするマッピングフレームワーク

単純なプロパティマッピング、意外にも様々なマッピングをサポートしている

コードサンプルはこんな感じ

public class Source {
    private String name;
    private int age;

    public Source() {}

    public Source(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // standard getters and setters
}
public class Dest {
    private String name;
    private int age;

    public Dest() {}

    public Dest(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // standard getters and setters
}
DozerBeanMapper mapper;

@Before
public void before() throws Exception {
    mapper = new DozerBeanMapper();
}

@Test
public void givenSourceObjectAndDestClass_whenMapsSameNameFieldsCorrectly_
  thenCorrect() {
    Source source = new Source("Baeldung", 10);
    Dest dest = mapper.map(source, Dest.class);

    assertEquals(dest.getName(), "Baeldung");
    assertEquals(dest.getAge(), 10);
}

@Test
public void givenSourceObjectAndDestObject_whenMapsSameNameFieldsCorrectly_
  thenCorrect() {
    Source source = new Source("Baeldung", 10);
    Dest dest = new Dest();
    mapper.map(source, dest);

    assertEquals(dest.getName(), "Baeldung");
    assertEquals(dest.getAge(), 10);
}

参考   https://www.baeldung.com/dozer

Orika

https://orika-mapper.github.io/orika-docs/

OrikaはDozerに似ているが、主な違いとして、Orikaはバイトコード生成を使用する

これにより、最小限のオーバーヘッドでより高速なマッパーを生成できるらしい

コードサンプル

public class Source {
    private String name;
    private int age;
    
    public Source(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // standard getters and setters
}
public class Dest {
    private String name;
    private int age;
    
    public Dest(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // standard getters and setters
}
@Test
public void givenSrcAndDest_whenMaps_thenCorrect() {
    mapperFactory.classMap(Source.class, Dest.class);
    MapperFacade mapper = mapperFactory.getMapperFacade();
    Source src = new Source("Baeldung", 10);
    Dest dest = mapper.map(src, Dest.class);

    assertEquals(dest.getAge(), src.getAge());
    assertEquals(dest.getName(), src.getName());
}

参考
https://www.baeldung.com/orika-mapping

MapStruct

MapStructは 、Beanマッパークラスを自動的に生成するコードジェネレーター 使用しているので割愛

参考
https://www.baeldung.com/mapstruct

ModelMapper

http://modelmapper.org/

ModelMapperは、規則に基づいて1つのオブジェクトモデルを別のオブジェクトモデルにどのようにマッピングされるかを自動的に決定することにより、オブジェクトマッピングを簡単にするフレームワーク

タイプセーフおよびリファクタリングセーフなAPIを提供している

サンプルコードはこんな感じ

// Assume getters and setters on each class
class Order {
  Customer customer;
  Address billingAddress;
}

class Customer {
  Name name;
}

class Name {
  String firstName;
  String lastName;
}

class Address {
  String street;
  String city;
}
// Assume getters and setters
class OrderDTO {
  String customerFirstName;
  String customerLastName;
  String billingStreet;
  String billingCity;
}
ModelMapper modelMapper = new ModelMapper();
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
assertEquals(order.getCustomer().getName().getFirstName(), orderDTO.getCustomerFirstName());
assertEquals(order.getCustomer().getName().getLastName(), orderDTO.getCustomerLastName());
assertEquals(order.getBillingAddress().getStreet(), orderDTO.getBillingStreet());
assertEquals(order.getBillingAddress().getCity(), orderDTO.getBillingCity());

JMapper

https://github.com/jmapper-framework/jmapper-core/wiki

JMapperは、JavaBean間で使いやすく高性能なマッピングを提供することを目的としたマッピングフレームワーク

アノテーションとリレーショナルマッピングを使用してDRYの原則を適用することを目的としている

JMapperでは次のことが可能(Github READMEより)

  • ターゲットオブジェクトを作成して強化する
  • マッピングに特定のロジックを適用する
  • 複雑で再帰的なマッピングを実行する
  • さまざまなタイプの暗黙的および明示的な関係を管理する
  • 明示的な変換を実装する
  • アノテーションxmlAPIを使用してマッピングを構成する
  • 継承された構成も適用する
  • 一連のユーティリティメソッドを使用して、すばやく簡単なxml構成ファイルを作成します
  • カスタムバイトコードジェネレータを定義する

まとめ

実際使ってないから詳しいことはわからないが、こんだけ似たようなライブラリがあることがわかった

ただ、MapStructだけちょっと経路が違くて、Interfaceを定義すると自動で実装クラスを生成する

実装クラスがあるので、どのようなマッピングになっているか追いやすくてよいなと感じている

いまのところMapStruct便利と思っているので使い続けてみる