Hibernate does not use left outer joins on one-to-one when using a named query.
Issue
I have got the following entities:
@Entity
@NamedQueries({@NamedQuery(name="byId", query="select f from FooEntity f where f.id = :id")})
public class FooEntity {
@Id
@GeneratedValue
private Long id;
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
BarEntity bar;
String foo;
...
@Entity
public class BarEntity {
@Id
@GeneratedValue
private Long id;
String bar;
...
But when I load the Foo entity through find or through a named query, I get different queries generated:
public void testFooBar() throws Exception {
FooEntity foo = new FooEntity();
foo.setFoo("foo");
BarEntity bar = new BarEntity();
bar.setBar("bar");
foo.setBar(bar);
log.info("---------- saving foo entity");
delegate.saveObject(foo);
Long id = foo.getId();
assertEquals(id, bar.getId());
log.info("---------- loading foo entity through find");
foo = delegate.loadById1(id);
assertEquals("foo", foo.getFoo());
assertEquals("bar", foo.getBar().getBar());
log.info("---------- loading foo entity through named query");
foo = delegate.loadById2(id);
assertEquals("foo", foo.getFoo());
assertEquals("bar", foo.getBar().getBar());
}
public void saveObject(Object obj) {
getEntityManager().persist(obj);
}
public FooEntity loadById1(long id) {
return getEntityManager().find(FooEntity.class, id);
}
public FooEntity loadById2(long id) {
return (FooEntity) getEntityManager().createNamedQuery("byId").setParameter("id", id).getSingleResult();
}
this test passes, with the following log:
INFO com.xxxx.transaction2.dao.negoce.TrNegoceDAOTest - ---------- saving foo entity
DEBUG org.hibernate.SQL - insert into FooEntity (id, foo) values (null, ?)
DEBUG org.hibernate.SQL - call identity()
DEBUG org.hibernate.SQL - insert into BarEntity (id, bar) values (null, ?)
DEBUG org.hibernate.SQL - call identity()
INFO com.xxxx.transaction2.dao.negoce.TrNegoceDAOTest - ---------- loading foo entity through find
DEBUG org.hibernate.SQL - select fooentity0_.id as id0_1_, fooentity0_.foo as foo0_1_, barentity1_.id as id1_0_, barentity1_.bar as bar1_0_ from FooEntity fooentity0_ left outer join BarEntity barentity1_ on fooentity0_.id=barentity1_.id where fooentity0_.id=?
INFO com.xxxx.transaction2.dao.negoce.TrNegoceDAOTest - ---------- loading foo entity through named query
DEBUG org.hibernate.SQL - select top ? fooentity0_.id as id0_, fooentity0_.foo as foo0_ from FooEntity fooentity0_ where fooentity0_.id=?
DEBUG org.hibernate.SQL - select barentity0_.id as id1_0_, barentity0_.bar as bar1_0_ from BarEntity barentity0_ where barentity0_.id=?
When the find() is used, only one query with a left outer join is generated. However, if I do something similar with a named query, then I get 2 queries. This makes it very inefficient.
What is causing this behaviour? Can we influence the queries being generated when using the named query?
If I change the named query in:
select f from FooEntity f left join f.bar where f.id = :id
Then I still get 2 queries:
DEBUG org.hibernate.SQL - select top ? fooentity0_.id as id0_, fooentity0_.foo as foo0_ from FooEntity fooentity0_ left outer join BarEntity barentity1_ on fooentity0_.id=barentity1_.id where fooentity0_.id=?
DEBUG org.hibernate.SQL - select barentity0_.id as id1_0_, barentity0_.bar as bar1_0_ from BarEntity barentity0_ where barentity0_.id=?
With the first one doing the left outer join, but the second one is generated nonetheless.
Environment
JBoss Enterprise Application Platform 5.1.0
Subscriber exclusive content
A Red Hat subscription provides unlimited access to our knowledgebase, tools, and much more.