Skip to content

Instantly share code, notes, and snippets.

@alexandre-jacquot-ptl
Created May 23, 2021 12:57
Show Gist options
  • Save alexandre-jacquot-ptl/8e4c5ec724e75b52951b49ca7d70c9c0 to your computer and use it in GitHub Desktop.
Save alexandre-jacquot-ptl/8e4c5ec724e75b52951b49ca7d70c9c0 to your computer and use it in GitHub Desktop.
r2dbc ItemService update
@Service
@RequiredArgsConstructor
public class ItemService {
private final ItemRepository itemRepository;
private final ItemTagRepository itemTagRepository;
private final TagMapper tagMapper;
/**
* Update an Item
* @param itemToSave item to be saved
* @return the saved item without the related entities
*/
@Transactional
public Mono<Item> update(Item itemToSave) {
if(itemToSave.getId() == null || itemToSave.getVersion() == null) {
return Mono.error(new IllegalArgumentException("When updating an item, the id and the version must be provided"));
}
return verifyExistence(itemToSave.getId())
// Find the existing link to the tags
.then(itemTagRepository.findAllByItemId(itemToSave.getId()).collectList())
// Remove and add the links to the tags
.flatMap(currentItemTags -> {
// As R2DBC does not support embedded IDs, the ItemTag entity has a technical key
// We can't just replace all ItemTags, we need to generate the proper insert/delete statements
final Collection<Long> existingTagIds = tagMapper.extractTagIdsFromItemTags(currentItemTags);
final Collection<Long> tagIdsToSave = tagMapper.extractTagIdsFromTags(itemToSave.getTags());
// Item Tags to be deleted
final Collection<ItemTag> removedItemTags = currentItemTags.stream()
.filter(itemTag -> !tagIdsToSave.contains(itemTag.getTagId()))
.collect(Collectors.toList());
// Item Tags to be inserted
final Collection<ItemTag> addedItemTags = tagIdsToSave.stream()
.filter(tagId -> !existingTagIds.contains(tagId))
.map(tagId -> new ItemTag(itemToSave.getId(), tagId))
.collect(Collectors.toList());
return itemTagRepository.deleteAll(removedItemTags)
.then(itemTagRepository.saveAll(addedItemTags).collectList());
})
// Save the item
.then(itemRepository.save(itemToSave));
}
...
private Mono<Boolean> verifyExistence(Long id) {
return itemRepository.existsById(id).handle((exists, sink) -> {
if (Boolean.FALSE.equals(exists)) {
sink.error(new ItemNotFoundException(id));
} else {
sink.next(exists);
}
});
}
...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment