Here are my entity:
@Entity
public class ProductStateEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@OneToOne
@JoinColumn(name = "product_id", nullable = false)
private ProductEntity product;
// other fields
}
@Entity
public class ProductEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
// other fields
}
If I make a request this way:
session.get(ProductStateEntity.class, 10);
SQL is formed this way:
SELECT product_states.id, product_states.product_id, products.id, -- other columns
FROM product_states
INNER JOIN products ON product_states.product_id=products.id
WHERE product_states.id=10
So far, so good, using INNER JOIN
.
If you make a request in this way:
session.createQuery("from ProductStateEntity where id = :id")
.setParameter("id", 10)
.list()
SQL is formed this way:
SELECT product_states.id, product_states.product_id, -- other columns
FROM product_states
WHERE product_states.id=10;
SELECT products.id, -- other columns
FROM products
WHERE products.id=10
In this case, 2 requests are made. First a query is made in product_states, and then in products.
That's not all, now we will make such a request, which receives 4 records of 4 id at once:
session.createQuery("from ProductStateEntity where id in :ids")
.setParameter("ids", Arrays.asList(10, 11, 12, 13))
.list();
SQL is formed this way:
SELECT product_states.id, product_states.product_id, -- other columns
FROM product_states
WHERE product_states.id IN (10, 11, 12, 13);
SELECT products.id, -- other columns
FROM products
WHERE products.id=10;
SELECT products.id, -- other columns
FROM products
WHERE products.id=11;
SELECT products.id, -- other columns
FROM products
WHERE products.id=12;
SELECT products.id, -- other columns
FROM products
WHERE products.id=13;
In this case, 5 requests are made. First, a request is made in the product_states, the id of all products is obtained, and then it is done on 1 request to receive each of 4 products.
Add join fetch
to the previous query:
session.createQuery("from ProductStateEntity p join fetch p.product where p.id in :ids")
.setParameter("ids", Arrays.asList(10, 11, 12, 13))
.list();
SQL is formed this way:
SELECT product_states.id, products.id, product_states.product_id, -- other columns
FROM product_states
INNER JOIN products ON product_states.product_id=products.id
WHERE product_states.id IN (10, 11, 12, 13)
Thus, only 1 request is made with INNER JOIN
, which is what I want to achieve.
And so the questions are:
- Why do you need to specify
join fetch
explicitly increateQuery
? Could this default behavior be made? After all, a single query with join is better than a lot. - Why, without specifying
join fetch
, additional select queries are not combined into one withid in (...)
? Instead, Hibernate makes selects one at a time. Can this be customized?