java ModelMapper DTO-->实体,如何无条件跳过所有未Map的字段

cl25kdpy  于 2023-01-15  发布在  Java
关注(0)|答案(1)|浏览(288)

我有两个类(实体和DTO)

public class Deliver  {

    private Long id;
    private String uri;
    private Instant moment;
    private DeliverStatus status; // enum PENDING,ACCEPTED,REJECTED
    private String feedback;      // feedback about received task
    private Integer correctCount; // nr of correct questions
    private Enrollment enrollment;
    private Lesson lesson;

        // constructors, getters and setters..

public class DeliverRevisionDto  {

    private DeliverStatus status;
    private String feedback;
    private Integer correctCount;
    
    // constructors, getters and setters..

目标很简单,更新Dto类传递的实体字段我在服务层有以下代码(Sping Boot 版本2.4.4):

@Service
public class DeliverService {

    @Autowired
    private DeliverRepository deliverRepository;
    
    @Autowired
    private ModelMapper modelMapper;
    
    @Transactional
    public void saveRevision(Long id, DeliverRevisionDto dto) {
    
        Deliver deliver = deliverRepository.getOne(id);
        
        System.out.println("BEFORE MAPPING: " + deliver.toString());  // # debug purpose

        deliver = modelMapper.map(dto, Deliver.class);
 
        // # debug purpose
        TypeMap<DeliverRevisionDto, Deliver> tm = modelMapper.getTypeMap(DeliverRevisionDto.class, Deliver.class);
        List<Mapping> list = tm.getMappings();
        for (Mapping m : list)
        {
            System.out.println(m);
        }
        System.out.println("AFTER MAPPING: " + deliver.toString()); // # debug purpose
        deliverRepository.save(deliver);
    }

}

控制台输出为:

BEFORE MAPPING: Deliver [id=1, uri=``https://github/someone.com``, moment=2020-12-10T10:00:00Z, status=PENDING, feedback=null, correctCount=null, enrollment=com.devsuperior.dslearnbds.entities.Enrollment@7e0, lesson=com.devsuperior.dslearnbds.entities.Task@23]`
`PropertyMapping[DeliverRevisionDto.correctCount -> Deliver.correctCount]`
`PropertyMapping[DeliverRevisionDto.feedback -> Deliver.feedback]`
`PropertyMapping[DeliverRevisionDto.status -> Deliver.status]`
`AFTER MAPPING: Deliver [id=null, uri=null, moment=null, status=ACCEPTED, feedback=Muito bem cabra, tarefa aceita., correctCount=5, enrollment=null, lesson=null]

DTO中3个字段的Map正确完成,但实体的所有其他字段都设置为空。我知道可以根据http://modelmapper.org/user-manual/property-mapping/跳过字段
问题是我不想把代码和特定的字段名/getters/setters结合起来,这就是我使用ModelMapper的原因。我想知道是否有任何配置在MapModelMapper对象时说:“嘿,TARGET类比SOURCE类有更多的字段,我将无条件地保持它们不变(意味着我不需要说明字段是什么)。”
我试图在两个类之间Map字段,它们具有不同的字段集(有些是相同的),当我将具有较小字段集的类Map到具有较大字段集的类时,Map器将字段集设置为不匹配“null”,我希望这些字段保持不变(具有原始值),而无需我告诉它们是哪一个,毕竟,Map器知道哪些字段匹配。

7lrncoxx

7lrncoxx1#

ModelMapper文档并不是该框架最好的部分,让我们看看代码中发生了什么。
在这里,您可以从存储库中获取要更新的实体:

Deliver deliver = deliverRepository.getOne(id);

并记录它的所有字段应该是。但是这一行:

deliver = modelMapper.map(dto, Deliver.class);

对变量deliver进行重新赋值。此方法创建Deliver类的新示例,并将其赋值给变量deliver,从而丢弃从repo获取的实体。
此新示例将具有DTOnull中不存在或未设置的所有字段。
这是我的IDE提供的API文档,用于这两种不同的方法:
字符串org.modelmapper.ModelMapper.map(对象源,类destinationType)将源Map到destinationType的示例。Map根据相应的TypeMap执行。如果源.getClass()和destinationType不存在TypeMap,则创建一个。
对比
voidorg.modelmapper.ModelMapper.map(对象源,对象目标)
将源Map到目标。根据对应的TypeMap执行Map。如果源.getClass()和目标.getClass()不存在TypeMap,则创建一个。
第一个方法实际上是基于传递的类型(Class)创建一个新示例,这一点可能没有明确说明,但应该清楚的是,ModelMapper不能仅仅通过知道类型来更改某个任意变量。您需要将要更改的变量作为方法参数传递。

相关问题