【问题标题】:List Results Mapping Spring JPA列出结果映射 Spring JPA
【发布时间】:2023-03-15 11:38:01
【问题描述】:

我使用 PostgreSQL,并且我有这些表,product 和 product_media 与 product_media 上的关系 OneToMany。我想检索一个包含产品的列表,其中每个产品都包含一个 product_media 列表。 为了从数据库中检索它们,我有两个选择。

第一个解决方案是首先检索产品列表,然后迭代检索到的列表并执行查询以检索产品媒体列表。

查询1:

select * from product as p where p.status=1;

检索列表,然后迭代此列表并执行此查询:

select * from product_media as pm where pm.product_id=?

其次是实现查询中的联接并从我的数据库中检索所有数据。 查询:

select * from product as p Join product_media as pm on (p.id=pm.product_id)

检索包含所有数据的复杂列表。 第二个选项的问题是不知道将这个列表映射到具有以下格式的对象的优雅方法。你知道如何将结果自动映射成这种格式吗?

product:[
    {
       id:1,
       name:'Pro1',
       medias:[
         {
            id:1,
            uuid:'asdfi-asdf-rg-fgsdf-do'
         },
         {
            id:2,
            uuid:'asdfi-asdf-rg-fgsdf-do'
         }    
       ]
    },
    {
       id:2,
       name:'Pro2',
       medias:[
         {
            id:5,
            uuid:'asdfi-asdf-rg-fgsdf-do'
         },
         {
             id:7,
             uuid:'asdfi-asdf-rg-fgsdf-do'
         }    
       ]
    }
]

【问题讨论】:

  • 您正在使用 JPA,因此您应该简单地拥有一个 OneToMany 关联,并使用一个 JPQL(不是 SQL)查询和一个连接提取。docs.jboss.org/hibernate/orm/5.1/userguide/html_single/…跨度>
  • 如果你打算使用 JPA,那么你应该……嗯……你应该使用 JPA。你在哪里说你想要 JSON 在哪里?
  • 从发布的回复中我可以看到你有多对多的关系

标签: java spring postgresql jpa


【解决方案1】:

如果您的回复不是json 格式,您可以在下面尝试

ProductMedia 之间存在多对多关系。

Product_Media 是一个辅助表,用于维护ProductMedia 实体之间的多对多关系。

产品实体:

@Entity(name = "product")
public class Product {

    @Id
    @GeneratedValue
    private Long product_id;

    @Column
    private String name;

    @ManyToMany(cascade = { CascadeType.MERGE }, fetch = FetchType.EAGER)
    @JoinTable(name = "product_media", joinColumns = {
            @JoinColumn(name = "product_id", table = "product") }, inverseJoinColumns = {
                    @JoinColumn(name = "media_id", table = "media") })
    List<Media> medias;

}

媒体实体

@Entity(name = "media")
public class Media {

    @Id
    @GeneratedValue
    private Long media_id;

    @Column
    private String name;

}

Hibernate 生成的 SQL

select
    product0_.product_id as product_1_1_0_,
    product0_.name as name2_1_0_,
    medias1_.product_id as product_1_1_1_,
    media2_.media_id as media_id2_2_1_,
    media2_.media_id as media_id1_0_2_,
    media2_.name as name2_0_2_ 
from
    product product0_ 
left outer join
    product_media medias1_ 
        on product0_.product_id=medias1_.product_id 
left outer join
    media media2_ 
        on medias1_.media_id=media2_.media_id 
where
    product0_.product_id=?

如果关系是一对多,则如下更改实体

媒体实体

@Entity(name = "media")
public class Media {

    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String name;

    @ManyToOne
    @JoinColumn(name = "product_id", referencedColumnName = "id", nullable = false, updatable = false)
    private Product product;

    public Media() {

    }
}

产品实体

@Entity(name = "product")
public class Product {

    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String name;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "product")
    List<Media> medias;
}

Hibernate 生成的 SQL

select
    product0_.id as id1_2_0_,
    product0_.name as name2_2_0_,
    medias1_.product_id as product_3_2_1_,
    medias1_.id as id1_0_1_,
    medias1_.id as id1_0_2_,
    medias1_.name as name2_0_2_,
    medias1_.product_id as product_3_0_2_ 
from
    product product0_ 
left outer join
    media medias1_ 
        on product0_.id=medias1_.product_id 
where
    product0_.id=?

【讨论】:

  • 我现在有这些实体。但是对于每个产品都应该执行一个查询来检索与产品相关的所有媒体。
  • 使用第二个选项,带连接的SQL,如果你使用上面的代码,它会创建一个带连接的SQL并执行
  • 是的,我的查询是:选择 p.id 作为 id,p.name_el 作为 name_el,pm.id 作为 media_id,pm.multimedia_path 作为 media_path 从产品作为 p 加入 product_multimedia 作为 pm on (p. id=pm.product_id) 我想将结果映射到 Product.class
  • Pro1和Pro2是同一个媒体,你确定是一对多的关系吗,我相信是多对多的
  • 我确信这是 oneToMany 关系。这是一个例子
【解决方案2】:

我认为第二种变体是更好的选择。从数据库中获取对象树后,您可以执行以下操作来实现上面发布的内容:

  1. 假设您的实体定义如下:

    Product.java

    public class Product {
    
        private long id;
        private String name;
        private List<ProductMedia> mediaList;
    
    
        public Product() {
            mediaList = new ArrayList<ProductMedia>();
        }
    
        public Product(long id, String name) {
            this.id = id;
            this.name = name;
            mediaList = new ArrayList<ProductMedia>();
        }
        // getters + setters
    }
    

    ProductMedia.java

    public class ProductMedia {
        private long id;
        private String uuid;
    
        public ProductMedia() { }
    
        public ProductMedia(long id, String uuid) {
            this.uuid = uuid;
        }
        // getters + setters
    }
    
  2. 使用 Jackson 库,您可以生成如下输出:

    public class JsonTest {
    
        public static void main(String[] args) throws IOException {
    
            ObjectMapper mapper = new ObjectMapper();
    
            mapper.enable(SerializationFeature.INDENT_OUTPUT);
    
            Product prod = new Product(1, "p1");
    
            ProductMedia pm = new ProductMedia(1, "uuid1");
            ProductMedia pm2 = new ProductMedia(2, "uuid2");
    
            prod.getMediaList().add(pm);
            prod.getMediaList().add(pm2);
    
    
            Product prod1 = new Product(2, "p2");
    
            ProductMedia pm3 = new ProductMedia(3, "uuid3");
            ProductMedia pm4 = new ProductMedia(4, "uuid4");
    
            prod1.getMediaList().add(pm3);
            prod1.getMediaList().add(pm4);
    
            Product[] pList = {prod, prod1};
    
            mapper.writeValue(System.out, pList);
        }
    }
    

    在本例中,我将输出写入控制台。但你不限于此;您可以写入通过 FileOutputStream 传递的文件。

为了能够运行这个例子,你需要添加依赖;如果您使用 Maven,您可以将以下内容添加到您的 POM 中:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.7.4</version>
    </dependency>

否则将依赖项的jar添加到您的项目构建路径中。

【讨论】:

  • 我想你八岁了,但是如何迭代检索到的数据呢?使用 for 和 if 语句?
  • 为什么要迭代?如果对象映射正确,则不需要进行迭代。该框架将为您完成。正如您在示例中看到的,我自己进行了映射;但如果映射正确完成,持久性提供程序将返回与子项正确嵌套的产品。
  • 我有这个列表,其中每个对象都有每个元组的属性,然后我应该迭代以获取包含所有数据的 Json 对象。 List productTests = productRepository.getProductTest();
  • SQL 查询返回具有以下属性的元组:product_id、product_name、media_id、media_uuid
  • 您的查询返回product 对象列表,每个元素都包含media 对象列表,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-12
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多