[Java] Let's replace data objects with a mapper ~ BeanMapper Orika ~

What is Orika

A library that can be mapped to POJOs and beans. Convenient because you can easily specify mapping and type conversion.

Automatically map object properties

usage environment

Build tool Framework
Gradle Spring Boot

The framework is used to DI the Orika objects. (See below)

① Preparation for using the library

Add the following line to the dependencies of build.gradle. Please read the version as appropriate.

build.gradle


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

** If you are using another build tool, please use [this link](https://mvnrepository.com/artifact/ma.glasnost.orika/orika-core/1.5.4) to describe the description according to your environment. please refer to. ** **

② Instantiate MapperFactory

You can new in the class you use, but officially it's better to use a singleton It seems that the performance is good, so this time I used the DI function of Spring to make it a singleton.

ConvertMapper.class



@Componet
public class ConvertMapper {

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

Field variable of the class that performs Convert processing


@Autowired
private MapperFactory mapperFactory;

③ Set the source class and destination class of Convert

Set the class name of the object to be converted (the one for which data is set) to the Convert source class name, Set the class name of the object to be converted (the one you want to set from now on) in the conversion destination class name.

Method of class that performs Convert processing


 BoundMapperFacade<Convert source class name,Convert destination class name> boundMapperFacade =
        mapperFactory.getMapperFacade(Convert source class name.class,Convert destination class name.class);

④ Implementation of Convert

Method of class that performs Convert processing


Object to convert to= boundMapperFacade.map(Convert original object);

This completes the conversion.

How to manually map object properties

If you have a class with the following structure and want to convert from A to B, ** Cannot be converted by automatic mapping because the field variable names are different. ** **

Mold Convert source Convert destination
ClassA ClassB
int id id
String propatyA propatyB

Therefore, it is necessary to explicitly specify the paired property name before converting the object. ** * [Automatically map object properties](https://qiita.com/NekozeDaisensei/items/92e9d5d653119a90f991#%E3%82%AA%E3%83%96%E3%82%B8%E3%82% A7% E3% 82% AF% E3% 83% 88% E3% 81% AE% E3% 83% 97% E3% 83% AD% E3% 83% 91% E3% 83% 86% E3% 82% A3% E3% 82% 92% E8% 87% AA% E5% 8B% 95mapping% E3% 81% 99% E3% 82% 8B) Same up to step ③ **

Method of class that performs Convert processing


mapperFactory.classMap(InputEstimateData.class, EstimateDataValue.class)
        .field("propatyA","propatyB") //Specify the property name to be mapped.
        .byDefault()                  //The rest is automatically mapped
        .register();

//Same for executing Convert
Object to convert to= boundMapperFacade.map(Convert original object);

Convert type and data with Convert

If you want to convert a specific type with Convert, do the following.

① Create a class for type conversion

Create a class that inherits the following classes according to the conversion conditions.

Unidirectional conversion only Bidirectional conversion
ma.glasnost.orika.CustomConverter ma.glasnost.orika.converter.BidirectionalConverter

An example is a bidirectional conversion class of java.sql.Timestamp type and java.util.LocalDateTime type.

Example: Bidirectional conversion between LocalDateTime and 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();
  }
}

(2) Register the conversion class in ConverterFactory

There are two ways to register.

Method 1. When applying to all conversions

python


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

Method 2. When specifying the target property at the time of conversion

ConverterFactory converterFactory = mapperFactory.getConverterFactory();
converterFactory.registerConverter("Management name",new DataConverter());

Set the above contents with the method that creates the instance of MapperFactory.

ConvertMapper.class



@Componet
public class ConvertMapper {

  @Bean
  public MapperFactory getMapperFactory(){
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    //Get Converter Factory
    ConverterFactory converterFactory = mapperFactory.getConverterFactory();
        
    //When specifying the target property at the time of conversion
    converterFactory.registerConverter("Management name",new DataConverter());
    
    //When applying to all conversions
    converterFactory.registerConverter(new DataConverter());
    
    return mapperFactory;
  }
}

③ Conversion settings and conversion

BoundMapperFacade<Convert source class name,Convert destination class name> boundMapperFacade =
        mapperFactory.getMapperFacade(Convert source class name.class,Convert destination class name.class);

//Set conversion conditions for method 2 (not required for method 2)
// java.util.LocalDateTime java.sql.Convert to Timestamp type and map
mapperFactory.classMap(Convert source class name.class,Convert destination class name.class)
  .fieldMap("Property name to be mapped of Convert source class","Property name to be mapped of Convert destination class")
  .converter("Management name specified when registering with ConverterFactory")
  .add()
  .byDefault()
  .register();

//Same for executing Convert
Object to convert to= boundMapperFacade.map(Convert original object);

Afterword

It was a way of using Orika of BeanMapper, which is convenient but not very visible. I feel that I can do most of the things I'm writing here.

What doesn't catch the light is that Lombok can create a constructor that sets arguments to all properties ... After all, that doesn't get you out of Getter hell. This is convenient because Orika will automatically map if the property name is the same.

Recommended Posts

[Java] Let's replace data objects with a mapper ~ BeanMapper Orika ~
Let's create a timed process with Java Timer! !!
Let's scrape with Java! !!
[Java basics] Let's make a triangle with a for statement
Let's operate Excel with Java! !!
Using Mapper with Java (Spring)
Replace with a value according to the match with a Java regular expression
Build a Java project with Gradle
Sort a List of Java objects
Declare a method that has a Java return value with the return value data type
Let's express the result of analyzing Java bytecode with a class diagram
Let's go with Watson Assistant (formerly Conversation) ⑤ Create a chatbot with Watson + Java + Slack
Let's make a Christmas card with Processing!
Let's try WebSocket with Java and javascript!
Let's create a Java development environment (updating)
Split a string with ". (Dot)" in Java
[Java] Let's make a DB access library!