JPA:选择实体的子集不会加载@OneToOne 属性
JPA: Selecting subset of entity won't load @OneToOne property
我有一个巨大的实体,我想加载它的子集(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 属性 将为空:
"SELECT new package.GiganticEntity(ge.id, ge.baz) " +
"FROM GiganticEntity ge WHERE ge.id = 1";
我尝试添加显式连接,但结果也为空:
"SELECT new package.GiganticEntity(ge.id, b) FROM GiganticEntity ge " +
"LEFT JOIN ge.baz as b " +
"WHERE ge.id = 1";
如果我只是 select 我这样的巨大实体,那么一切正常(但我正在尝试保存一些连接):
"SELECT GiganticEntity g WHERE g.id = 1";
这可以用 JPA 实现吗?我正在使用 Hibernate 作为它的实现。
编辑:查询实际上需要LEFT JOIN
,所以我需要所有巨大的实体和baz
-es.
为什么这么奇怪的构造?我宁愿
"SELECT GiganticEntity ge LEFT JOIN FETCH ge.baz WHERE g.id = 1 ";
或
"SELECT GiganticEntity ge FETCH ALL PROPERTIES WHERE g.id = 1 ";
由于 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
编辑
根据题目要求修改:
Query actually needs to be LEFT JOIN, so I need all gigantic entites
with baz-es.
您可以将多个实体映射到同一个 table。您将拥有包含所有关联和多个实体视图的 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
如果您不想总是获取 OneToOne
(或 ManyToOne
),您应该明确地将它们声明为惰性的(默认为 eager)。按如下方式更改您的代码:
@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
@OneToOne
关联必须定义为 optional = false
。参见 this question and answer
是的,我知道这听起来很疯狂,但这是告诉 Hibernate 为关联实体创建代理的唯一方法。
我有一个巨大的实体,我想加载它的子集(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 属性 将为空:
"SELECT new package.GiganticEntity(ge.id, ge.baz) " +
"FROM GiganticEntity ge WHERE ge.id = 1";
我尝试添加显式连接,但结果也为空:
"SELECT new package.GiganticEntity(ge.id, b) FROM GiganticEntity ge " +
"LEFT JOIN ge.baz as b " +
"WHERE ge.id = 1";
如果我只是 select 我这样的巨大实体,那么一切正常(但我正在尝试保存一些连接):
"SELECT GiganticEntity g WHERE g.id = 1";
这可以用 JPA 实现吗?我正在使用 Hibernate 作为它的实现。
编辑:查询实际上需要LEFT JOIN
,所以我需要所有巨大的实体和baz
-es.
为什么这么奇怪的构造?我宁愿
"SELECT GiganticEntity ge LEFT JOIN FETCH ge.baz WHERE g.id = 1 ";
或
"SELECT GiganticEntity ge FETCH ALL PROPERTIES WHERE g.id = 1 ";
由于 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
编辑
根据题目要求修改:
Query actually needs to be LEFT JOIN, so I need all gigantic entites with baz-es.
您可以将多个实体映射到同一个 table。您将拥有包含所有关联和多个实体视图的 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
如果您不想总是获取 OneToOne
(或 ManyToOne
),您应该明确地将它们声明为惰性的(默认为 eager)。按如下方式更改您的代码:
@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
@OneToOne
关联必须定义为 optional = false
。参见 this question and answer
是的,我知道这听起来很疯狂,但这是告诉 Hibernate 为关联实体创建代理的唯一方法。