【问题标题】:Retrieving foreign key attributes in DTO在 DTO 中检索外键属性
【发布时间】:2020-06-18 13:04:48
【问题描述】:

我正在使用 java+Spring 框架+Hibernate 来创建 rest api,但我偶然发现了使用外键属性检索表的详细信息。 我有以下表格::

https://i.stack.imgur.com/lG7UR.png

我正在检索使用产品 ID 给出的所有评级,然后映射到 DTO,现在我还想使用 idusers 填充用户名,因为这是我的外键。

当我尝试检索用户给出的评分时也是如此,而不是显示 idproducts 我想显示产品名称和产品描述,因为它是一个外键。

关于如何使用 DTO 的任何建议。

【问题讨论】:

  • 分享一些你正在尝试的代码
  • 我意识到我只需要简单地使用 UserDTO 对象来检索用户 ID,然后访问 UserDTO 字段来检索用户名

标签: spring hibernate orm dto object-model


【解决方案1】:

在将 DTO 转换为实体 bean 以及从实体 bean 转换为 DTO 时,您可以使用 ModelMapper。

将 ModelMapper 添加到您的项目中

<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.5</version>
</dependency>

在 Spring 配置中定义 ModelMapper bean

@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}

根据您给出的给定 ER 图假设以下模型

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
}

您可以通过以下方法使用产品 ID 和用户详细信息检索产品的评级

 @Repository
 public interface RatingRepository extends JpaRepository<Rating, Integer>{
 List<Rating> findByProduct_ProductId(Integer productId);
 }

然后将评级对象映射到 DTO

 RatingDto ratingDto = modelMapper.map(rating, RatingDto.class);

现在您可以按以下方式检索用户名

 ratingsDto.getUserDto().getUserName()

与通过 userId 检索评级和访问产品详细信息的方式相同

【讨论】:

    【解决方案2】:

    这是Blaze-Persistence Entity Views 的完美用例。

    Blaze-Persistence 是基于 JPA 的查询构建器,它支持 JPA 模型之上的许多高级 DBMS 功能。我在它之上创建了实体视图,以允许在 JPA 模型和自定义接口定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您以您喜欢的方式定义您的目标结构,并通过 JPQL 表达式将属性(getter)映射到实体模型。由于属性名称用作默认映射,因此您通常不需要显式映射,因为 80% 的用例是拥有作为实体模型子集的 DTO。

    假设你有一个这样的实体模型

    @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;
    }
    

    模型的 DTO 映射可能如下所示简单

    @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();
    }
    

    查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

    RatingDto dto = entityViewManager.find(entityManager, RatingDto.class, id);

    但是 Spring Data 集成允许您几乎像 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

    它只会获取您告诉它获取的映射

    【讨论】:

    • 这是我想要使用的,它不仅为我们提供了优于惰性配置的优势,而且在性能方面也有优势。非常感谢!
    猜你喜欢
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 2022-12-10
    • 2015-06-03
    • 2011-08-03
    • 1970-01-01
    相关资源
    最近更新 更多