当前位置: 首页 > news >正文

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 ... {

privateStringid;

privateStringname;

privateResourceCategoryresourceCategory;

@Id
@GenericGenerator(name
="generator",strategy="uuid")
@GeneratedValue(generator
="generator")
@Column(name
="ID")
publicStringgetId()...{
returnid;
}


@Column(name
="NAME")
publicStringgetName()...{
returnname;
}


@ManyToOne(fetch
=FetchType.LAZY)
@JoinColumn(name
="CATEGORY_ID",updatable=false,insertable=false)
publicResourceCategorygetResourceCategory()...{
returnresourceCategory;
}


@Override
publicbooleanequals(finalObjectother)...{
if(!(otherinstanceofResource))
returnfalse;
ResourcecastOther
=(Resource)other;
returnnewEqualsBuilder().append(id,castOther.id).isEquals();
}


@Override
publicinthashCode()...{
returnnewHashCodeBuilder().append(id).toHashCode();
}

}

Province子类

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

privateSet<City>cities=newHashSet<City>();

@OneToMany(cascade
=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="province")
publicSet<City>getCities()...{
returncities;
}

}

子类City

@Entity
@DiscriminatorValue(
" city " )
public class City extends Resource ... {
privateProvinceprovince;

publicCity(Stringname,ResourceCategoryresourceCategory)...{
super(name,resourceCategory);
}


@ManyToOne
@JoinColumn(name
="PARENT_ID")
publicProvincegetProvince()...{
returnprovince;
}

}

hibernate.cfg.xml

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

hibernate助手类

public class HibernateUtil ... {

privatestaticSessionFactorysessionFactory;

static...{
//Configurationconfiguration=newConfiguration();
AnnotationConfigurationconfiguration=newAnnotationConfiguration();
configuration.configure();

sessionFactory
=configuration.buildSessionFactory();
}


publicstaticSessionFactorygetSessionFactory()...{
returnsessionFactory;
}


publicSessiongetSession()...{
returngetSessionFactory().openSession();
}

}

单元测试类

public class HibnerateTest extends TestCase ... {

publicvoidtestListProvinceByHQL()...{
SessionFactorysessionFactory
=HibernateUtil.getSessionFactory();
Sessionsession
=sessionFactory.openSession();
Transactionctx
=session.beginTransaction();

Queryquery
=session.createQuery("fromProvince");
List
<Province>provinces=query.list();

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


ctx.commit();
}


publicvoidtestListProvinceByCriteria()...{
SessionFactorysessionFactory
=HibernateUtil.getSessionFactory();
Sessionsession
=sessionFactory.openSession();
Transactionctx
=session.beginTransaction();

Criteriacriteria
=session.createCriteria(Province.class);

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

for(Provinceprovince: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

<? xmlversion="1.0" ?>
<! DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.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" >
< set name ="cities" lazy ="false" fetch ="join" >
< key >
< column name ="PARENT_ID" />
</ key >
< one-to-many class ="City" />
</ set >
</ subclass >

< subclass name ="City"
discriminator-value
="city" >
< many-to-one name ="province"
class
="Province"
column
="PARENT_ID" />
</ subclass >

</ class >
</ hibernate-mapping >

ResourceCategory.hbm.xml

<? xmlversion = " 1.0 " ?>
<! DOCTYPEhibernate - mappingPUBLIC " -//Hibernate/HibernateMappingDTD3.0//EN "
" http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd " >

< hibernate - mapping >
< class name = " ResourceCategory "
table
= " T_RESOURCE_CATEGORY " >

< idname = " id " type = " string " >
< columnname = " ID " />
</ id >

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

</ class >
</ hibernate - mapping >

相关文章:

  • toad导出mysql数据库_将toad里的数据库结构导出到pdm
  • 炒股精髓:多位高手多年心血结晶
  • 好神奇哟
  • java linux 压缩文件夹_Linux下压缩某个文件夹(文件夹打包)
  • java中mapper层作用_Java的MyBatis框架中Mapper映射配置的使用及原理解析
  • java空接口_java中RandomAccess接口明明是个空接口,有什么用呢?
  • java pdf base64_Javaweb中利用pdf.js显示oracle数据库中Base64编码转为的PDF
  • SQL Server 2005豪华盛宴
  • java班级管理系统代码_基于jsp的班级管理系统-JavaEE实现班级管理系统 - java项目源码...
  • java 聚合服务_远程服务接口聚合带来的性能提升
  • java编写客户_java编写服务器和客户端.docx
  • ORA-03113错误分析
  • 一个带年月日时分秒选择的js脚本
  • java发送苹果消息慢_使用javapns向苹果apns发送消息成功,手机设备有时收不到推送信息...
  • java 1.6 ubuntu_Ubuntu16.04安装java6(jdk 1.6)
  • Asm.js的简单介绍
  • js如何打印object对象
  • js算法-归并排序(merge_sort)
  • SpringBoot 实战 (三) | 配置文件详解
  • SQLServer之创建显式事务
  • Unix命令
  • 诡异!React stopPropagation失灵
  • 汉诺塔算法
  • 机器学习中为什么要做归一化normalization
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 聊聊redis的数据结构的应用
  • 每天一个设计模式之命令模式
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 在Unity中实现一个简单的消息管理器
  • 自定义函数
  • Spring Batch JSON 支持
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • #预处理和函数的对比以及条件编译
  • (C语言)逆序输出字符串
  • (MATLAB)第五章-矩阵运算
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (力扣题库)跳跃游戏II(c++)
  • (十六)Flask之蓝图
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)树状数组
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .net framework4与其client profile版本的区别
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 中 GetProcess 相关方法的性能
  • .net连接MySQL的方法
  • .NET文档生成工具ADB使用图文教程
  • /proc/interrupts 和 /proc/stat 查看中断的情况