#1699 add sensible defaults to NullValuePropertyMapping.SET_TO_DEFAULT (#1702)

This commit is contained in:
Sjaak Derksen 2019-01-28 22:47:37 +01:00 committed by GitHub
parent 884ca2507a
commit 0981959ff0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 9 deletions

View File

@ -33,6 +33,17 @@ public enum NullValuePropertyMappingStrategy {
/** /**
* If a source bean property equals {@code null} the target bean property will be set to its default value. * If a source bean property equals {@code null} the target bean property will be set to its default value.
* <p>
* This means:
* <ol>
* <li>For {@code List} MapStruct generates an {@code ArrayList}</li>
* <li>For {@code Map} a {@code HashMap}</li>
* <li>For arrays an empty array</li>
* <li>For {@code String} {@code ""}</li>
* <li>for primitive / boxed types a representation of {@code 0} or {@code false}</li>
* <li>For all other objects an new instance is created, requiring an empty constructor.</li>
* </ol>
* <p>
* Make sure that a {@link Mapping#defaultValue()} is defined if no empty constructor is available on * Make sure that a {@link Mapping#defaultValue()} is defined if no empty constructor is available on
* the default value. * the default value.
*/ */

View File

@ -2134,11 +2134,15 @@ The strategy works in a hierarchical fashion. Setting `nullValueMappingStrategy`
[[mapping-result-for-null-properties]] [[mapping-result-for-null-properties]]
=== Controlling mapping result for 'null' properties in bean mappings (update mapping methods only). === Controlling mapping result for 'null' properties in bean mappings (update mapping methods only).
MapStruct offers control over the property to set in an `@MappingTarget` annotated target bean when the source property equals `null` or the presence check method yields absent. MapStruct offers control over the property to set in an `@MappingTarget` annotated target bean when the source property equals `null` or the presence check method results in 'absent'.
By default the source property will be set to null. However: By default the target property will be set to null.
1. By specifying `nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT` on `@Mapping`, `@BeanMapping`, `@Mapper` or `@MappingConfig`, the mapping result can be altered to return *default* values. Please note that a default constructor is required. If not available, use the `@Mapping#defaultValue`. For `List` MapStruct generates an `ArrayList`, for `Map` mapstruct generates a `HashMap`. However:
1. By specifying `nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT` on `@Mapping`, `@BeanMapping`, `@Mapper` or `@MappingConfig`, the mapping result can be altered to return *default* values.
For `List` MapStruct generates an `ArrayList`, for `Map` a `HashMap`, for arrays an empty array, for `String` `""` and for primitive / boxed types a representation of `false` or `0`.
For all other objects an new instance is created. Please note that a default constructor is required. If not available, use the `@Mapping#defaultValue`.
2. By specifying `nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE` on `@Mapping`, `@BeanMapping`, `@Mapper` or `@MappingConfig`, the mapping result will be equal to the original value of the `@MappingTarget` annotated target. 2. By specifying `nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE` on `@Mapping`, `@BeanMapping`, `@Mapper` or `@MappingConfig`, the mapping result will be equal to the original value of the `@MappingTarget` annotated target.

View File

@ -934,6 +934,22 @@ public class Type extends ModelElement implements Comparable<Type> {
throw new UnsupportedOperationException( getName() ); throw new UnsupportedOperationException( getName() );
} }
public String getSensibleDefault() {
if ( isPrimitive() ) {
return getNull();
}
else if ( "String".equals( getName() ) ) {
return "\"\"";
}
else {
if ( isNative() ) {
// must be boxed, since primitive is already checked
return typeFactory.getType( typeUtils.unboxedType( typeMirror ) ).getNull();
}
}
return null;
}
@Override @Override
public int hashCode() { public int hashCode() {
// javadoc typemirror: "Types should be compared using the utility methods in Types. There is no guarantee // javadoc typemirror: "Types should be compared using the utility methods in Types. There is no guarantee

View File

@ -161,6 +161,8 @@ Performs a default assignment with a default value.
new <@includeModel object=ext.targetType.implementationType/>() new <@includeModel object=ext.targetType.implementationType/>()
<#elseif ext.targetType.arrayType> <#elseif ext.targetType.arrayType>
new <@includeModel object=ext.targetType.componentType/>[0] new <@includeModel object=ext.targetType.componentType/>[0]
<#elseif ext.targetType.sensibleDefault??>
${ext.targetType.sensibleDefault}
<#else> <#else>
new <@includeModel object=ext.targetType/>() new <@includeModel object=ext.targetType/>()
</#if> </#if>

View File

@ -38,7 +38,6 @@ public interface UserMapper {
@InheritInverseConfiguration @InheritInverseConfiguration
@BeanMapping( nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT ) @BeanMapping( nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT )
@Mapping( target = "phone", source = "contactDataDTO.phone", defaultValue = "0" )
void updateUserFromUserAndDefaultDTO(UserDTO userDTO, @MappingTarget User user); void updateUserFromUserAndDefaultDTO(UserDTO userDTO, @MappingTarget User user);
} }

View File

@ -12,8 +12,8 @@ import javax.annotation.Generated;
@Generated( @Generated(
value = "org.mapstruct.ap.MappingProcessor", value = "org.mapstruct.ap.MappingProcessor",
date = "2019-01-27T12:40:32+0100", date = "2019-01-28T21:17:39+0100",
comments = "version: , compiler: Eclipse JDT (Batch) 1.2.100.v20160418-1457, environment: Java 1.8.0_181 (Oracle Corporation)" comments = "version: , compiler: javac, environment: Java 1.8.0_181 (Oracle Corporation)"
) )
public class UserMapperImpl implements UserMapper { public class UserMapperImpl implements UserMapper {
@ -116,7 +116,7 @@ public class UserMapperImpl implements UserMapper {
user.setAddress( address ); user.setAddress( address );
} }
else { else {
user.setAddress( new String() ); user.setAddress( "" );
} }
String phone = userDTOContactDataDTOPhone( userDTO ); String phone = userDTOContactDataDTOPhone( userDTO );
if ( phone != null ) { if ( phone != null ) {
@ -130,13 +130,13 @@ public class UserMapperImpl implements UserMapper {
user.setEmail( email ); user.setEmail( email );
} }
else { else {
user.setEmail( new String() ); user.setEmail( "" );
} }
if ( userDTO.getName() != null ) { if ( userDTO.getName() != null ) {
user.setName( userDTO.getName() ); user.setName( userDTO.getName() );
} }
else { else {
user.setName( new String() ); user.setName( "" );
} }
} }