我使用Spring进行持久化。我得更新一下模型。该模型有“n”个字段和一个主键。
{
"some_model":{
"id":"5527716",
"field_one": "44248156",
"field_two": "44248156",
"field_three": "44248156",
"field_four": "44248156",
"field_five": "44248156",
"field_six": "44248156",
"field_seven": "44248156",
"field_eight": "44248156",
"field_nine":"65037768"
}
}考虑到上面json作为我的模型的一个表示,我只想更新那些传入json中的字段(主键是Id,它将始终在那里)。是否有任何方法可以实现,而不必显式地检查每个字段并设置它们?
如果我收到这样的请求:
{
"some_model":{
"id":"5527716",
"field_one": "44248156",
"field_two": "44248156",
"field_three": "44248156",
"field_eight": "44248156",
"field_nine":"65037768"
}
}我只想使用repository.save或类似的东西来实现更新(插入类的东西)。目前,使用存储库的保存方法在内部使用primaryKey值更新模型,但将缺失字段的值设置为null。我希望这些字段保持不变。
主要问题是:有数百个模型,每个模型大约有10-15个字段,显式检查每个字段并更新所有模型将是一场噩梦。
我还检查了@DynamicUpdate注释,但它似乎适用于优化生成的sql的显式设置。
我希望对此有任何想法。
发布于 2018-06-29 05:05:16
我发现我的问题的确切要求不能得到满足。Dozer Bean Mapper似乎是一个选项,但更多的是映射不同类的bean对象,在那里我们可以对应要映射的字段,这不是我的情况。
解决方案是改变在执行更新时发送所有所需信息的方法。
正如西蒙在评论中指出的:
简单的回答:那是不可能的。因为反序列化之后,如果字段丢失,则值为null。Java是一种静态类型化语言,不能很好地满足您的要求。
发布于 2018-05-30 12:48:41
通常,合并将对您有效,因为您得到了独立的副本--从JSON获得的副本和持久化的副本(来自存储库)。Merge正是这样做的--用分离的属性的值更新持久化属性,如果没有值,它就创建它(我不确定该部分是否需要)。仍然是自动的,你失去了你自己写它的灵活性。
对于JPA,合并方法是EntityManager的一部分。因此,您需要注入它并将其称为em.merge(detachedEntity);
除此之外,还有一些库可以这样做,但我没有使用任何库。需要进行一些编码的最佳解决方案是编写手动更新字段的方法;)
发布于 2018-05-30 12:45:11
看看杜泽尔 --一个bean映射库。您可以使用自定义字段映射器配置dozer,如果字段为null,则不复制字段。
您可以从DB检索对象,将字段值从请求对象复制到从DB检索的对象(使用不映射空值的自定义字段映射程序),然后保存对象。
User user1 = new User(); // Request body
user1.setFirstName("newFn");
User user2 = new User(); // Entity retrieved from the database
user2.setFirstName("fn");
user2.setLastName("ln");
DozerBeanMapper dozerBeanMapper = new DozerBeanMapper();
dozerBeanMapper.setCustomFieldMapper(
(source, destination, sourceFieldValue, classMap, fieldMapping) -> sourceFieldValue == null);
dozerBeanMapper.map(user1, user2);
System.out.println(user2); // User(firstName=newFn, lastName=ln)参考文献:https://stackoverflow.com/a/36716023/1377058
如果不希望将dozer作为依赖项添加,还可以使用BeanUtils只复制那些非空属性。看看这的问题,了解如何做它的细节。
https://stackoverflow.com/questions/50604647
复制相似问题