JPA: selecting a subset of an object does not load @OneToOne property

I have a giant object and I would like to load a subset of it (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 the following JPA query, but the 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 that also resulted in a null value:

"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 giant object like this, then everything works (but I'm trying to keep some connections):

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

      

Is this possible with JPA? I am using Hibernate as my implementation.

EDIT : Actually the request should be LEFT JOIN

, so I need all the giant permissions with baz

-es.

+3


source to share


4 answers


Since it GiganticEntity

has a one-to-one feedback with Baz

:

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

      

This means that Baz also has a relationship with GiganticEntity

:

@OneToOne
GiganticEntity giganticEntity;

      

So the request could be as follows:

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

      

Edit

According to the requirements for the requirements:



Actually the request should be a LEFT JOIN, so I need all the giant base ideas.

You can map multiple objects in one table. You will have GiganticEntity

one 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 request looks 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

      

+2


source


Why such a constructive approach? I would prefer

"SELECT GiganticEntity ge LEFT JOIN FETCH ge.baz WHERE g.id = 1 ";

      



OR

"SELECT GiganticEntity ge FETCH ALL PROPERTIES WHERE g.id = 1 ";

      

0


source


If you don't want to always fetch OneToOne

(or a ManyToOne

), you must explicitly declare them lazy (the default is impatient). Change your code like this:

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

      

Then write your request to get what you want:

SELECT GiganticEntity g LEFT JOIN FETCH g.baz WHERE g.id = 1

      

0


source


The link @OneToOne

should be defined as optional = false

. See this question and answer

Yes, I know it sounds crazy, but this is the only way to tell Hibernate to create a proxy for the associated Entity.

0


source







All Articles