Spring内容。 Hibernate 执行 3 个查询来获取每个产品的图像

Spring Content. Hibernate executes 3 queries to fetch image for each product

我有一个产品页面。每个列出的产品都有自己的图像。 要在视图中显示它,我使用此行 <img th:src="@{/data/{id}(id=${product.id})}"

当我去端点查看产品时,Hibernate 生成 7 个查询而不是 1 个。

Hibernate: 
    select
        product0_.id as id1_0_,
        product0_.content_id as content_2_0_,
        product0_.content_length as content_3_0_,
        product0_.mime_type as mime_typ4_0_,
        product0_.name as name5_0_ 
    from
        product product0_
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?

问题可能与我在页面上接收图像的方式有关。 我假设它是这样发生的:ProductRepository 通常执行 1 个查询来获取产品列表。 然后在页面 Spring 上显示图像,对每个产品执行 3 个查询。 我还注意到带有图像 "/data/1" 的端点会产生 3 个查询。

Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?
Hibernate: 
    select
        product0_.id as id1_0_0_,
        product0_.content_id as content_2_0_0_,
        product0_.content_length as content_3_0_0_,
        product0_.mime_type as mime_typ4_0_0_,
        product0_.name as name5_0_0_ 
    from
        product product0_ 
    where
        product0_.id=?

如何优化这个过程并执行更少的查询? 演示问题的项目

https://github.com/leonaugust/hibernate-problem

代码:

@SpringBootApplication
@Controller
@EnableJpaRepositories
public class HibernateProblemApplication {

  @Autowired
  private ProductRepository repository;

  public static void main(String[] args) {
    SpringApplication.run(HibernateProblemApplication.class, args);
  }

  @GetMapping("/")
  public String getAll(Model model) {
    model.addAttribute("products", repository.findAll());
    return "products";
  }

  @Bean
  public CommandLineRunner uploadImages(ProductRepository repository,
      ProductImageStore store) {
    return (args) -> {
      Product chicken = new Product("Chicken");
      store.setContent(chicken, this.getClass().getResourceAsStream("/img/chicken.jpg"));
      repository.save(chicken);

      Product goose = new Product("Goose");
      store.setContent(goose, this.getClass().getResourceAsStream("/img/goose.jpg"));
      repository.save(goose);
    };
  }

}


@StoreRestResource(path = "data")
@Repository
public interface ProductImageStore extends ContentStore<Product, String> {
}


@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

}


@Entity
public class Product {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String name;

  @ContentId
  private String contentId;

  @ContentLength
  private Long contentLength = 0L;

  @MimeType
  private String mimeType = "text/plain";

  public Product(String name) {
    this.name = name;
  }

}

@leonaugust 感谢您提醒我注意此事。事实证明,我们的休息控制器不是很聪明,并且执行了比需要更多的查询。 Fixed 在 1.2.1 版本中。