What I do when I have to perform patch request for an Entity with LocalDateTime attribute:
Lets for clarity say that your Entity having attribute LocalDateTime date is modeled with an Event.class:
@NoArgsConstructor
@Getter
@Setter
@Entity(name = "events")
...
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long eventId;
...
@Column(nullable = false)
private LocalDateTime date;
...
1) Se externally the LocalDateTime format pattern in application.properties file:
config.datetime.format.pattern=yyyy-MM-dd HH:mm
2) Create a class AppConfig.class (or something like that) to extract the value from the application.properties file:
@Configuration
public class AppConfig {
@Value("${config.datetime.format.pattern}")
private String formatPattern;
public DateTimeFormatter getDateTimeFormatter(){
return DateTimeFormatter.ofPattern(formatPattern);
}
}
3) Add the AppConfig dependency to your service class:
@Service
public class EventService {
private final EventRepository eventRepo;
private final EventDtoMapper eventDtoMapper;
private final AppConfig appConfig;
...
@Autowired
public EventService(EventRepository eventRepo, EventDtoMapper eventDtoMapper, AppConfig appConfig, ...) {
this.eventRepo = eventRepo;
this.eventDtoMapper = eventDtoMapper;
this.appConfig = appConfig;
...
}
4) Write the service code for the function that will do the partial update:
public EventDtoForCreate updatePartially(Long id, Map<String, String> fields) {
Optional<Event> found = eventRepo.findById(id);
if (found.isEmpty()) {
// custom exception
throw new ResourceNotFoundException("Failed to find event");
}
fields.forEach((key, value) -> {
Field field = ReflectionUtils.findField(Event.class, key);
if (field != null) {
field.setAccessible(true);
if (field.getAnnotatedType().getType().equals(LocalDateTime.class)) {
ReflectionUtils.setField(field, found.get(), LocalDateTime.parse(value, appConfig.getDateTimeFormatter()));
} else {
ReflectionUtils.setField(field, found.get(), value);
}
}
});
return eventDtoMapper.toDtoCreate(eventRepo.save(found.get()));
}
5) Finally, create the controller for the patch request:
@PatchMapping(
value = "/{id}",
produces = {MediaType.APPLICATION_JSON_VALUE}
)
public ResponseEntity<EventDtoCreate> updatePartially(
@PathVariable(name = "id") Long userId,
@RequestBody Map<String, String> fields
) {
return ResponseEntity.ok(eventService.updatePartially(userId, fields));
}