JPA:选择实体子集不会加载@OneToOne属性

时间:2015-04-17 19:47:45

标签: java hibernate jpa orm hibernate-mapping

我有一个巨大的实体,我想加载它的子集(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。

4 个答案:

答案 0 :(得分:2)

由于GiganticEntityBaz具有反向一对一的关联:

@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为相关实体创建代理的唯一方法。