`
wangjian5748
  • 浏览: 209699 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

hibernate的Criteria的一个bug

阅读更多

 

这个bug是在使用hibernate annotation过程中发现的,开始以为是hibenrate annotation的bug,后来又使用xml文件来配置,还是存在同样的问题。
问题场景:我需要使用省份与城市,他们的关系是:一个省有个多城市,很简单的OneToMany关系,在改变province中的cities的lazy特性时,遇到问题
由于我采用把所有的资源都是放在一个表中的策略,所有这里有一个基类Resource

基类

@Entity
@Inheritance(strategy 
= InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name 
= "CATEGORY_ID", discriminatorType = DiscriminatorType.STRING)
@Table(name 
= "T_RESOURCE")
public class Resource implements Serializable ...{

    
private String id;

    
private String name;

    
private ResourceCategory resourceCategory;

    @Id
    @GenericGenerator(name 
= "generator", strategy = "uuid")
    @GeneratedValue(generator 
= "generator")
    @Column(name 
= "ID")
    
public String getId() ...{
        
return id;
    }


    @Column(name 
= "NAME")
    
public String getName() ...{
        
return name;
    }


    @ManyToOne(fetch 
= FetchType.LAZY)
    @JoinColumn(name 
= "CATEGORY_ID", updatable = false, insertable = false)
    
public ResourceCategory getResourceCategory() ...{
        
return resourceCategory;
    }


    @Override
    
public boolean equals(final Object other) ...{
        
if (!(other instanceof Resource))
            
return false;
        Resource castOther 
= (Resource) other;
        
return new EqualsBuilder().append(id, castOther.id).isEquals();
    }


    @Override
    
public int hashCode() ...{
        
return new HashCodeBuilder().append(id).toHashCode();
    }

}

Province子类

@Entity
@DiscriminatorValue(
"province")
public class Province extends Resource ...{

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

    @OneToMany(cascade 
= CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "province")
    
public Set<City> getCities() ...{
        
return cities;
    }

}

 子类City

@Entity
@DiscriminatorValue(
"city")
public class City extends Resource ...{
    
private Province province;

    
public City(String name, ResourceCategory resourceCategory) ...{
        
super(name, resourceCategory);
    }


    @ManyToOne
    @JoinColumn(name 
= "PARENT_ID")
    
public Province getProvince() ...{
        
return province;
    }

}

 hibernate.cfg.xml

<!-- 
    <mapping resource="ResourceCategory.hbm.xml" />
    <mapping resource="Resource.hbm.xml" />
-->
<mapping class="ResourceCategory" />
<mapping class="Resource" />

hibernate助手类

public class HibernateUtil ...{

    
private static SessionFactory sessionFactory;

    
static ...{
        
// Configuration configuration = new Configuration();
        AnnotationConfiguration configuration = new AnnotationConfiguration();
        configuration.configure();

        sessionFactory 
= configuration.buildSessionFactory();
    }


    
public static SessionFactory getSessionFactory() ...{
        
return sessionFactory;
    }


    
public Session getSession() ...{
        
return getSessionFactory().openSession();
    }

}

单元测试类

public class HibnerateTest extends TestCase ...{

    
public void testListProvinceByHQL() ...{
        SessionFactory sessionFactory 
= HibernateUtil.getSessionFactory();
        Session session 
= sessionFactory.openSession();
        Transaction ctx 
= session.beginTransaction();

        Query query 
= session.createQuery("from Province");
        List
<Province> provinces = query.list();

        
for (Province province : provinces) ...{
            System.out.println(province.getName());
        }


        ctx.commit();
    }


    
public void testListProvinceByCriteria() ...{
        SessionFactory sessionFactory 
= HibernateUtil.getSessionFactory();
        Session session 
= sessionFactory.openSession();
        Transaction ctx 
= session.beginTransaction();

        Criteria criteria 
= session.createCriteria(Province.class);
        
        List
<Province> provinces = criteria.list();

        
for (Province province : provinces) ...{
            System.out.println(province.getName());
        }


        ctx.commit();
    }

}

分别执行单元测试方法,他们输出的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

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

<hibernate-mapping>
    
<class name="Resource"
        table
="T_RESOURCE">

        
<id name="id" type="string">
            
<column name="ID" />
        
</id>

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

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

        
<many-to-one name="resourceCategory" insert="false"
            update
="false"
            class
="ResourceCategory"
            column
="CATEGORY_ID" />

        
<subclass name="Province"
            discriminator-value
="province"
分享到:
评论

相关推荐

    SpringRestBugtracker:使用Spring,Hibernate,Criteria,Oracle base的Rest服务

    本项目“SpringRestBugtracker”正是以此为基础,结合Spring框架、Hibernate持久化技术和Oracle数据库,构建了一个功能完备的bug追踪系统。本文将深入探讨其核心技术和实现细节。 首先,Spring作为Java企业级应用的...

    HIbernate免注解实现操作数据库 及Hibernate3连接SQL的BUG解决办法

    SessionFactory是线程安全的,整个应用生命周期只需一个实例。 3. **获取Session**: 通过SessionFactory获取`Session`实例,Session是与数据库交互的主要接口。 4. **实体类和数据表的映射**: 在XML映射文件中,...

    hibernate-release-5.2.10

    5.2.10版本是一个稳定版本,提供了一些bug修复和可能的新功能。对于开发者来说,这个版本意味着可以享受到稳定性和兼容性的保障。 在解压"hibernate-release-5.2.10.Final"后,我们可以找到以下关键组件: 1. **源...

    hibernate资料 3.6.6版本

    Hibernate是一个广泛使用的Java对象关系映射(ORM)工具,它允许开发人员用面向对象的方式来处理数据库交互,而无需直接编写SQL语句。在3.6.6这个版本中,可能会包含一些特定的功能、改进和修复的bug。 描述部分...

    Hibernate 中文手册 3.2.pdf

    Hibernate 3.2 版本是Hibernate历史上的一个重要版本,它引入了很多新的特性,例如注解支持,提高了开发的便捷性。注解允许开发者通过在Java类、方法、字段上使用元数据标记,来描述对象的持久化属性,而无需通过XML...

    hibernate5.2.6-compiled

    **hibernate5.2.6-compiled** 这个标题表明我们正在讨论的是Hibernate ORM框架的一个特定版本,即5.2.6的编译版本。Hibernate是一个流行的Java对象关系映射(ORM)工具,它允许开发人员使用面向对象的方式来处理...

    hibernate 4.1.4

    首先,Hibernate 4.1.4是Hibernate框架的一个稳定版本,它包含了众多的性能优化和新特性。此版本的主要改进在于对JPA 2.1规范的支持,这意味着开发者可以利用更多的标准API来处理数据,提高了代码的可移植性。此外,...

    hibernate-release-5.0.6.Final.zip(最新Hibernate架包)

    2. **版本5.0.6.Final**:此版本是Hibernate 5系列的一个最终稳定版,包含了多个bug修复、性能优化以及新功能的添加。在使用时,开发者可以期待更稳定的运行环境和更好的兼容性。 3. **lib目录**:在压缩包中的"lib...

    hibernate4.2.1

    Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者将数据库操作转换为对对象的操作,使得在处理数据库时可以使用面向对象的方式,大大简化了开发工作。 描述中提到"我是用的最新版本的hibernate,...

    hibernate-4.3.9(最新稳定版)(jar)

    Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者使用面向对象的方式来操作数据库,极大地简化了数据访问层的编码工作。此压缩包“hibernate-4.3.9(最新稳定版)(jar)”提供了Hibernate框架的4.3.9...

    hibernate4.2.2最终版jar包

    4. **Primary Key**:每个实体类通常有一个@Id注解的属性,作为主键,对应数据库表的主键字段。 5. **配置文件**:Hibernate的配置文件(hibernate.cfg.xml)定义了数据源、实体类扫描路径、方言、缓存策略等信息。...

    hibernate帮助文档 3.2、3.6、4.1

    Hibernate 3.2是Hibernate系列的一个稳定版本,它引入了一些关键的增强功能。其中,最显著的是对JPA 1.0规范的支持,使开发者能够利用Java持久化API与Hibernate的灵活性相结合。此外,3.2版改进了性能,特别是通过...

    spring4+hibernate4 封装BaseDao增删改查以及分页,,支持jdk1.7,不支持jdk1.8

    本项目结合了Spring 4和Hibernate 4,旨在提供一个基础的数据访问层(DAO)实现,包括基本的CRUD操作(创建、读取、更新、删除)以及分页功能。以下是关于这个项目的详细知识点: 1. **Spring 4**:Spring框架是...

    hibernate-4.3.10

    Hibernate 4.3.10是4.x系列的一个重要版本,它在4.3系列的基础上进行了多方面的改进和优化,包括性能提升、bug修复以及对新特性的支持。这个版本尤其注重稳定性和兼容性,确保开发者可以放心地在项目中使用。 3. *...

    Hibernate 3.6.10 final Release

    Hibernate 是一个流行的开源对象关系映射(ORM)框架,它简化了Java应用程序与数据库之间的交互。在这个3.6.10最终版本中,Hibernate 提供了一个稳定且功能丰富的平台,用于将Java对象模型与关系型数据库的数据进行...

    hibernate新版本

    【hibernate新版本】是Java开发领域中的一个重要更新,主要关注的是ORM(对象关系映射)框架的改进和优化。Hibernate作为一个强大的开源框架,它允许开发者将Java类与数据库表进行映射,从而简化了数据库操作,提升...

    hibernate-release-5.4.15.Final.zip

    在这个`hibernate-release-5.4.15.Final.zip`压缩包中,包含的是Hibernate 5.4.15 Final版本的完整开发库,这个版本发布于2020年4月30日,是你花费一个小时耐心下载的成果。 Hibernate 5.4系列是Hibernate项目的一...

    hibernate框架源码

    Hibernate是一个开源的对象关系映射(ORM)框架,它允许开发者使用Java对象来操作数据库,而无需直接编写SQL语句。这个框架极大地简化了Java应用程序的数据持久化层的开发,通过提供一套规范化的API和元数据配置,...

    hibernate-distribution-3.6.8.Final-dist

    Hibernate,作为一个开源的对象关系映射(ORM)框架,极大地简化了Java应用程序与数据库之间的交互。在Hibernate 3.6.8.Final这个版本中,我们看到了一系列增强的功能和优化,使其成为企业级应用开发的首选工具之一...

    hibernate-release-4.3.5.Final.zip

    "Final"的标签意味着这是该版本线的最后一个发布,通常包含了一系列的bug修复和性能提升,为开发者提供了更加可靠的开发环境。 二、主要特性 1. **JPA 2.1支持**: Hibernate 4.3.5.Final对Java Persistence API...

Global site tag (gtag.js) - Google Analytics