Hello
I'm having trouble using LEFT JOIN in a JPQL with nullable sub-entities. It seems to me that the SQL is created incorrectly by Hibernate.
This JPQL...
select e.id, e.subEntity from TestEntity e left join e.subEntity
...results in this SQL:
select testentity0_.id as col_0_0_, testentity0_.subEntity_id as col_1_0_, testsubent2_.id as id1_ from entities testentity0_ left outer join sub_entities testsubent1_ on testentity0_.subEntity_id=testsubent1_.id inner join sub_entities testsubent2_ on testentity0_.subEntity_id=testsubent2_.id
Because of the extra inner join, entities with sub entity null are not returned.
I'm using Hibernate 3.5.1. With for instance version 3.3.2, it works fine. This is the SQL produced by 3.3.2:
select testentity0_.id as col_0_0_, testentity0_.subEntity_id as col_1_0_, testsubent1_.id as id1_ from entities testentity0_ left outer join sub_entities testsubent1_ on testentity0_.subEntity_id=testsubent1_.id
As you can see, the inner join is not included in this SQL.
Is this a bug, or am I doing something wrong?
Code to reproduce the problem:
Code:
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:test"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
public class TestHibernateJoin {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
EntityManager em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
em.persist(new TestEntity(1, new TestSubEntity(1)));
em.persist(new TestEntity(2, null));
em.persist(new TestEntity(3, new TestSubEntity(2)));
et.commit();
Query query = em.createQuery("select e.id, e.subEntity from TestEntity e left join e.subEntity");
List<String[]> list = query.getResultList();
for (int i = 0; i < list.size(); i++) {
Object[] res = list.get(i);
for (int j = 0; j < res.length; j++) {
System.out.print(res[j] + " ");
}
System.out.println("");
}
em.close();
}
}
@Entity
@Table(name = "entities")
public class TestEntity {
@Id
private final int id;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private final TestSubEntity subEntity;
public TestEntity(int id, TestSubEntity subEntity) {
super();
this.id = id;
this.subEntity = subEntity;
}
public int getId() {
return id;
}
public TestSubEntity getSubEntity() {
return subEntity;
}
}
@Entity
@Table(name = "sub_entities")
public class TestSubEntity {
@Id
private final int id;
public TestSubEntity(int id) {
super();
this.id = id;
}
public int getId() {
return id;
}
}
This is the output of the program:
1 testhibernatejoin.TestSubEntity@3a6e5c
3 testhibernatejoin.TestSubEntity@979f67
As you can see, the entity with subEntity null is not included in the result as I expected it to.