我的数据模型中有一个OneToOne关系,Hibernate总是在查询两个实体以生成结果集。
这是数据模型
@Entity
public class C1 {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, targetEntity = C2.class)
private C2 c2;
//... other stuff
}
@Entity
public class C2 extends OtherClassOutOfDomain {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "c2")
private C1 c1;
//... other stuff
}
Hibernate会产生我的模式,作为两个表,C1表具有C2的外键,这对我来说是完美的,因为我会更经常使用C1。
但是
每次我查询C1 Hibernate都会生成1个查询,每行加入两个实体数据,并在第一个结果中为每行的N查询生成n个查询(甚至在我访问结果集之前)
示例
Hibernate (just one):
select
this_.id as id1_2_1_,
this_.c2_id as authDat22_2_1_,
this_.bio as bio2_2_1_,
this_.blocked as blocked3_2_1_,
this_.commentsAmount as comments4_2_1_,
this_.confirmed as confirme5_2_1_,
this_.deleted as deleted6_2_1_,
c22_.id as id1_0_0_,
c22_.adid as adid2_0_0_,
from
c1 this_
inner join
c2 c22_
on this_.authData_id=c22_.id
Hibernate (N times as the size of previous query):
select
this_.id as id1_2_1_,
this_.c2_id as authDat22_2_1_,
this_.bio as bio2_2_1_,
this_.blocked as blocked3_2_1_,
this_.commentsAmount as comments4_2_1_,
this_.confirmed as confirme5_2_1_,
this_.deleted as deleted6_2_1_,
c22_.id as id1_0_0_,
c22_.adid as adid2_0_0_,
from
c1 this_
inner join
c2 c22_
on this_.authData_id=c22_.id
where
this_.authData_id=?
.....repeat
.....repeat
.....repeat
重复查询的结果是在第一个大查询的一行中共同签名的...是否有任何方法可以避免这些不必要的请求?我尝试设置为懒惰,但它不起作用
我正在运行以获得此行为的代码很简单
HibernateUtils.createNewSession().createCriteria(C1.class).list();
在触发嵌套查询之前,我什至没有访问结果
我正在使用Hibernate 5.10 E MySQL 5.7.17
将这两件事留在您的脑海中。
OneToOne的默认提取策略急切。
懒惰只能在关联不可用的情况下进行OneToone关联。
您的问题类似于n 1选择问题
解决n 1选择问题:
hql fetch join
来自 C1 C1 左加入fetch C1.C2
或
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, mappedBy= "c1")
@Fetch(FetchMode.JOIN)
private C2 c2;
和第二类
@OneToOne(fetch = FetchType.LAZY, mappedBy = "c2")
@Fetch(FetchMode.JOIN)
private C1 c1;
我有一个解决方案,但我没有完全理解原因。
随着与JPA Hibernate的OneToOne关系映射将把外键放在具有" targinalentity"属性的实体上(具有属性的实体no intribute值中设置的实体)
在通过其结构中具有外键的实体查询时,将自动查询嵌套实体(我不知道原因)
要解决我以前的相关问题,我只需要将注释更改为
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, mappedBy= "c1")
private C2 c2;
@OneToOne(fetch = FetchType.LAZY, targetEntity = C1.class)
private C1 c1;