1

I have the following entities:

//The class Entity is a @MappedSuperclass with id, audit fields, equals and so on.
@Entity
public class Foo extends Entity {
    @OneToMany(mappedBy = "foo", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Bar> bars = new HashSet<Bar>; // + getter/setter

    // ... other properties
}

@Entity
public class Bar extends Entity {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "foo_id")
    private Foo foo; // +getter/setter

    @OneToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "baz_id", nullable = false)
    private Baz baz; // + getter/setter

    // ... other properties
}

@Entity
public class Baz extends Entity {
    @OneToOne(mappedBy = "baz", fetch = FetchType.LAZY, optional = false)
    private Bar bar; // + getter/setter

    // ... other properties
}

Now if I load a Bar with the following, all is well (i.e. only one query is sent to the DB):

SELECT bar FROM Bar bar LEFT JOIN FETCH bar.baz WHERE bar.id = :barId

However, If I do either of the following, a new SELECT is created for every Baz to get the associated Bar object:

SELECT f FROM Foo f LEFT JOIN FETCH f.bars bar LEFT JOIN FETCH bar.baz WHERE f.id = :fooId
SELECT f FROM Foo f LEFT JOIN FETCH f.bars bar LEFT JOIN FETCH bar.baz baz LEFT JOIN FETCH baz.bar WHERE f.id = :fooId

The output is:

10:52:08,622 INFO  [STDOUT] Hibernate: select ... from Foo ...
10:52:08,698 INFO  [STDOUT] Hibernate: select ... from Bar where baz_id=?
10:52:08,711 INFO  [STDOUT] Hibernate: select ... from Bar where baz_id=?
... and so on

Now, I understand from this answer that @OneToOne has problems with lazy loading, so I followed their advice and added optional = false (which didn't seem to do much for me).

I also tried suggestion 3 from this blogpost, but that seems to have no effect at all..

Any suggestions how to eagerly fetch the object graph to avoid the SELECT n+1 issue?

I use EJB 3 (JPA 1) with Hibernate 3.2.4.sp1 on a JBoss 4.2 server.

NOTE: This is somewhat analogous to one of my previous questions. The difference is that here Baz has a reference back to Bar which seems to be the issue.

Community
  • 1
  • 1
Morten Jacobsen
  • 976
  • 1
  • 11
  • 29

1 Answers1

0

I was able to work around the issue, by removing the back reference from Baz to Bar. I did not find the underlying cause, or a way to load the objects eagerly without the extra selects.

Morten Jacobsen
  • 976
  • 1
  • 11
  • 29