I use the Spring framework in my project, I stuck with the identification of DTO to be saved. I have a #RestController PUT-method end-point. I need to implement the logic: if an entity exists than override at DB else create a new one. So if the client will submit DTO 2 times it will 2 duplicated DTOs at DB. The only option I see to identify by ID(Actually, it how Spring Data operates out-of-the-box if id exists then override values of the entity). However, how can I hide this id from the client? Thanks.
P.S: Create a UNIQUE index for all fields and compare DTO by all fields is NOT the solution in my case.
Many thanks.
Annote #JsonIgnore on ID for the DTO will solve your problem to hide ID to the client. The best way is to map that DTO to Entity and do further operation.
You can check more details on this link.
Related
I'm currently in the process of migrating an API built in Laravel/PHP to Spring Boot and had a question on best practice/how to approach the problem.
In laravel, I have a User model, with 3 child relationships: roles, communities and profiles. In laravel, I'd use Resources to dictate the data I'm returning in an API response, for example a GET /id would return the user with all of the child relationships, where as on a GET / list operation, it would return the base model with no child relationships.
What is the best way to replicate this with Spring Boot JPA? I had looked into Jackson JsonViews, however this only seems to reduce the object returned by the API, rather than limiting the amount of SQL queries being ran.
Any suggestions are appreciated. Thanks!
If all of your relationships are Lazy (as they normally should be), then JsonViews is the right solution.
Whenever the joins are lazy, there is no query for the child data until the field has been accessed. So if the JsonView on / excludes the roles member of the User object, then the Json serializer will never call user.getRoles(), so the query is never run.
But if the JsonView for /id does include roles, then the serializer will have to call user.getRoles(), and at that time the query is run.
If you need even more optimization, then you can also attach an EntityGraph to a function on your repository like this:
public class UserRepository<User,Long> {
#EntityGraph(attributePaths = {"roles", "communities", "profiles"})
User getDetailedUserById(Long id);
}
This will force Eager loading for those otherwise lazy attributes, which means there will only be one query run.
I have a project where I need to store Users on database. I'm using Hibernate and in some part of module also Spring Data JPA experimentally.
I have a REST endpoint for register customer and I'm receiving there UserDTO object. After that in other service I need to convert it to UserEntity and save in database.
Now I created user settings page where I need to display some information about logged user. I don't want to sent UserDTO object because there is to much data so I need to create one more DTO class and Converter class. I feel it's a little bit tricky because every time when I wan to store or receive some specific data, I need to create new DTO and converter class so I have a lot of DTOs and Converters in my project. When I will need to change something on my Entity class, probably I will need also change a lot of converters.
Is this correct way or do you have any better solution for that?
You can use projection queries to create your DTO-s without converters.
Here is a short example with explanation: JPA - Basic Projections
I have a class named Genre (a #Entity), having only one field "name" (which is also id), in my Spring Boot application. It works fine, but now I realized - maybe I can't use the CRUDRepository to update a genre...
Since if I send in an altered Genre to genreRepository.save() - how can it find it? Can I make my own query to update it by name? Or must I add a new Id-field to the entity?
Greetings Val
First thing is I advice you to reconsider your design since it only contains one column "name", to my understanding normally you might not want to use the string as a primary key, I think its better to use a separate column such as "ID" which will uniquely identify each row in a table, when you do that there are bunch of options provided in the spring boot and then using Spring CRUD Repository make more sense
As answered already in this Question
(How to use spring Repository without #Id?)
JPA requires that every entity has an ID.
I have entity with updatedAt and updatedBy audit fields. I want to set this fields only if entity state was changed. So, for dirty checking I can use either Hibernate EmptyInterceptor interface (overriding onFlushDirty() method) or JPA listeners (#PreUpdate). But how I can get current userId inside interceptor or listener? To my mind comes 2 solutions:
Pass userId to DAO layer, so I can create custom interceptor passing to it constructor userId and then use this interceptor when creating new Session.
Set current userId to public-static ThreadLocal variable so I have access to it from any place.
But I think both approaches are ugly. So may be there is exist some more elegant way to solve my problem?
Please note, I can't use Envers library (it don't fit our project requirements).
Thanks.
I recommend storing the Person object in the Http session when the user authenticates. This way you can grab it from the session and use the merge functionality in the entity manager to convert it back to an attached entity.
I personally also assign the entity to the requiring domain object in the dao and do not use the #PreUpdate because I do not want the entity to have to know how to retrieve the current user object.
Am having a registration form which has multiple pages. So, I am mapping one page to one pojo. Finally, when I processing with database, I want to make it as single pojo to commit. Any idea to simplify this model.
Thanks :)
You can create a wrapper POJO which holds your other POJO's with additional helper methods in the master POJO.
What is wrong with sending multiple POJOs to your service level to commit to the database. Koekiebox's suggestion of a wrapper POJO will work, but also will add another place to make changes to if you add or remove POJOs.
If the data truly belongs together why not increase the number of fields in your POJO and use just one for your form and database.