简体   繁体   中英

Toggle mapping of nulls on/off using Orika?

I'm using Orika, and have a need to sometimes map nulls (null values on source bean should overwrite value on destination bean with null) and in other situations to ignore nulls (nulls on source bean do not overwrite existing values on destination bean).

Orika can support this using the mapNulls(true/false) method. So I thought of creating two separate mapper factories and doing a mapNulls(false) on one and mapNulls(true) on the other. I then would repeat all of the same class mapping configs on both factories. Then I can choose the appropriate factory I need at runtime, depending on whether I want to map the nulls or not.

However, The documentation indicates creating these factories and facades is expensive, so doing it that way seems wasteful and would require me to have 2 factories and 2 facade mappers, with all the identical class mappings repeated twice.

Does anyone know of a better way to do this using Orika? I'd Appreciate any suggestions! Thanks -Gary.

I had similar requirement when trying not to set null fields to JPA Entities. But reverse should set null values coming from database. I don't know if your need with "sometimes" states. But if you have something to identify(@Entity in my case) your need to mapNulls on your beans you could use this.

I have written a ma.glasnost.orika.impl.ConfigurableMapper and Overriden one of the map method in it.

@Override
    public <S, D> void map(S sourceObject, D destinationObject) {
        if (!factory.existsRegisteredMapper(TypeFactory.valueOf(sourceObject.getClass()), TypeFactory.valueOf(destinationObject.getClass()), false)){
            ClassMapBuilder mapBuilder = factory.classMap(sourceObject.getClass(), destinationObject.getClass());
            mapBuilder.mapNulls( //Eğer Entity sınıfı ise
                Arrays.stream(sourceObject.getClass().getDeclaredAnnotations())
                        .map(annotation -> annotation.annotationType().equals(Entity.class))
                        .map(value -> !value)
                        .reduce(Boolean::logicalOr)
                        .orElse(false)
            );
            mapBuilder.mapNullsInReverse( //Eğer Entity sınıfı ise
                Arrays.stream(destinationObject.getClass().getDeclaredAnnotations())
                        .map(annotation -> annotation.annotationType().equals(Entity.class))
                        .map(value -> !value)
                        .reduce(Boolean::logicalOr)
                        .orElse(false)
            );
            mapBuilder.byDefault().register();
        }
        super.map(sourceObject, destinationObject);

    }

What it does is basically creates mappers which mapNulls if mappins is Entity->DTO and registers new mappers if not registered before. Actually this registration could be somewhere else but this just a PoC and it does the job.

And for an example on implementing ConfigurableMapper you can check this link. (This is actually a spring injectable mapper example) https://github.com/dlizarra/orika-spring-integration/blob/master/src/main/java/com/dlizarra/orika/mapper/OrikaBeanMapper.java

(Wanted to clearify your question but don't got enough rep to comment)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM