I have a products page. Each listed product has its own image.
To display it on view I use this line <img th:src="@{/data/{id}(id=${product.id})}"
When I'm going to the endpoint to see products, Hibernate generates 7 queries instead of 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=?
Probably, the problem is connected to the way how I receive the image on the page.
I assume it happens like that: ProductRepository normally executes 1 query to get list of products.
Then to show image on page Spring executes 3 queries for each product.
Also I noticed that endpoint with image "/data/1"
produces 3 queries.
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=?
How to optimize this process and execute less queries? Project to demonstrate the problem
Code:
@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;
}
}