Skip to content

Add option to retain collection elements from existing target instead of clearing them #3695

@maxifridge

Description

@maxifridge

Use case

Using retainAll() for Set and Map targets will minimize the amount of add/remove operations required for these types.
This limits side effects of removing preemptively all elements through clear() to non-Set Collections and Arrays.

A good example of why it is important (and the one that made me work on this issue) : when mapping to an existing Set property of a Hibernate-managed entity, calling clear() then addAll() effectively triggers requests for all additions then all deletions ; though because of the flush operation order in Hibernate, only the newer elements are inserted, the others are deleted.

CollectionMappingStrategy does not seem to apply there ? Maybe there should be another configuration option for handling the cleaning of target properties, so that it would be possible to clear / retain (Set and Map only to prevent duplicates in other collections) / merge (may duplicate).

Generated Code

I already have made changes in that regard in a PR see #3696 but for the sake of summarizing everything here :

With target.getStrings() being a Set I would like the following to be produced by MapStruct :

        if ( target.getStrings() != null ) {
            if ( source.hasStrings() ) {
                target.getStrings().retainAll( source.getStrings() );
                target.getStrings().addAll( source.getStrings() );
            }
        }

Possible workarounds

I thought of maybe defining mappings dedicated to handling Set/Map targets, but it may become a hassle to maintain in larger codebases with many entities and DTOs.

    public void merge(@MappingTarget Set<Entity> target, Collection<Dto> source) {
        target.retainAll(source.stream().map(entityMapper::map).collect(Collectors.toSet()));
        target.addAll(entityMapper.mapToEntities(source));
    }

MapStruct Version

1.5.5, 1.6.0, 1.7.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions