maa*_*nus 9 java performance hibernate join hibernate-criteria
我仍在使用旧的org.hibernate.Criteria,并且对获取模式越来越困惑。在各种查询中,我需要以下所有变体,因此我无法通过注释来控制它。我只是将所有内容都切换到@ManyToOne(fetch=FetchType.LAZY),否则,查询中的任何内容都没有更改。
到目前为止我能找到的要么涉及 HQL 或 JPA2,要么只提供两种选择,但对于旧标准和(至少)以下三种情况,我需要它:
SELECT * FROM item JOIN order on item.order_id = order.idWHERE ...;SELECT item.* FROM item JOIN order on item.order_id = order.idWHERE ...; SELECT order.* FROM order WHERE ...;SELECT item.* FROM item JOIN order on item.order_id = order.idWHERE ...ORDER BY order.name, item.name;看起来没有明确指定fetch=FetchType.LAZY,一切都会像第一种情况一样急切地获取,这有时太糟糕了。我想,使用Criteria#setFetchMode,我可以获得第三种情况。我还没有尝试过,因为我仍然错过了第二个案例。我知道,它在某种程度上可能,还有的@BatchSize标注。
看起来使用createAlias()线索急切地获取所有东西。有一些重载允许指定JoinType,但我需要指定获取类型。现在,我更加困惑了。
是的,您可以使用 FetchType.LAZY、BatchSize、不同的获取模式和投影来满足所有三种情况(请注意,我刚刚编写了一个“where”子句Restrictions.like("name", "%s%")以确保检索到许多行):
执行 JOIN,然后从两个表中获取数据。
由于项目的顺序是 FetchType.LAZY,因此默认的获取模式将为“SELECT”,因此只需将其设置为“JOIN”即可从连接而不是单独的查询中获取相关实体数据:
Session session = entityManager.unwrap(org.hibernate.Session.class);
Criteria cr = session.createCriteria(Item.class);
cr.add(Restrictions.like("name", "%s%"));
cr.setFetchMode("order", FetchMode.JOIN);
List results = cr.list();
results.forEach(r -> System.out.println(((Item)r).getOrder().getName()));
Run Code Online (Sandbox Code Playgroud)
生成的单个 SQL 查询:
select
this_.id as id1_0_1_,
this_.name as name2_0_1_,
this_.order_id as order_id3_0_1_,
order2_.id as id1_1_0_,
order2_.name as name2_1_0_
from
item_table this_
left outer join
order_table order2_
on this_.order_id=order2_.id
where
this_.name like ?
Run Code Online (Sandbox Code Playgroud)
执行 JOIN,从第一个表中获取数据,并与另一个表分开获取。
将获取模式保留为默认的“SELECT”,为订单创建别名以在排序中使用其列,并使用投影来选择所需的列子集(包括外键):
Session session = entityManager.unwrap(org.hibernate.Session.class);
Criteria cr = session.createCriteria(Item.class);
cr.add(Restrictions.like("name", "%s%"));
cr.createAlias("order", "o");
cr.addOrder(org.hibernate.criterion.Order.asc("o.id"));
cr.setProjection(Projections.projectionList()
.add(Projections.property("id"), "id")
.add(Projections.property("name"), "name")
.add(Projections.property("order"), "order"))
.setResultTransformer(org.hibernate.transform.Transformers.aliasToBean(Item.class));
List results = cr.list();
results.forEach(r -> System.out.println(((Item)r).getOrder().getName()));
Run Code Online (Sandbox Code Playgroud)
第一个 SQL 查询结果:
select
this_.id as y0_,
this_.name as y1_,
this_.order_id as y2_
from
item_table this_
inner join
order_table o1_
on this_.order_id=o1_.id
where
this_.name like ?
order by
o1_.id asc
Run Code Online (Sandbox Code Playgroud)
@BatchSize(value=5)以及后续批次(注意我在 Order 类上使用):
select
order0_.id as id1_1_0_,
order0_.name as name2_1_0_
from
order_table order0_
where
order0_.id in (
?, ?, ?, ?, ?
)
Run Code Online (Sandbox Code Playgroud)
执行 JOIN,但不获取连接的表。
与前面的情况相同,但不执行任何操作来提示加载延迟加载的订单:
Session session = entityManager.unwrap(org.hibernate.Session.class);
Criteria cr = session.createCriteria(Item.class);
cr.add(Restrictions.like("name", "%s%"));
cr.createAlias("order", "o");
cr.addOrder(Order.asc("o.id"));
cr.setProjection(Projections.projectionList()
.add(Projections.property("id"), "id")
.add(Projections.property("name"), "name")
.add(Projections.property("order"), "order"))
.setResultTransformer(org.hibernate.transform.Transformers.aliasToBean(Item.class));
List results = cr.list();
results.forEach(r -> System.out.println(((Item)r).getName()));
Run Code Online (Sandbox Code Playgroud)
生成的单个 SQL 查询:
select
this_.id as y0_,
this_.name as y1_,
this_.order_id as y2_
from
item_table this_
inner join
order_table o1_
on this_.order_id=o1_.id
where
this_.name like ?
order by
o1_.id asc
Run Code Online (Sandbox Code Playgroud)
我的所有案例的实体保持不变:
@Entity
@Table(name = "item_table")
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
private Order order;
// getters and setters omitted
}
@Entity
@Table(name = "order_table")
@BatchSize(size = 5)
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// getters and setters omitted
}
Run Code Online (Sandbox Code Playgroud)