Reputation: 13
I am using java+Spring framework+Hibernate for creating rest api but I have stumbled upon retrieving details of a table using foreign key attributes. I have the following tables::
https://i.sstatic.net/lG7UR.png
I am retrieving all the ratings given using product id and then mapping to DTO, now I also want to populate the username using idusers as this is my foreign key.
Same is the case when I try to retrieve ratings given by the users, instead of displaying idproducts I want to display the product name and product description as It is a foreign key.
Any advice on how to do so using DTO's.
Upvotes: 1
Views: 4893
Reputation: 16452
This is a perfect use case for Blaze-Persistence Entity Views.
Blaze-Persistence is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model. I created Entity Views on top of it to allow easy mapping between JPA models and custom interface defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure the way you like and map attributes(getters) via JPQL expressions to the entity model. Since the attribute name is used as default mapping, you mostly don't need explicit mappings as 80% of the use cases is to have DTOs that are a subset of the entity model.
Assuming you have an entity model like this
@Entity
public class User {
@Id
Integer id;
String role;
String username;
String password;
boolean enabled;
}
@Entity
public class Product {
@Id
Integer id;
String imageUrl;
String category;
int productPrice;
int productQuantity;
String productName;
String productDesc;
@OneToMany(mappedBy = "product")
Set<Rating> ratings;
}
@Entity
public class Rating {
@Id
Integer id;
int rating;
String review;
String ratingscol;
@ManyToOne(fetch = LAZY)
Product product;
@ManyToOne(fetch = LAZY)
User user;
}
A DTO mapping for your model could look as simple as the following
@EntityView(Rating.class)
interface RatingDto {
Integer getId();
UserDto getUser();
ProductDto getProduct();
}
@EntityView(User.class)
interface UserDto {
Integer getId();
String getUsername();
}
@EntityView(Rating.class)
interface ProductDto {
Integer getId();
String getProductName();
String getProductDesc();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
RatingDto dto = entityViewManager.find(entityManager, RatingDto.class, id);
But 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
It will only fetch the mappings that you tell it to fetch
Upvotes: 1
Reputation: 311
You can use ModelMapper when converting a DTO to an Entity bean and back from Entity bean to a DTO.
Add ModelMapper to your project
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.5</version>
</dependency>
Define the ModelMapper bean in your Spring configuration
@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
Assuming the following models based on the given ER diagram you have given
public class UserDto {
Integer userId;
String role;
String username;
String password;
boolean enabled;
...default and parameterized constructor
...getter and setter methods
}
public class ProductDto {
Integer productId;
String imageUrl;
String category;
int productPrice;
int productQuantity;
String productName;
String productDesc;
...default and parameterized constructor
...getter and setter methods
}
public class RatingDto {
@Id
Integer id;
int rating;
String review;
String ratingscol;
ProductDto productDto;
UserDto userDto;
...default and parameterized constructor
...getter and setter methods
}
You can retrieve the ratings of a product using product id along with the user details by using the following method
@Repository
public interface RatingRepository extends JpaRepository<Rating, Integer>{
List<Rating> findByProduct_ProductId(Integer productId);
}
Then mapping rating objects to DTO
RatingDto ratingDto = modelMapper.map(rating, RatingDto.class);
Now you can retrieve username as following
ratingsDto.getUserDto().getUserName()
The same way you can retrieve the ratings by userId and access product details
Upvotes: 0