This is not production-ready code.
I created this code only for demonstrational purposes.
This project demonstrates one more way of using records as DTOs (data transfer objects).
It utilizes an in-memory H2 database (so no additional DB services are required), Spring Boot and Hibernate frameworks.
Entities:
TagNote
DTOs:
TagDtoNoteDto
Content objects:
TagContentNoteContent
Models are used only within the service layer.
The service layer consumes/produces DTOs and content objects.
The content objects are purposed to transfer an object's content (like tag color and name).
DTOs and content objects are immutable Java records.
To demonstrate the process, I created very simple REST controllers (NoteController and TagController).
For example:
@PutMapping(PREFIX + VERSION + "/tags/{id}")
TagDto updateTagContent(@PathVariable long id, @RequestBody TagContent content) {
TagDto tag = tagService.getTagById(id).orElseThrow(() -> new NoSuchItemException("tag " + id));
return tagService.updateTagContent(tag, content).orElseThrow(() -> new NotUpdatedException("tag " + id));
}Here is the service method:
@Transactional
public Optional<TagDto> updateTagContent(TagDto tag, TagContent content) {
return Functions.checkTagDto.apply(tag)
.flatMap(t -> repository.getTagById(t.id()))
.flatMap(t -> setTagNameAndColor(t, content.name(), content.color()))
.map(repository::saveAndFlush)
.flatMap(t -> repository.findById(t.getId()));
}A DTO is received, checked, and "transformed" into a model. Then, the model properties are updated. After that, an updated DTO is fetched and returned.
Here is the corresponding repository method:
@QueryHints(value = {
@QueryHint(name = READ_ONLY, value = "true")
})
@Transactional(readOnly = true)
@Query(value = "SELECT new dev.isdn.demo.records_dto.app.domain.tag.TagDto(t.id, t.name, t.color) FROM tags t WHERE t.id = :id")
Optional<TagDto> findById(@Param("id") long id);So, there is no need for special "mapper" functions to convert DTOs/models.
mvn clean testmvn clean package -DskipTests
java --enable-preview -jar target/records-dto-demo-0.1.jaror
mvn clean spring-boot:runList of notes:
curl -i http://127.0.0.1:8080/v1/notesCreate notes:
curl -i -H 'Content-type:application/json' -d '{"content":"test"}' -X POST http://127.0.0.1:8080/v1/notes
curl -i -H 'Content-type:application/json' -d '{"content":"another test"}' -X POST http://127.0.0.1:8080/v1/notes
curl -i -H 'Content-type:application/json' -d '{"content":""}' -X POST http://127.0.0.1:8080/v1/notesDelete a note:
curl -i -X DELETE http://127.0.0.1:8080/v1/notes/766714176451034115Get a note:
curl -i http://127.0.0.1:8080/v1/notes/2119985630772393670Update a note:
curl -i -H 'Content-type:application/json' -d '{"content":"test updated"}' -X PUT http://127.0.0.1:8080/v1/notes/8465407150649195493Get note tags:
curl -i http://127.0.0.1:8080/v1/notes/8465407150649195493/tagsList of tags:
curl -i http://127.0.0.1:8080/v1/tagsCreate tags:
curl -i -H 'Content-type:application/json' -d '{"name":"test1", "color":"ffffff"}' -X POST http://127.0.0.1:8080/v1/tags
curl -i -H 'Content-type:application/json' -d '{"name":"test2"}' -X POST http://127.0.0.1:8080/v1/tags
curl -i -H 'Content-type:application/json' -d '{"name":"test3"}' -X POST http://127.0.0.1:8080/v1/tagsDelete a tag:
curl -i -X DELETE http://127.0.0.1:8080/v1/tags/614426635004842295Get a tag:
curl -i http://127.0.0.1:8080/v1/tags/4760561560720237306Update a tag:
curl -i -H 'Content-type:application/json' -d '{"name":"test3_updated", "color": "AAaaAA"}' -X PUT http://127.0.0.1:8080/v1/tags/4760561560720237306Get tag notes:
curl -i http://127.0.0.1:8080/v1/tags/4760561560720237306/notesAdd tags to a note:
curl -i -X PUT http://127.0.0.1:8080/v1/notes/8465407150649195493/tags/4760561560720237306
curl -i -X PUT http://127.0.0.1:8080/v1/notes/8465407150649195493/tags/362170154209224171Delete a tag from a note:
curl -i -X DELETE http://127.0.0.1:8080/v1/notes/8465407150649195493/tags/362170154209224171