Let's say you have table T1 and T2 with 1-* relationship. Hence the C1 (class that maps T1) has a collection of T2, named "c2s". If you do
Code:
session.createCriteria(C1.class)
.createCriteria("c2s", Criteria.LEFT_JOIN)
.add(Restrictions.eq("PK", 2L))
then the "c2s" collection always contains only single item - the one with the PK=2, even though there are other ones. If you do INNER_JOIN, the collection is populated correctly.
Here is a test case:
- DB setup
Code:
create table t1 (pk number(15), cid number(15));
create table t2 (pk number(15), cid number(15), FK_T1 number(15));
insert into t1 values (1,1003);
insert into t2 values (1,1002,1);
insert into t2 values (2,1002,1);
insert into t2 values (3,1002,1);
- Hibernate configuration:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<session-factory>
<!-- Hibernate settings -->
<property name="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.pool_size">40</property>
<property name="hibernate.connection.validationQuery">select 1 from dual</property>
<property name="hibernate.connection.validationAttempts">5</property>
<property name="hibernate.connection.validationAttemptTimeout">10</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1522:local11</property>
<property name="hibernate.connection.username">hibernatetest</property>
<property name="hibernate.connection.password">hibernatetest</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.OSCacheProvider</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.format_sql">false</property>
<property name="hibernate.show_sql">false</property>
</session-factory>
</hibernate-configuration>
- C1.hbm.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "hibernate-mapping-3.0.dtd" >
<hibernate-mapping auto-import="false">
<class name="hibernatebug.C1" table="T1" discriminator-value="1003" batch-size="100" lazy="false" >
<cache usage="read-write"/>
<id name="PK" type="long" column="PK"/>
<discriminator column="CID" type="long" insert="true"/>
<bag name="c2s" lazy="extra" inverse="true" table="T2" optimistic-lock="false" >
<cache usage="read-write"/>
<key column="FK_T1" />
<many-to-many class="hibernatebug.C2" column="PK"/>
</bag>
</class>
</hibernate-mapping>
- C2.hbm.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "hibernate-mapping-3.0.dtd" >
<hibernate-mapping auto-import="false">
<class name="hibernatebug.C2" table="T2" discriminator-value="1002" batch-size="100" lazy="false" >
<cache usage="read-write"/>
<id name="PK" type="long" column="PK"/>
<discriminator column="CID" type="long" insert="true"/>
</class>
</hibernate-mapping>
- C1.java
Code:
package hibernatebug;
import java.util.List;
public class C1 {
private Long pk;
private Integer cid;
private List<C2> fieldC2s;
public Long getPK() {
return pk;
}
public void setPK(Long pk) {
this.pk = pk;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public List<C2> getC2s() {
return this.fieldC2s;
}
public void setC2s(List<C2> newC2s) {
this.fieldC2s = newC2s;
}
}
- C2.java
Code:
package hibernatebug;
public class C2 {
private Long pk;
private Integer cid;
public Long getPK() {
return pk;
}
public void setPK(Long pk) {
this.pk = pk;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
}
- and, finally, Test.java
Code:
package hibernatebug;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Restrictions;
public class Test {
public static void main(String[] args) {
Configuration cfg = new Configuration();
cfg.configure(Test.class.getClassLoader().getResource("hibernatebug/cfg.xml"));
cfg.addClass(C1.class);
cfg.addClass(C2.class);
SessionFactory sf = cfg.buildSessionFactory();
Session s = sf.openSession();
C1 list = (C1) s.createCriteria(C1.class)
.createCriteria("c2s", Criteria.LEFT_JOIN)
.add(Restrictions.eq("PK", 2L))
.uniqueResult();
System.out.println("size of 'c2s' collection: " + list.getC2s().size() + " (expected 3)");
}
}
I think it is a bug. Is it?