1. 概要

このチュートリアルでは、 JMapper 高速で使いやすいマッピングフレームワークについて説明します。

JMapperを構成するさまざまな方法、カスタム変換を実行する方法、およびリレーショナルマッピングについて説明します。

2. Maven構成

まず、JMapper依存関係pom.xmlに追加する必要があります。

<dependency>
    <groupId>com.googlecode.jmapper-framework</groupId>
    <artifactId>jmapper-core</artifactId>
    <version>1.6.0.1</version>
</dependency>

3. ソースモデルと宛先モデル

構成に入る前に、このチュートリアル全体で使用する単純なBeanを見てみましょう。

まず、ソースbean –基本的なユーザーは次のとおりです。

public class User {
    private long id;    
    private String email;
    private LocalDate birthDate;
}

そして、目的のBean UserDto:

public class UserDto {
    private long id;
    private String username;
}

ライブラリを使用して、ソースbean Userから宛先beanUserDtoに属性をマップします。

JMapperを構成するには、API、アノテーション、およびXML構成を使用する3つの方法があります。

次のセクションでは、これらのそれぞれについて説明します。

4. APIの使用

APIを使用してJMapperを構成する方法を見てみましょう。

ここでは、ソースクラスと宛先クラスに構成を追加する必要はありません。 代わりに、すべての構成は、 JMapperAPI、を使用して実行できます。これにより、最も柔軟な構成方法になります。

@Test
public void givenUser_whenUseApi_thenConverted(){
    JMapperAPI jmapperApi = new JMapperAPI() 
      .add(mappedClass(UserDto.class)
        .add(attribute("id").value("id"))
        .add(attribute("username").value("email")));

    JMapper<UserDto, User> userMapper = new JMapper<>
      (UserDto.class, User.class, jmapperApi);
    User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
    UserDto result = userMapper.getDestination(user);

    assertEquals(user.getId(), result.getId());
    assertEquals(user.getEmail(), result.getUsername());
}

ここでは、 マップされたクラス()メソッドを使用してマップされたクラス UserDtoを定義します。次に、 attribute()メソッドを使用して各属性とそのマップされたクラスを定義します価値。

次に、構成に基づいて JMapper オブジェクトを作成し、その getDestination()メソッドを使用して、UserDtoの結果を取得しました。

5. 注釈の使用

@JMapアノテーションを使用してマッピングを構成する方法を見てみましょう。

public class UserDto {  
    @JMap
    private long id;

    @JMap("email")
    private String username;
}

JMapperの使用方法は次のとおりです。

@Test
public void givenUser_whenUseAnnotation_thenConverted(){
    JMapper<UserDto, User> userMapper = new JMapper<>(UserDto.class, User.class);
    User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
    UserDto result = userMapper.getDestination(user);

    assertEquals(user.getId(), result.getId());
    assertEquals(user.getEmail(), result.getUsername());        
}

id 属性の場合、ソースbeanと同じ名前であるため、ターゲットフィールド名を指定する必要はありませんでしたが、usernameフィールドの場合はUserクラスのemailフィールドに対応します。

次に、ソースBeanと宛先BeanをJMapper に渡すだけで済み、それ以上の構成は必要ありません。

全体として、この方法はコードの使用量が最も少ないので便利です。

6. XML構成の使用

XML構成を使用してマッピングを定義することもできます。

user_jmapper.xmlのサンプルXML構成は次のとおりです。

<jmapper>
  <class name="com.baeldung.jmapper.UserDto">
    <attribute name="id">
      <value name="id"/>
    </attribute>
    <attribute name="username">
      <value name="email"/>
    </attribute>
  </class>
</jmapper>

そして、XML構成をJMapperに渡す必要があります。

@Test
public void givenUser_whenUseXml_thenConverted(){
    JMapper<UserDto, User> userMapper = new JMapper<>
      (UserDto.class, User.class,"user_jmapper.xml");
    User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
    UserDto result = userMapper.getDestination(user);

    assertEquals(user.getId(), result.getId());
    assertEquals(user.getEmail(), result.getUsername());            
}

XML構成をStringとしてファイル名の代わりにJMapperに直接渡すこともできます。

7. グローバルマッピング

ソースBeanと宛先Beanの両方に同じ名前の複数のフィールドがある場合は、グローバルマッピングを利用できます。

たとえば、 idemailの2つのフィールドを持つUserDto1がある場合:

public class UserDto1 {  
    private long id;
    private String email;
    
    // standard constructor, getters, setters
}

グローバルマッピングは、 User ソースBeanで同じ名前のフィールドにマッピングされるため、使いやすくなります。

7.1. APIの使用

JMapperAPI 構成では、 global()を使用します。

@Test
public void givenUser_whenUseApiGlobal_thenConverted() {
    JMapperAPI jmapperApi = new JMapperAPI()
      .add(mappedClass(UserDto.class).add(global())) ;
    JMapper<UserDto1, User> userMapper1 = new JMapper<>
      (UserDto1.class, User.class,jmapperApi);
    User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
    UserDto1 result = userMapper1.getDestination(user);

    assertEquals(user.getId(), result.getId());
    assertEquals(user.getEmail(), result.getEmail());
}

7.2. 注釈の使用

アノテーションの構成には、クラスレベルで@JGlobalMapを使用します。

@JGlobalMap
public class UserDto1 {  
    private long id;
    private String email;
}

そして、ここに簡単なテストがあります:

@Test
public void whenUseGlobalMapAnnotation_thenConverted(){
    JMapper<UserDto1, User> userMapper= new JMapper<>(
      UserDto1.class, User.class);
    User user = new User(
      1L,"[email protected]", LocalDate.of(1980,8,20));
    UserDto1 result = userMapper.getDestination(user);

    assertEquals(user.getId(), result.getId());
    assertEquals(user.getEmail(), result.getEmail());        
}

7.3. XML構成

また、XML構成には、要素があります。

<jmapper>
  <class name="com.baeldung.jmapper.UserDto1">
    <global/>
  </class>
</jmapper>

次に、XMLファイル名を渡します。

@Test
public void givenUser_whenUseXmlGlobal_thenConverted(){
    JMapper<UserDto1, User> userMapper = new JMapper<>
      (UserDto1.class, User.class,"user_jmapper1.xml");
    User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
    UserDto1 result = userMapper.getDestination(user);

    assertEquals(user.getId(), result.getId());
    assertEquals(user.getEmail(), result.getEmail());            
}

8. カスタム変換

それでは、JMapperを使用してカスタム変換を適用する方法を見てみましょう。

UserDtoに新しいフィールドageがあり、 User birthDate属性から計算する必要があります。

public class UserDto {
    @JMap
    private long id;

    @JMap("email")
    private String username;
    
    @JMap("birthDate")
    private int age;

    @JMapConversion(from={"birthDate"}, to={"age"})
    public int conversion(LocalDate birthDate){
        return Period.between(birthDate, LocalDate.now())
          .getYears();
    }
}

したがって、は、@ JMapConversionを使用して、ユーザーの誕生日からUserDtoのage属性への複雑な変換を適用しました。 したがって、UserUserDtoにマップすると、ageフィールドが計算されます。

@Test
public void whenUseAnnotationExplicitConversion_thenConverted(){
    JMapper<UserDto, User> userMapper = new JMapper<>(
      UserDto.class, User.class);
    User user = new User(
      1L,"[email protected]", LocalDate.of(1980,8,20));
    UserDto result = userMapper.getDestination(user);

    assertEquals(user.getId(), result.getId());
    assertEquals(user.getEmail(), result.getUsername());     
    assertTrue(result.getAge() > 0);
}

9. リレーショナルマッピング

最後に、リレーショナルマッピングについて説明します。 このメソッドでは、毎回ターゲットクラスを使用してJMapperを定義する必要があります。

ターゲットクラスがすでにわかっている場合は、マップされたフィールドごとにそれらを定義し、RelationshipalJMapperを使用できます。

この例では、1つのソースBean Userがあります。

public class User {
    private long id;    
    private String email;
}

そして、2つの宛先Bean UserDto1

public class UserDto1 {  
    private long id;
    private String username;
}

そしてUserDto2

public class UserDto2 {
    private long id;
    private String email;
}

RelationalJMapper。を活用する方法を見てみましょう。

9.1. APIの使用

API構成では、 targetClasses()を使用して各属性のターゲットクラスを定義できます。

@Test
public void givenUser_whenUseApi_thenConverted(){
    JMapperAPI jmapperApi = new JMapperAPI()
      .add(mappedClass(User.class)
      .add(attribute("id")
        .value("id")
        .targetClasses(UserDto1.class,UserDto2.class))
      .add(attribute("email")
        .targetAttributes("username","email")
        .targetClasses(UserDto1.class,UserDto2.class)));
    
    RelationalJMapper<User> relationalMapper = new RelationalJMapper<>
      (User.class,jmapperApi);
    User user = new User(1L,"[email protected]");
    UserDto1 result1 = relationalMapper
      .oneToMany(UserDto1.class, user);
    UserDto2 result2 = relationalMapper
      .oneToMany(UserDto2.class, user);

    assertEquals(user.getId(), result1.getId());
    assertEquals(user.getEmail(), result1.getUsername());
    assertEquals(user.getId(), result2.getId());
    assertEquals(user.getEmail(), result2.getEmail());            
}

ターゲットクラスごとに、ターゲット属性名を定義する必要があることに注意してください。

RelationshipalJMapper は、マップされたクラスの1つのクラスのみを取ります。

9.2. 注釈の使用

アノテーションアプローチでは、クラスも定義します。

public class User {
    @JMap(classes = {UserDto1.class, UserDto2.class})
    private long id;    
    
    @JMap(
      attributes = {"username", "email"}, 
      classes = {UserDto1.class, UserDto2.class})
    private String email;
}

いつものように、アノテーションを使用する場合、これ以上の構成は必要ありません。

@Test
public void givenUser_whenUseAnnotation_thenConverted(){
    RelationalJMapper<User> relationalMapper
      = new RelationalJMapper<>(User.class);
    User user = new User(1L,"[email protected]");
    UserDto1 result1 = relationalMapper
      .oneToMany(UserDto1.class, user);
    UserDto2 result2= relationalMapper
      .oneToMany(UserDto2.class, user);

    assertEquals(user.getId(), result1.getId());
    assertEquals(user.getEmail(), result1.getUsername());  
    assertEquals(user.getId(), result2.getId());
    assertEquals(user.getEmail(), result2.getEmail());          
}

9.3. XML構成

XML構成には、 各属性のターゲットクラスを定義します。

user_jmapper2.xmlは次のとおりです。

<jmapper>
  <class name="com.baeldung.jmapper.relational.User">
    <attribute name="id">
      <value name="id"/>
      <classes>
        <class name="com.baeldung.jmapper.relational.UserDto1"/>
        <class name="com.baeldung.jmapper.relational.UserDto2"/>
      </classes>
    </attribute>
    <attribute name="email">
      <attributes>
        <attribute name="username"/>
        <attribute name="email"/>
      </attributes>
      <classes>
        <class name="com.baeldung.jmapper.relational.UserDto1"/>
        <class name="com.baeldung.jmapper.relational.UserDto2"/>
      </classes>      
    </attribute>
  </class>
</jmapper>

次に、XML構成ファイルをRelationshipalJMapperに渡します。

@Test
public void givenUser_whenUseXml_thenConverted(){
    RelationalJMapper<User> relationalMapper
     = new RelationalJMapper<>(User.class,"user_jmapper2.xml");
    User user = new User(1L,"[email protected]");
    UserDto1 result1 = relationalMapper
      .oneToMany(UserDto1.class, user);
    UserDto2 result2 = relationalMapper
      .oneToMany(UserDto2.class, user);

    assertEquals(user.getId(), result1.getId());
    assertEquals(user.getEmail(), result1.getUsername());
    assertEquals(user.getId(), result2.getId());
    assertEquals(user.getEmail(), result2.getEmail());         
}

10. 結論

このチュートリアルでは、JMapperを構成するさまざまな方法と、カスタム変換を実行する方法を学びました。

例の完全なソースコードは、GitHubにあります。