Я создаю Rest API для базы данных MongoDB, используя MongoRepository. Я хочу создать конечную точку, которая использует «RequestMethod.PATCH» и реализует функциональность «PATCH»: дельта-обновление с полями, предоставленными в @RequestBody.
Функциональность, которую я хочу, уже существует в «Spring Data Rest» с использованием аннотации «@RepositoryRestResource» в моем классе Repository, как описано здесь https://spring.io/guides/gs/accessing-data-rest/
Но я не хочу так раскрывать свой класс репозитория. Мне нравится классическая линия Controller->Service->Repository. Мой контроллер выглядит так:
@RestController
public class ActivitiesController {
@Autowired
ActivitiesService activitiesService;
@RequestMapping(value="activities", method=RequestMethod.PATCH)
public ActivityModel updateActivity(
@RequestBody ActivityModel activityModel
){
//Input ActivityModel will only have subset of fields that have been changed, aka the delta
return activitiesService.update(activityModel);
}
@RequestMapping(value="activities", method=RequestMethod.PUT)
public ActivityModel updateActivity(
@RequestBody ActivityModel activityModel
){
//Input ActivityModel will have all fields populated
return activitiesService.save(activityModel);
}
}
И мой репозиторий здесь:
@Repository
public interface ActivitiesRepo extends MongoRepository<ActivityModel, String> {
//out of the box implementation
}
Моя проблема в том, что, насколько я могу судить, MongoRepository не предоставляет дельта-обновления из коробки, как это делает Spring Data Rest. Как я могу реализовать эту функциональность на уровне службы здесь?:
@Service
public class ActivitiesService {
@Autowired
ActivitiesRepo activitiesRepo;
public ActivityModel update(ActivityModel activityModel){
//delta update implementation, aka PATCH implementation
}
//method that should only be used with RequestMethod.PUT
public ActivityModel save(ActivityModel activityModel){
return activitiesRepo.save(activityModel);
}
}
Что вы думаете об этом решении для ручной реализации PATCH:
public class ModelUtil {
public static <T> Object update(Object origModel, Object dirtyModel, Class<T> clazz){
ObjectMapper m = new ObjectMapper();
HashMap<String, Object> origModelAsMap = m.convertValue(origModel, new TypeReference<Map<String, Object>>() {});
HashMap<String, Object> dirtyModelAsMap = m.convertValue(dirtyModel, new TypeReference<Map<String, Object>>() {});
dirtyModelAsMap.forEach((k, v)-> {
origModelAsMap.put(k, v);
});
return m.convertValue(origModelAsMap, clazz);
}
}