我有一个巨大的实体,我想加载它的子集(ID和baz属性):
@Entity
public class GiganticEntity {
@Id Long id;
@OneToOne(mappedBy = "giganticEntity")
Foo foo;
@OneToOne(mappedBy = "giganticEntity")
Bar bar;
@OneToOne(mappedBy = "giganticEntity")
Baz baz;
// default constructor + getters/setters
public GiganticEntity(Long id, Baz baz) {
this.id = id;
this.baz = baz;
}
}
我尝试使用以下JPA查询,但是baz属性将为null:
"SELECT new package.GiganticEntity(ge.id, ge.baz) " +
"FROM GiganticEntity ge WHERE ge.id = 1";
我尝试添加显式连接,但结果也是null:
"SELECT new package.GiganticEntity(ge.id, b) FROM GiganticEntity ge " +
"LEFT JOIN ge.baz as b " +
"WHERE ge.id = 1";
如果我只选择这样一个巨大的实体,那么一切正常(但我试图保存一些连接):
"SELECT GiganticEntity g WHERE g.id = 1";
这可以通过JPA实现吗?我正在使用Hibernate作为它的实现。
编辑:查询实际上需要LEFT JOIN
,因此我需要所有巨大的访问 baz
- es。
答案 0 :(得分:2)
由于GiganticEntity
与Baz
具有反向一对一的关联:
@OneToOne(mappedBy = "giganticEntity")
Baz baz;
这意味着Baz还与GiganticEntity
:
@OneToOne
GiganticEntity giganticEntity;
因此查询可以变为:
select new package.GiganticEntity(g.id, b)
from Baz b
join b.giganticEntity g
where g.id : id
根据问题要求的变化:
查询实际上需要LEFT JOIN,所以我需要所有巨大的参与者 与baz-es。
您可以将多个实体映射到同一个表。您将拥有包含所有关联和多个实体视图的GiganticEntity
:
@Entity
@Table(name="GiganticEntity")
@Immutable
public class GignaticBazViewEntity {
@Id Long id;
@OneToOne(mappedBy = "bar")
Bar bar;
@OneToOne(mappedBy = "baz")
Baz baz;
public GiganticEntity(Long id, Bar bar, Baz baz) {
this.id = id;
this.bar = bar;
this.baz = baz;
}
}
查询如下:
select g
from GignaticBazViewEntity g
left join fetch g.bar
left join fetch g.baz
where g.id : id
或
select g
from GignaticBazViewEntity g
FETCH ALL PROPERTIES
where g.id : id
答案 1 :(得分:0)
为什么这么奇怪的构造?我宁愿
"SELECT GiganticEntity ge LEFT JOIN FETCH ge.baz WHERE g.id = 1 ";
OR
"SELECT GiganticEntity ge FETCH ALL PROPERTIES WHERE g.id = 1 ";
答案 2 :(得分:0)
如果您不想总是获取OneToOne
(或ManyToOne
),则应明确声明它们为惰性(默认为急切)。按如下方式更改您的代码:
@Entity
public class GiganticEntity {
@Id Long id;
@OneToOne(mappedBy = "giganticEntity", fetch = FetchType.LAZY)
Foo foo;
@OneToOne(mappedBy = "giganticEntity", fetch = FetchType.LAZY)
Bar bar;
@OneToOne(mappedBy = "giganticEntity", fetch = FetchType.LAZY)
Baz baz;
// default constructor + getters/setters
}
然后编写您的查询以获取您想要的内容:
SELECT GiganticEntity g LEFT JOIN FETCH g.baz WHERE g.id = 1
答案 3 :(得分:0)
@OneToOne
关联必须定义为optional = false
。见this question and answer
是的,我知道这听起来很疯狂,但它是告诉Hibernate为相关实体创建代理的唯一方法。