LoginSignup
5
5

More than 3 years have passed since last update.

【Java】データオブジェクトの入れ替えはマッパーでやってしまおう~BeanMapper Orika~

Last updated at Posted at 2019-07-17

Orikaとは

POJOやBeanにマッピング処理できるライブラリ。
マッピングの指定や型変換が楽に行えて便利。

オブジェクトのプロパティを自動Mappingする

使用環境

ビルドツール フレームワーク
Gradle Spring Boot

フレームワークはOrikaのオブジェクトをDIするために使用してます。(後述)

①ライブラリの使用準備

build.gradleのdependenciesに以下の1行を追加。
versionについては適宜読み替えてください

build.gradle
compile group: 'ma.glasnost.orika', name: 'orika-core', version: '1.5.4'


別のビルドツールをお使いの方はこのリンク先で使用環境に応じた記述を参照してください。

② MapperFactoryをインスタンス化する

使用するクラスでnewしてもいいが、公式にはシングルトンにした方が
パフォーマンスいいみたいなので今回はSpringのDI機能を使用してシングルトン化しました。
※シングルトンってなんぞやって人はここでも見てくだせぇ

ConvertMapper.class

@Componet
public class ConvertMapper {

  @Bean
  public MapperFactory getMapperFactory(){
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    return mapperFactory;
  }
}

Convert処理を行うクラスのフィールド変数
@Autowired
private MapperFactory mapperFactory;

③ Convertの元クラスと先クラスを設定する

Convert元クラス名に変換元となるオブジェクト(データが設定されている方)のクラス名を設定、
Convert先クラス名に変換先となるオブジェクト(これから設定したい方)のクラス名を設定します。

Convert処理を行うクラスのメソッド
 BoundMapperFacade<Convert元クラス名, Convert先クラス名> boundMapperFacade =
        mapperFactory.getMapperFacade(Convert元クラス名.class, Convert先クラス名.class);

④ Convertの実施

Convert処理を行うクラスのメソッド
Convert先のオブジェクト = boundMapperFacade.map(Convert元のオブジェクト);

これにてConvert完了です。

オブジェクトのプロパティを手動Mappingする方法

以下のような構造のクラスがありAからBに変換したい場合では、
フィールド変数名が異なるため自動マッピングでは変換できません。

Convert元 Convert先
ClassA ClassB
int id id
String propatyA propatyB

そのため、オブジェクトの変換を行う前に明示的に対となるプロパティ名を指定してあげる必要があります。
オブジェクトのプロパティを自動Mappingするの手順③までは同じ

Convert処理を行うクラスのメソッド
mapperFactory.classMap(InputEstimateData.class, EstimateDataValue.class)
        .field("propatyA","propatyB") // マッピング対象となるプロパティ名を指定する。
        .byDefault()                  // 残りは自動Mappingする
        .register();

// Convertの実行も同じ
Convert先のオブジェクト = boundMapperFacade.map(Convert元のオブジェクト);

Convertで型やデータの変換を行う

Convertにて特定の型を変換したい場合には以下のことを行う。

①型変換用のクラスを作成する

変換条件に応じて下記のクラスを継承したクラスを作成する。

単方向のみの変換 双方向の変換
ma.glasnost.orika.CustomConverter ma.glasnost.orika.converter.BidirectionalConverter

例は、java.sql.Timestamp型とjava.util.LocalDateTime型の双方向変換のクラス

例:LocalDateTimeとTimestampの双方向変換
import java.sql.Timestamp;
import java.time.LocalDateTime;

public class DataConverter extends BidirectionalConverter<LocalDateTime, Timestamp> {
  @Override
  public Timestamp convertTo(LocalDateTime source, Type<Timestamp> destinationType, MappingContext mappingContext) {
    return Timestamp.valueOf(source);
  }

  @Override
  public LocalDateTime convertFrom(Timestamp source, Type<LocalDateTime> destinationType, MappingContext mappingContext) {
    return source.toLocalDateTime();
  }
}

② ConverterFactoryに変換用のクラスを登録する

登録方法には2通りある。

方法1. すべての変換に対して適用する場合

ConverterFactory converterFactory = mapperFactory.getConverterFactory();
converterFactory.registerConverter(new DataConverter());

方法2. 変換時に対象のプロパティを指定する場合 

ConverterFactory converterFactory = mapperFactory.getConverterFactory();
converterFactory.registerConverter("管理名",new DataConverter());

上記の内容をMapperFactoryのインスタンスを生成しているメソッドで設定する。

ConvertMapper.class

@Componet
public class ConvertMapper {

  @Bean
  public MapperFactory getMapperFactory(){
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    // ConverterFactoryの取得
    ConverterFactory converterFactory = mapperFactory.getConverterFactory();

    // 変換時に対象のプロパティを指定する場合
    converterFactory.registerConverter("管理名",new DataConverter());

    // すべての変換に対して適用する場合
    converterFactory.registerConverter(new DataConverter());

    return mapperFactory;
  }
}

③ 変換の設定とConvertの実施

BoundMapperFacade<Convert元クラス名, Convert先クラス名> boundMapperFacade =
        mapperFactory.getMapperFacade(Convert元クラス名.class, Convert先クラス名.class);

// 方法2の場合には変換条件を設定する(方法2の場合は不要)
// java.util.LocalDateTimeをjava.sql.Timestamp型に変換してマッピングする
mapperFactory.classMap(Convert元クラス名.class, Convert先クラス名.class)
  .fieldMap("Convert元クラスのマッピングさせたいプロパティ名","Convert先クラスのマッピングさせたいプロパティ名")
  .converter("ConverterFactoryに登録した時に指定した管理名")
  .add()
  .byDefault()
  .register();

// Convertの実行も同じ
Convert先のオブジェクト = boundMapperFacade.map(Convert元のオブジェクト);

あとがき

わりかし便利だけどあまり表に出てこないBeanMapperのOrikaの使い方でした。
ここに書いてる内容でだいたいのことはできる感じです。

日の目を浴びないのはLombokですべてのプロパティに引数を設定するコンストラクタを作れって話ですが・・・
結局、それではGetter地獄からは抜け出せません。
Orikaはプロパティ名さえ同じであれば自動的にマッピングしてくれるのでこれはこれで便利ですね。

5
5
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5