天天看点

hibernate的Criteria的一个bug

这个bug是在使用hibernate annotation过程中发现的,开始以为是hibenrate annotation的bug,后来又使用xml文件来配置,还是存在同样的问题。

问题场景:我需要使用省份与城市,他们的关系是:一个省有个多城市,很简单的OneToMany关系,在改变province中的cities的lazy特性时,遇到问题

由于我采用把所有的资源都是放在一个表中的策略,所有这里有一个基类Resource

基类

hibernate的Criteria的一个bug

@Entity

hibernate的Criteria的一个bug

@Inheritance(strategy  =  InheritanceType.SINGLE_TABLE)

hibernate的Criteria的一个bug

@DiscriminatorColumn(name  =   " CATEGORY_ID " , discriminatorType  =  DiscriminatorType.STRING)

hibernate的Criteria的一个bug

@Table(name  =   " T_RESOURCE " )

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

public   class  Resource  implements  Serializable  ... {

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    private String id;

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    private String name;

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    private ResourceCategory resourceCategory;

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    @Id

hibernate的Criteria的一个bug

    @GenericGenerator(name = "generator", strategy = "uuid")

hibernate的Criteria的一个bug

    @GeneratedValue(generator = "generator")

hibernate的Criteria的一个bug

    @Column(name = "ID")

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public String getId() ...{

hibernate的Criteria的一个bug

        return id;

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    @Column(name = "NAME")

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public String getName() ...{

hibernate的Criteria的一个bug

        return name;

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    @ManyToOne(fetch = FetchType.LAZY)

hibernate的Criteria的一个bug

    @JoinColumn(name = "CATEGORY_ID", updatable = false, insertable = false)

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public ResourceCategory getResourceCategory() ...{

hibernate的Criteria的一个bug

        return resourceCategory;

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    @Override

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public boolean equals(final Object other) ...{

hibernate的Criteria的一个bug

        if (!(other instanceof Resource))

hibernate的Criteria的一个bug

            return false;

hibernate的Criteria的一个bug

        Resource castOther = (Resource) other;

hibernate的Criteria的一个bug

        return new EqualsBuilder().append(id, castOther.id).isEquals();

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    @Override

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public int hashCode() ...{

hibernate的Criteria的一个bug

        return new HashCodeBuilder().append(id).toHashCode();

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug

}

hibernate的Criteria的一个bug

Province子类

hibernate的Criteria的一个bug

@Entity

hibernate的Criteria的一个bug

@DiscriminatorValue( " province " )

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

public   class  Province  extends  Resource  ... {

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    private Set<City> cities = new HashSet<City>();

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "province")

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public Set<City> getCities() ...{

hibernate的Criteria的一个bug

        return cities;

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug

}

hibernate的Criteria的一个bug

 子类City

hibernate的Criteria的一个bug

@Entity

hibernate的Criteria的一个bug

@DiscriminatorValue( " city " )

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

public   class  City  extends  Resource  ... {

hibernate的Criteria的一个bug

    private Province province;

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public City(String name, ResourceCategory resourceCategory) ...{

hibernate的Criteria的一个bug

        super(name, resourceCategory);

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    @ManyToOne

hibernate的Criteria的一个bug

    @JoinColumn(name = "PARENT_ID")

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public Province getProvince() ...{

hibernate的Criteria的一个bug

        return province;

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug

}

 hibernate.cfg.xml

hibernate的Criteria的一个bug

<!--  

hibernate的Criteria的一个bug

    <mapping resource="ResourceCategory.hbm.xml" />

hibernate的Criteria的一个bug

    <mapping resource="Resource.hbm.xml" />

hibernate的Criteria的一个bug

-->

hibernate的Criteria的一个bug

< mapping  class ="ResourceCategory"   />

hibernate的Criteria的一个bug

< mapping  class ="Resource"   />

hibernate的Criteria的一个bug

hibernate助手类

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

public   class  HibernateUtil  ... {

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    private static SessionFactory sessionFactory;

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    static ...{

hibernate的Criteria的一个bug

        // Configuration configuration = new Configuration();

hibernate的Criteria的一个bug

        AnnotationConfiguration configuration = new AnnotationConfiguration();

hibernate的Criteria的一个bug

        configuration.configure();

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        sessionFactory = configuration.buildSessionFactory();

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public static SessionFactory getSessionFactory() ...{

hibernate的Criteria的一个bug

        return sessionFactory;

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public Session getSession() ...{

hibernate的Criteria的一个bug

        return getSessionFactory().openSession();

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug

}

hibernate的Criteria的一个bug

单元测试类

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

public   class  HibnerateTest  extends  TestCase  ... {

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public void testListProvinceByHQL() ...{

hibernate的Criteria的一个bug

        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

hibernate的Criteria的一个bug

        Session session = sessionFactory.openSession();

hibernate的Criteria的一个bug

        Transaction ctx = session.beginTransaction();

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        Query query = session.createQuery("from Province");

hibernate的Criteria的一个bug

        List<Province> provinces = query.list();

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        for (Province province : provinces) ...{

hibernate的Criteria的一个bug

            System.out.println(province.getName());

hibernate的Criteria的一个bug

        }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        ctx.commit();

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

    public void testListProvinceByCriteria() ...{

hibernate的Criteria的一个bug

        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

hibernate的Criteria的一个bug

        Session session = sessionFactory.openSession();

hibernate的Criteria的一个bug

        Transaction ctx = session.beginTransaction();

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        Criteria criteria = session.createCriteria(Province.class);

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        List<Province> provinces = criteria.list();

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        for (Province province : provinces) ...{

hibernate的Criteria的一个bug

            System.out.println(province.getName());

hibernate的Criteria的一个bug

        }

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

        ctx.commit();

hibernate的Criteria的一个bug

    }

hibernate的Criteria的一个bug

}

hibernate的Criteria的一个bug

分别执行单元测试方法,他们输出的sql语句是一样的,但是输出的结果是不一样的。

select this_.ID as ID1_1_, this_.NAME as NAME1_1_, this_.COMMENTS as COMMENTS1_1_, this_.CATEGORY_ID as CATEGORY2_1_1_, cities2_.PARENT_ID as PARENT5_3_, cities2_.ID as ID3_, cities2_.ID as ID1_0_, cities2_.NAME as NAME1_0_, cities2_.COMMENTS as COMMENTS1_0_, cities2_.CATEGORY_ID as CATEGORY2_1_0_, cities2_.PARENT_ID as PARENT5_1_0_ from T_RESOURCE this_ left outer join T_RESOURCE cities2_ on this_.ID=cities2_.PARENT_ID where this_.CATEGORY_ID='province'

testListProvinceByHQL方式输出的是

上海

上海

上海

上海

江苏

江苏

江苏

江苏

testListProvinceByCriteria方式输出的是

上海

江苏

若把public Set<City> getCities()的映射改为

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "province")

    @Fetch(FetchMode.SELECT)

或者

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "province")

    @LazyCollection(LazyCollectionOption.FALSE)

则两个方法输出sql语句是一样的,且结果也一样

SQL:

select this_.ID as ID1_0_, this_.COMMENTS as COMMENTS1_0_, this_.NAME as NAME1_0_, this_.CATEGORY_ID as CATEGORY1_1_0_ from T_RESOURCE this_ where this_.CATEGORY_ID='province'

select cities0_.PARENT_ID as PARENT5_1_, cities0_.ID as ID1_, cities0_.ID as ID1_0_, cities0_.COMMENTS as COMMENTS1_0_, cities0_.NAME as NAME1_0_, cities0_.CATEGORY_ID as CATEGORY1_1_0_, cities0_.PARENT_ID as PARENT5_1_0_ from T_RESOURCE cities0_ where cities0_.PARENT_ID=?

select cities0_.PARENT_ID as PARENT5_1_, cities0_.ID as ID1_, cities0_.ID as ID1_0_, cities0_.COMMENTS as COMMENTS1_0_, cities0_.NAME as NAME1_0_, cities0_.CATEGORY_ID as CATEGORY1_1_0_, cities0_.PARENT_ID as PARENT5_1_0_ from T_RESOURCE cities0_ where cities0_.PARENT_ID=?

输出:

上海

江苏

从上面的现象可是看出,不论配置文件怎么变化,通过hql语句获得结果一直不变,而Criteria会变化,这就证明了Criteria是有bug的。

据此我得出结论:hibernate的Criteria在把关联的lazy属性设置为"false",且把fetch设置为join时,查找数据就存在bug

后来我使用xml配置文件的方式,也存在同样的问题,也证明了我的这个结论,

Resource.hbm.xml

hibernate的Criteria的一个bug

<? xml version="1.0" ?>

hibernate的Criteria的一个bug

<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

hibernate的Criteria的一个bug

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

< hibernate-mapping >

hibernate的Criteria的一个bug

     < class  name ="Resource"

hibernate的Criteria的一个bug

        table ="T_RESOURCE" >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < id  name ="id"  type ="string" >

hibernate的Criteria的一个bug

             < column  name ="ID"   />

hibernate的Criteria的一个bug

         </ id >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < discriminator  column ="CATEGORY_ID"  type ="string"   />

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < property  name ="name"  type ="string"  column ="NAME"   />

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < many-to-one  name ="resourceCategory"  insert ="false"

hibernate的Criteria的一个bug

            update ="false"

hibernate的Criteria的一个bug

            class ="ResourceCategory"

hibernate的Criteria的一个bug

            column ="CATEGORY_ID"   />

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < subclass  name ="Province"

hibernate的Criteria的一个bug

            discriminator-value ="province" >

hibernate的Criteria的一个bug

             < set  name ="cities"  lazy ="false"  fetch ="join" >

hibernate的Criteria的一个bug

                 < key >

hibernate的Criteria的一个bug

                     < column  name ="PARENT_ID"   />

hibernate的Criteria的一个bug

                 </ key >

hibernate的Criteria的一个bug

                 < one-to-many  class ="City"   />

hibernate的Criteria的一个bug

             </ set >

hibernate的Criteria的一个bug

         </ subclass >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < subclass  name ="City"

hibernate的Criteria的一个bug

            discriminator-value ="city" >

hibernate的Criteria的一个bug

             < many-to-one  name ="province"

hibernate的Criteria的一个bug

                class ="Province"

hibernate的Criteria的一个bug

                column ="PARENT_ID"   />

hibernate的Criteria的一个bug

         </ subclass >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

     </ class >

hibernate的Criteria的一个bug

</ hibernate-mapping >

hibernate的Criteria的一个bug

ResourceCategory.hbm.xml

hibernate的Criteria的一个bug

<? xml version = " 1.0 " ?>

hibernate的Criteria的一个bug

<! DOCTYPE hibernate - mapping PUBLIC  " -//Hibernate/Hibernate Mapping DTD 3.0//EN "

hibernate的Criteria的一个bug

" http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd " >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

< hibernate - mapping >

hibernate的Criteria的一个bug

     < class  name = " ResourceCategory "

hibernate的Criteria的一个bug

        table = " T_RESOURCE_CATEGORY " >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < id name = " id "  type = " string " >

hibernate的Criteria的一个bug

             < column name = " ID "   />

hibernate的Criteria的一个bug

         </ id >

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

         < property name = " name "  type = " string "  column = " NAME "   />

hibernate的Criteria的一个bug
hibernate的Criteria的一个bug

     </ class >

hibernate的Criteria的一个bug

</ hibernate - mapping >

hibernate的Criteria的一个bug