#Spring Boot JPA Relationship practices

17 messages · Page 1 of 1 (latest)

sacred brook
#

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!

drifting mistBOT
#

This post has been reserved for your question.

Hey @sacred brook! Please use /close or the Close Post button above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

drifting mistBOT
#

💤 Post marked as dormant

This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.

wind idol
# sacred brook I'm currently in the process of migrating an API built in Laravel/PHP to Spring ...

To lazily load your relations, you can use the @Column annotation with the fetch attribute set to LAZY value to never load relations upon entity load.

At that point, calling getX() where X is a relation will trigger a database query to fetch the requested relation.

Be careful! You might have set spring.jpa.open-in-view to false in your application.properties because Spring Boot told you it wasn't nice, you will need to put it back to true (if explicitly set, you don't receive a warning).


An alternative to JsonViews that can quickly make your code messy, you can have two different DTOs representing users depending whether or not you need the relations.

public record SimpleUserDto(String username) {

  public static SimpleUserDto from(User user) {
    return new SimpleUserDto(user.getUsername());
  }
}

public record UserDto(String username, List<FriendDto> friends) {

  public static UserDto from(User user) {
    return new UserDto(user.getUsername(), user.getFriends().stream().map(FriendDto::from).toList());
  }
}

And your controller return one of these depending on what you need to return

sacred brook
#

Thanks for the response, I’ll check this out when I’m back in office, but the advice makes sense, thank you!

wind idol
#

Now, this can be a little bit ugly as your view (in the MVC model) calls your database... it sorta breaks the model.

To fix that, your service can return DTO itself.
UserService#findByUsername(String username) => SimpleUserDto
UserService#findByUsernameWithRelations(String username) => UserDto

And therefore as soon as the service layer is no longer involved, all the required database calls would've been done

At which point your controller can return directly that Dto, assuming it doesn't contain anything such as a password
Or you can have another bridge, an actual view that's built using the service's dto.

sacred brook
#

So In your example, is the service akin to the repository? Ie my User model has a UserRepository, implementing the CrudRepository class

real void
#

Essentially, it's controller -> service -> repository, and those three are separate layers of the "onion model" that spring is designed around

#

Keke is correct in that your service should be the only layer which accesses the database via repositories

amber kettle
#

wb spring data rest?

#

This way you dont need to worry about endpoints for manipulating the resources since it's all done for you

sacred brook
#

I’ll need to do more research. Currently (in my sort of POC/mock-up) I do controller -> repo -> model

#

I’ll take a closer look tomorrow when I’m back in office and report back

drifting mistBOT
#

💤 Post marked as dormant

This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.

sacred brook
#

Hey folks, currently getting into this a bit, and I appreciate the advice thus far. For some reason the following: ```java
@Getter
@JoinTable(
name = "communities_tags",
joinColumns = @JoinColumn(name = "community_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
@ManyToMany(fetch = FetchType.LAZY)
private Set<CommunityTag> tags;