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=?
如何优化这个过程并执行更少的查询?
演示问题的项目
代码:
@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 版本中。
我有一个产品页面。每个列出的产品都有自己的图像。
要在视图中显示它,我使用此行 <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=?
如何优化这个过程并执行更少的查询? 演示问题的项目
代码:
@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 版本中。