Reputation: 53
I have an entity called "Review" that has a OneToOne relationship with a "User" entity and a OneToMany relationship with a "ReviewStage" entity. I have implemented a DTO pattern so, I also have ReviewDTO which is actually what is being sent to the UI. I am using mapstruct to map the entity to dto. All is working well however, I would rather use the UserDTO and ReviewStageDTO in the relationship mappings.
This works well:
@Entity
@Getter @Setter @NoArgsConstructor
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long reviewId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ownerId")
private User owner;
@OneToMany(mappedBy = "reviewId")
private Set<ReviewStage> stages;
}
For fun, I tried this but, obviously doesn't work:
@Entity
@Getter @Setter @NoArgsConstructor
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long reviewId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ownerId")
private UserDTO owner;
@OneToMany(mappedBy = "reviewId")
private Set<ReviewStageDTO> stages;
}
I just need a nudge in the right direction. Thanks,
Upvotes: 2
Views: 2244
Reputation: 16400
If you are concerned about the performance, I can recommend you take a look at what Blaze-Persistence Entity Views has to offer.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
@EntityView(Review.class)
public interface ReviewDTO {
@IdMapping
Long getReviewId();
UserDTO getOwner();
Set<ReviewStageDTO> getStages();
@EntityView(User.class)
interface UserDTO {
@IdMapping
Long getId();
String getName();
}
@EntityView(ReviewStage.class)
interface ReviewStageDTO {
@IdMapping
Long getId();
String getName();
}
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
ReviewDTO a = entityViewManager.find(entityManager, ReviewDTO.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Optional<ReviewDTO> findByReviewId(long reviewId);
Note that this will only fetch the state that is actually required. With MapStruct or other bean-mapping solutions you have to handle efficient fetching yourself.
Upvotes: 0
Reputation: 1134
The relationships
should be between entities
only and if you want to make a dto
for Review
and inside this dto
you want to return the UserDto
for example you should create a mapstruct class
to map between UserEntity
to UserDTO
Example
class UserDto {
/// put any fields here that you want to map
}
class ReviewDto {
UserDto user;
}
@Mapper(componentModel = "spring")
class UserMapper {
UserDto map(User user);
}
@Mapper(componentModel = "spring", uses={UserMapper.class})
class ReviewMapper {
ReviewDto map(Review review);
}
Upvotes: 1