JPA @OneToOne关系n + 1选择执行

时间:2013-05-29 17:42:49

标签: hibernate jpa playframework

我看了类似的问题,但答案对我没有用..

问题:当我在一个查询中选择多个父实体,这些实体已连接到某些@OneToOne子实体时,查询会为每个子实体执行select语句。没有join fetch,它就会按预期执行。


Suser实体有关系;

@OneToOne(optional = false, fetch = FetchType.LAZY)
@Cascade(value = { CascadeType.PERSIST, CascadeType.DELETE })
public SuserStats stats;

@OneToOne(fetch=FetchType.LAZY)
@Cascade(value = {CascadeType.PERSIST})
public Profile profile;

SuserStats与其所有者的实体关系;

@OneToOne
@JoinColumn
public Suser owner;

Profile与其所有者的实体关系;

@OneToOne(optional = false, mappedBy = "profile")
public Suser user;

当我执行查询时;

select u from Suser u where u.id in 
  (select f.targetUser.id from Friendship f where f.sourceUser = ?)

正如所料,只在单个查询中获取关系的id。没关系。 lazy fetch正在运作..

然而,当我把它改为; (这次我希望他们获取)

select u from Suser u left join fetch u.stats s left join fetch u.profile where u.id in 
  (select f.targetUser.id from Friendship f where f.sourceUser = ?)

正在执行2n + 1个查询..每个查询和统计信息关系。我在这里尝试了许多方法,但他们并没有解决我的问题。我想在定义亲子关系时我错过了一些基本的东西..

提前感谢..

1 个答案:

答案 0 :(得分:2)

我找到了解决方案;

注意: CascadeType修改与问题和解决方案无关。

注2:我将相同的策略应用于Profile实体,因此无需再次编写

SuserStats实体;

@MapsId
@OneToOne
@JoinColumn(name="id")
public Suser owner;

Suser实体;

@OneToOne(mappedBy="owner",optional=false,fetch=FetchType.LAZY,cascade=javax.persistence.CascadeType.PERSIST,javax.persistence.CascadeType.REMOVE})
@PrimaryKeyJoinColumn
public SuserStats stats;

通过这些更改,Stats的主要列成为id的{​​{1}}(作为外键)。所以 默认的懒惰关系和按需加入提取工作正常。