基本編。
環境
使用するBean
public class Person { private String name; private int age; // constructor/getter/setter } public class PersonEntity { private String name; private int age; // constructor/getter/setter } public class Address { private String address; private String zipCode; // constructor/getter/setter } public class Student { private String name; private int age; private String address; // constructor/getter/setter }
Mapperクラスの作成
Mapperクラスは、interfaceクラスまたはabstractクラスに @Mapping
を付与して作成する。
MapStructはこのアノテーションを元にMapperの実装クラスを生成する。
interfaceクラスの場合
@Mapper public interface FooMapper { @Mapping(...) Bar fooToBar(Foo foo); }
abstractクラスの場合
@Mapper public abstract FooMapper { @Mapping(...) public abstract Bar fooToBar(Foo foo); }
Mapperクラスのインスタンス
Mapperクラスのインスタンスを生成するには、Mappers#getMapper
を使用する。
FooMapper MAPPER = Mappers.getMapper(FooMapper.class);
他にも方法があるので公式ドキュメントを参照。 http://mapstruct.org/documentation/stable/reference/html/#retrieving-mapper
Mapperの作成
ここから実際にMapperを作成していく。
同一フィールド名を持つBeanへのマッピング
@Mapper public interface BasicMapper { BasicMapper MAPPER = Mappers.getMapper(BasicMapper.class); Person toPerson(PersonEntity entity); }
テストコード
@Test public void test() { PersonEntity entity = new PersonEntity("マイケル", 23); // PersonEntity -> Person Person person = BasicMapper.MAPPER.toPerson(entity); assertThat(person.getName()).isEqualTo("マイケル"); assertThat(person.getAge()).isEqualTo(23); }
リストのマッピング
リストのマッピングをするには、単一Beanへのマッピングが定義してあることが条件。
@Mapper public interface BasicMapper { BasicMapper MAPPER = Mappers.getMapper(BasicMapper.class); Person toPerson(PersonEntity entity); List<Person> toPersons(List<PersonEntity> entities); }
テストコード
@Test public void test() { List<PersonEntity> list = List.of(new PersonEntity("マイケル", 23), new PersonEntity("カリー", 30)); // List -> List List<Person> persons = BasicMapper.MAPPER.toPersons(list); List<Person> expected = List.of(new Person("マイケル", 23), new Person("カリー", 30)); assertThat(persons).hasSize(2).containsExactlyElementsOf(expected); }
一部のフィールドをマッピング対象外にする
フィールドの一部をマッピング対象外にするには、 @Mapping
アノテーションを利用する。
target属性に対象外にするフィールドと、ignore属性に true を設定する。
@Mapper public interface BasicMapper { BasicMapper MAPPER = Mappers.getMapper(BasicMapper.class); @Mapping(target = "name", ignore = true) PersonEntity toPersonEntity(Person dto); }
テストコード
@Test public void test() { Person dto = new Person("マイケル", 23); PersonEntity entity = BasicMapper.MAPPER.toPersonEntity(dto); assertThat(entity.getName()).isNull(); assertThat(entity.getAge()).isEqualTo(23); }
カスタムメソッドを追加する
独自のマッピングをカスタムメソッドとして追加することができる。 interfaceクラスの場合はdefaultメソッドで定義する。
@Mapper public interface BasicMapper { BasicMapper MAPPER = Mappers.getMapper(BasicMapper.class); default Person toPerson(PersonEntity entity) { Person dto = new Person(); dto.setName(entity.getName() + "!!"); dto.setAge(entity.getAge() + 100); return dto; } }
テストコード
@Test public void test() { PersonEntity entity = new PersonEntity("マイケル", 23); Person person = CustomMethodMapper.MAPPER.toPerson(entity); assertThat(person.getName()).isEqualTo("マイケル!!"); assertThat(person.getAge()).isEqualTo(123); }
複数のBeanから一つのBeanにマッピング
source属性に引数名.フィールド名、target属性にマッピング対象のフィールド名を指定する。
@Mapper public interface BasicMapper { BasicMapper MAPPER = Mappers.getMapper(BasicMapper.class); @Mapping(source = "person.name", target = "name") @Mapping(source = "person.age", target = "age") @Mapping(source = "address.address", target = "address") Student personAndAddressToStudent(Person person, Address address); }
テストコード
@Test public void test() { Person person = new Person("マイケル", 23); Address address = new Address("ノースカロライナ州", "12345"); // 2つのBean -> 1つのBean Student student = BasicMapper.MAPPER.personAndAddressToStudent(person, address); assertThat(student.getName()).isEqualTo("マイケル"); assertThat(student.getAge()).isEqualTo(23); assertThat(student.getAddress()).isEqualTo("ノースカロライナ州"); }
Beanをアップデートする
マッピングするBeanとマッピングされるBeanを引数に指定する。そのとき更新対象のBeanの引数に @MappingTarget
を付与する。
@Mapper public interface BasicMapper { BasicMapper MAPPER = Mappers.getMapper(BasicMapper.class); void updateStudent(Person person, @MappingTarget Student student); }
テストコード
@Test public void test() { Person person = new Person("マイケル", 23); Student student = new Student("カリー", 30, "カリフォルニア州"); // studentをpersonの内容でアップデート BasicMapper.MAPPER.updateStudent(person, student); assertThat(student.getName()).isEqualTo("マイケル"); assertThat(student.getAge()).isEqualTo(23); assertThat(student.getAddress()).isEqualTo("カリフォルニア州"); // Personにaddressを持っていないので変わらない }