MapStruct:使用 updateMethod() 初始化,即使源为空也创建
MapStruct: initialize using updateMethod(), create even though source is null
有人能告诉我如何(或者如果可能的话)强制更新方法在目标为空时创建目标吗?
我想实现这样的目标:
@BeforeMapping
@Mapping(source = "inputBy", target = "tactical.inputBy")
default BCSecuritiesTrade updateOrCreateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade){
return bcSecuritiesTrade != null? bcSecuritiesTrade:new BCSecuritiesTrade();
}
但是这个 return 始终是新实例并且不进行映射。
我想要一种方法,当它存在时更新“目标”并在输入 null 时创建新的“目标”对象。
此外,当“源”对象为空时,它不应 return 为空,而应为“目标”对象或创建新对象(如果“目标”对象为空)。当前方法在“源”为空时 returning 为空。
非常感谢!
我还没有找到开箱即用的解决方案。
根据 documentation,MapStruct 似乎设计为仅对现有实例使用 updateMethod
。
我通过其他自定义方法解决了问题。
MapStruct 版本 1.4.2.Final
@Mapper
public interface BCSecuritiesTradeMapper {
BCSecuritiesTradeMapper INSTANCE = Mappers.getMapper(BCSecuritiesTradeMapper.class);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade updateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade);
default BCSecuritiesTrade updateOrCreateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if (bcSecuritiesTrade == null) {
bcSecuritiesTrade = new BCSecuritiesTrade();
}
if (inputBy == null) {
return bcSecuritiesTrade;
}
return updateInputBy(inputBy, bcSecuritiesTrade);
}
}
生成的代码:
public class BCSecuritiesTradeMapperImpl implements BCSecuritiesTradeMapper {
@Override
public BCSecuritiesTrade updateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if ( inputBy == null ) {
return null;
}
if ( bcSecuritiesTrade.tactical == null ) {
bcSecuritiesTrade.tactical = new Tactical();
}
stringToTactical( inputBy, bcSecuritiesTrade.tactical );
return bcSecuritiesTrade;
}
protected void stringToTactical(String string, Tactical mappingTarget) {
if ( string == null ) {
return;
}
mappingTarget.inputBy = string;
}
}
MapStruct 版本 1.5.0.RC1
新版本有更好的实现。如果 source
是 null
,将返回 target
,但如果传递 null
,它仍然无法创建 target
对象的实例。
自定义方法简化但未消除。
@Mapper
public interface BCSecuritiesTradeMapper {
BCSecuritiesTradeMapper INSTANCE = Mappers.getMapper(BCSecuritiesTradeMapper.class);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade updateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade);
default BCSecuritiesTrade updateOrCreateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if (bcSecuritiesTrade == null) {
bcSecuritiesTrade = new BCSecuritiesTrade();
}
return updateInputBy(inputBy, bcSecuritiesTrade);
}
}
生成的代码:
public class BCSecuritiesTradeMapperImpl implements BCSecuritiesTradeMapper {
@Override
public BCSecuritiesTrade updateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if ( inputBy == null ) {
return bcSecuritiesTrade;
}
if ( bcSecuritiesTrade.tactical == null ) {
bcSecuritiesTrade.tactical = new Tactical();
}
stringToTactical( inputBy, bcSecuritiesTrade.tactical );
return bcSecuritiesTrade;
}
protected void stringToTactical(String string, Tactical mappingTarget) {
if ( string == null ) {
return;
}
mappingTarget.inputBy = string;
}
}
单元测试:
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class MapperTest {
@Test
public void test() {
BCSecuritiesTrade bcSecuritiesTrade = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy(null, null);
Assert.assertNotNull(bcSecuritiesTrade);
Assert.assertNull(bcSecuritiesTrade.tactical);
BCSecuritiesTrade bcSecuritiesTradeUpdate = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy(null, bcSecuritiesTrade);
Assert.assertNotNull(bcSecuritiesTradeUpdate);
Assert.assertNull(bcSecuritiesTradeUpdate.tactical);
Assert.assertEquals(bcSecuritiesTrade, bcSecuritiesTradeUpdate);
bcSecuritiesTrade = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy("123", null);
Assert.assertNotNull(bcSecuritiesTrade);
Assert.assertEquals(bcSecuritiesTrade.tactical.inputBy, "123");
bcSecuritiesTradeUpdate = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy("124", bcSecuritiesTrade);
Assert.assertNotNull(bcSecuritiesTradeUpdate);
Assert.assertEquals(bcSecuritiesTradeUpdate.tactical.inputBy, "124");
Assert.assertEquals(bcSecuritiesTrade, bcSecuritiesTradeUpdate);
}
}
使用的实体:
public class BCSecuritiesTrade {
public Tactical tactical;
}
public class Tactical {
public String inputBy;
}
备选方案:
为 Create
和 Update
创建两个单独的方法。
@Mapper(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
public interface BCSecuritiesTradeMapper {
BCSecuritiesTradeMapper INSTANCE = Mappers.getMapper(BCSecuritiesTradeMapper.class);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade updateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade createInputBy(String inputBy);
}
有人能告诉我如何(或者如果可能的话)强制更新方法在目标为空时创建目标吗?
我想实现这样的目标:
@BeforeMapping
@Mapping(source = "inputBy", target = "tactical.inputBy")
default BCSecuritiesTrade updateOrCreateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade){
return bcSecuritiesTrade != null? bcSecuritiesTrade:new BCSecuritiesTrade();
}
但是这个 return 始终是新实例并且不进行映射。
我想要一种方法,当它存在时更新“目标”并在输入 null 时创建新的“目标”对象。
此外,当“源”对象为空时,它不应 return 为空,而应为“目标”对象或创建新对象(如果“目标”对象为空)。当前方法在“源”为空时 returning 为空。
非常感谢!
我还没有找到开箱即用的解决方案。
根据 documentation,MapStruct 似乎设计为仅对现有实例使用 updateMethod
。
我通过其他自定义方法解决了问题。
MapStruct 版本 1.4.2.Final
@Mapper
public interface BCSecuritiesTradeMapper {
BCSecuritiesTradeMapper INSTANCE = Mappers.getMapper(BCSecuritiesTradeMapper.class);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade updateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade);
default BCSecuritiesTrade updateOrCreateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if (bcSecuritiesTrade == null) {
bcSecuritiesTrade = new BCSecuritiesTrade();
}
if (inputBy == null) {
return bcSecuritiesTrade;
}
return updateInputBy(inputBy, bcSecuritiesTrade);
}
}
生成的代码:
public class BCSecuritiesTradeMapperImpl implements BCSecuritiesTradeMapper {
@Override
public BCSecuritiesTrade updateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if ( inputBy == null ) {
return null;
}
if ( bcSecuritiesTrade.tactical == null ) {
bcSecuritiesTrade.tactical = new Tactical();
}
stringToTactical( inputBy, bcSecuritiesTrade.tactical );
return bcSecuritiesTrade;
}
protected void stringToTactical(String string, Tactical mappingTarget) {
if ( string == null ) {
return;
}
mappingTarget.inputBy = string;
}
}
MapStruct 版本 1.5.0.RC1
新版本有更好的实现。如果 source
是 null
,将返回 target
,但如果传递 null
,它仍然无法创建 target
对象的实例。
自定义方法简化但未消除。
@Mapper
public interface BCSecuritiesTradeMapper {
BCSecuritiesTradeMapper INSTANCE = Mappers.getMapper(BCSecuritiesTradeMapper.class);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade updateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade);
default BCSecuritiesTrade updateOrCreateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if (bcSecuritiesTrade == null) {
bcSecuritiesTrade = new BCSecuritiesTrade();
}
return updateInputBy(inputBy, bcSecuritiesTrade);
}
}
生成的代码:
public class BCSecuritiesTradeMapperImpl implements BCSecuritiesTradeMapper {
@Override
public BCSecuritiesTrade updateInputBy(String inputBy, BCSecuritiesTrade bcSecuritiesTrade) {
if ( inputBy == null ) {
return bcSecuritiesTrade;
}
if ( bcSecuritiesTrade.tactical == null ) {
bcSecuritiesTrade.tactical = new Tactical();
}
stringToTactical( inputBy, bcSecuritiesTrade.tactical );
return bcSecuritiesTrade;
}
protected void stringToTactical(String string, Tactical mappingTarget) {
if ( string == null ) {
return;
}
mappingTarget.inputBy = string;
}
}
单元测试:
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class MapperTest {
@Test
public void test() {
BCSecuritiesTrade bcSecuritiesTrade = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy(null, null);
Assert.assertNotNull(bcSecuritiesTrade);
Assert.assertNull(bcSecuritiesTrade.tactical);
BCSecuritiesTrade bcSecuritiesTradeUpdate = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy(null, bcSecuritiesTrade);
Assert.assertNotNull(bcSecuritiesTradeUpdate);
Assert.assertNull(bcSecuritiesTradeUpdate.tactical);
Assert.assertEquals(bcSecuritiesTrade, bcSecuritiesTradeUpdate);
bcSecuritiesTrade = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy("123", null);
Assert.assertNotNull(bcSecuritiesTrade);
Assert.assertEquals(bcSecuritiesTrade.tactical.inputBy, "123");
bcSecuritiesTradeUpdate = BCSecuritiesTradeMapper.INSTANCE.updateOrCreateInputBy("124", bcSecuritiesTrade);
Assert.assertNotNull(bcSecuritiesTradeUpdate);
Assert.assertEquals(bcSecuritiesTradeUpdate.tactical.inputBy, "124");
Assert.assertEquals(bcSecuritiesTrade, bcSecuritiesTradeUpdate);
}
}
使用的实体:
public class BCSecuritiesTrade {
public Tactical tactical;
}
public class Tactical {
public String inputBy;
}
备选方案:
为 Create
和 Update
创建两个单独的方法。
@Mapper(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
public interface BCSecuritiesTradeMapper {
BCSecuritiesTradeMapper INSTANCE = Mappers.getMapper(BCSecuritiesTradeMapper.class);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade updateInputBy(String inputBy, @MappingTarget BCSecuritiesTrade bcSecuritiesTrade);
@Mapping(source = "inputBy", target = "tactical.inputBy")
BCSecuritiesTrade createInputBy(String inputBy);
}