我正在研究一个Hibernate问题,它涉及在他们自己的类中单独定义的2个独立的Entity bean:
请注意,Store将具有多个StoreServer - 因此使用@OneToMany注释。请参阅以下代码段:
商店:
@Entity
@Table(name="Store")
public class Store implements Serializable {
/**
* Serializable class - generated UID
*/
private static final long serialVersionUID = 5644190852867691168L;
@Id
@Column(name="STORE_NO", nullable=false)
private int storeNumber;
@Column(name="STORE_NAME", nullable=false)
private String storeName;
@Column(name="STORE_PHONE", nullable=false)
private String storePhone;
//other Store fields...
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name="STORE_NO", insertable=false, updatable=false)
private List<StoreServer> storeServers = new ArrayList<StoreServer>();
//getters and setters
StoreServer:
@Entity
@Table(name="Store_Server")
public class StoreServer implements Serializable {
/**
* Serializable class - generated UID
*/
private static final long serialVersionUID = -5410564578856243437L;
@Id
private StoreServerPK storeServerPK;
@Column(name="IP_ADDRESS", nullable=true)
private String ipAddress;
//other StoreServer fields...getters and setters
由于StoreServer具有复合主键,因此这里是StoreServerPK:
@Embeddable
public class StoreServerPK implements Serializable {
/**
* Serializable class - generated UID
*/
private static final long serialVersionUID = -1401889029390423604L;
@Column(name="STORE_NO", nullable=false)
protected int storeNumber;
@Column(name="SERVER_NO", nullable=false)
protected String serverNumber;
//getters and setters
目前,我得到了正确的结果,但性能却令人无法接受。我已经开启登录Hibernate,我可以看到为每个Store Entity运行一个单独的SELECT查询,以获取相关的StoreServer记录。
目前,在日志中,我看到一个SELECT语句来获取Store记录(返回的结果超过200个)。然后为每个商店提供一个新的SELECT语句来获取StoreServer记录。我的问题是......为什么Hibernate没有进行连接(运行一个查询)?
请问如何使用JOIN告诉Hibernate运行单个查询?
谢谢
答案 0 :(得分:1)
它被称为N + 1问题
解决方案实际上取决于您如何进行查询 - 如果您使用的是Criteria API,则应使用Root.fetch方法:
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Store> cq = qb.createQuery(Store.class);
Root<Store> root = cq.from(Store.class);
root.fetch(App_.storeServers, JoinType.LEFT);
cq.select(root);
return em.createQuery(cq).getResultList();
如果您使用的是HQL,则应使用fetch
关键字:
select distinct st from Store st left join fetch st.storeServers
使用内存数据库(如H2和JDBC Sniffer
验证Hibernate在单元测试中生成的查询数量可能是个好主意