Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA: Selecting subset of entity won't load @OneToOne property

I have a gigantic entity and I'd like to load its subset (ID and baz property):

@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;
    }
}

I tried using following JPA query, but baz property will be null:

"SELECT new package.GiganticEntity(ge.id, ge.baz) " +
"FROM GiganticEntity ge WHERE ge.id = 1";

I tried adding an explicit join, but it resulted in null as well:

"SELECT new package.GiganticEntity(ge.id, b) FROM GiganticEntity ge " +
    "LEFT JOIN ge.baz as b " +
    "WHERE ge.id = 1";

If I only select my gigantic entity like this then everything works (but I am trying to save some joins):

"SELECT GiganticEntity g WHERE g.id = 1";

Is this achievable with JPA? I am using Hibernate as its implementation.

EDIT: Query actually needs to be LEFT JOIN, so I need all gigantic entites with baz-es.

like image 399
Xorty Avatar asked Nov 01 '22 06:11

Xorty


1 Answers

Since GiganticEntity has an inverse one-to-one association to a Baz:

@OneToOne(mappedBy = "giganticEntity")
Baz baz;

It means that Baz has also an association to GiganticEntity:

@OneToOne
GiganticEntity giganticEntity;

The query can therefore become:

select new package.GiganticEntity(g.id, b)  
from Baz b
join b.giganticEntity g
where g.id : id

Edit

According to the question requirements changes:

Query actually needs to be LEFT JOIN, so I need all gigantic entites with baz-es.

You can map multiple entities to the same table. You will have the GiganticEntity containing all associations and several entity views:

@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;
    }
}

The query goes like this:

select g
from GignaticBazViewEntity g
left join fetch g.bar
left join fetch g.baz
where g.id : id

or

select g
from GignaticBazViewEntity g
FETCH ALL PROPERTIES
where g.id : id
like image 159
Vlad Mihalcea Avatar answered Nov 15 '22 05:11

Vlad Mihalcea