-
-
Notifications
You must be signed in to change notification settings - Fork 990
Description
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