hibernate@onetomany导致多个select语句

disho6za  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(258)

我正在研究一个hibernate问题,它涉及两个单独的实体bean,分别在它们自己的类中定义:
商店
存储服务器
请注意,一个存储将有多个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

存储服务器:

@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实体运行一个单独的select查询,以获取相关的storeserver记录。
目前,在日志中,我看到一个select语句来获取存储记录(返回了200多个结果)。然后对于每个存储,使用一个新的select语句来获取storeserver记录。我的问题是…为什么hibernate不执行连接(运行一个查询)?
我能得到一些关于如何告诉hibernate使用join运行单个查询的帮助吗?
谢谢您

gzszwxb4

gzszwxb41#

这就是所谓的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生成的查询数可能是个好主意

相关问题