当前位置:  开发笔记 > 编程语言 > 正文

JPA Query返回空值 - 具有空列的Composite Key

如何解决《JPAQuery返回空值-具有空列的CompositeKey》经验,为你挑选了1个好方法。

我有一个遗留数据库(实际上是Cobol文件),我使用Hibernate/JPA的专有JDBC驱动程序访问.

实体有一个包含2列的复合主键:CODESITE.

在传统的数据存在针对相同的记录CODE是可以有一个特定的值SITE,或者可以有与空记录SITE柱代表"所有网站".这个文件的理论是,如果你找不到CODE特定的,SITE那么你在SITE('catch-all')中查找带有NULL的记录.

我不能改变这个'表'的结构,因为它将涉及重写我们不想做的传统Cobol系统的大部分.我也无法创建数据视图.

现在,当我em.find使用包含特定code和null 的主复合键类时site,Hibernate正确地在列中找到具有NULL值的匹配记录 - 一切都好!

但是,如果我尝试使用em.createQuery类似于以下内容进行查询:

SELECT x FROM TareWeight x WHERE x.pk.code = 'LC2'

如果有2条记录,它会在结果列表中为SITE列中的NULL返回一个空对象.

如果我使用Hibernate用于此查询的SQL,那么'database'将返回两条记录,一条记录具有NULL站点,另一条记录具有特定站点.似乎当Hibernate从这些结果加载实体时,它将它映射到空Entity对象.

所以要么Hibernate支持它,要么它不支持它.为什么em.find工作而不是em.createQuery

我知道这个问题很相似,但答案似乎表明这是不可能的.但显然Hibernate可以正确地进行查找,那么为什么查询不起作用呢?


编辑:好的,所以我NullableStringType在这个Hibernate JIRA问题上找到了一个类定义,并将它添加到我的项目中.

如果我使用这个类型类在PK @Typesite列上添加一个定义,那么我可以成功地从SELECT查询中获取非空实体,该site字段包含我定义的任何String文本作为其表示null.

但是,它仍然表现不同.所述find返回一个实体与所述site字段包含null,但该查询返回的实体与site包含"南"(的默认表示字段null).

它仍然感觉这些应该表现相同.


更新2:有些人想知道有关"数据库"的具体细节.

它是Genesis RDBMS引擎,由Trifox Inc.编写.数据存储在AcuCobol(现为Micro Focus)Vision索引文件中.

我们将配置集设置为将空白(SPACES)字母数字字段转换为NULL,因此包含PK字段空格的文件记录将被转换为NULL.我可以通过使用专门选择相应的记录WHERE site_id IS NULL,所以RDBMS 治疗这些空白字段作为SQL NULL.

说完所有我不相信这个问题与'数据库'有关,除了PK字段为空是不寻常的事实.

更重要的是,如果我记录Hibernate用于find查询和查询的SQL,它们几乎完全相同.

这是查找的SQL:

select tareweight0_.CODE as CODE274_0_, tareweight0_.SITE as SITE274_0_, 
       tareweight0_.WEIGHT as WEIGHT274_0_ from TARE_WEIGHT tareweight0_ 
       where tareweight0_.CODE=? and tareweight0_.SITE=?

这是查询的SQL:

select tareweight0_.CODE as CODE274_, tareweight0_.SITE as SITE274_, 
       tareweight0_.WEIGHT as WEIGHT274_ from TARE_WEIGHT tareweight0_ 
       where tareweight0_.CODE=? and tareweight0_.SITE=?

如您所见,唯一的区别是列别名.


更新3:这是一些示例数据:

select code, site, weight from tare_weight where code like 'LC%';

 CODE   SITE    WEIGHT
 ------ ------ -------
 LC1               .81
 LC2               .83
 LC2    BEENLH     .81
 LC3              1.07
 LC3    BEENLH    1.05
 LC4              1.05
 LCH1              .91
 LCH2              .93
 LCH2   BEENLH     .91
 LCH6             1.13
 LCH6   BEENLH    1.11

并专门搜索NULL:

select code, site, weight from tare_weight where code like 'LC%' and site IS NULL;

 CODE   SITE    WEIGHT
 ------ ------ -------
 LC1               .81
 LC2               .83
 LC3              1.07
 LC4              1.05
 LCH1              .91
 LCH2              .93
 LCH6             1.13

philipxy.. 8

"所以要么他们支持,要么他们不支持"

TL; DR那种期望/感觉是没有道理的.您链接(以及我的下方)中不受支持的功能正是您的."不支持"意味着如果你这样做,那么Hibernate可以做任何他们想做的事情.你很幸运他们(似乎)回归了合理的价值观.(虽然只是猜测他们是如何行动的.你没有规范.)没有理由期待任何事情,更不用说一致性了.当行为只是一些不受支持的案例产生的结果时,任何"为什么"很可能只是一个关于代码是如何编写其他案例的工件.


这是Hibernate团队回答的(旧的)支持线程:

发布主题:一
列为空值的复合键PostPosted:Mon Jul 03,2006 2:21 am

我有复合主键的表,我为表创建了以下映射.因为只要所有列的组合都是唯一的,就可以为复合键中的任何列插入空值,我在表中有记录V_CHAR2列的空值(它是复合键的一部分).当我对这个实体执行查询时,我得到具有空值V_CHAR2列的记录的空值.我的映射和实现有什么问题..

发布时间:2006年7月11日星期二上午9:09
Hibernate Team

主键不能为空(既不完全也不是部分)

发布时间:2007年1月6日星期六上午5:35
Hibernate Team

抱歉disapoint你,但在主键无效,不支持-主要是因为这样做加盟的和比较需要的,这只是不需要其他任何地方painfullly愚蠢的代码很多.....仔细想想,你会看到(例如,你怎么了用这样的表做正确的连接)

这并不奇怪,因为SQL中的PK列不允许使用NULL.PRIMARY KEY声明是UNIQUE NOT NULL的同义词.NULL不等于具有(误导)意图的任何事物,即未知某些未记录的值是相等的.(你的某种异常的至少一些在PK NULL场合的预期等于在条件NULL是违背SQL)由于NULL不PK值允许,我们可以期待与1 PK优化:1映射和设置而不是行包以假设在方便的时候没有NULL.可以预料的是,Hibernate决定不担心它们的实现对SQL中不应出现的情况的影响.太糟糕了,他们没有告诉你编译或执行.希望它在文档中.)

即使findcreateQueryre NULL 不同也不足为奇.前者涉及一个值,而后者涉及预期不具有NULL(但不是)的行集(不是行包).

解决方法可能是不将主键的任何列视为NULL,而是将其作为存储中的实际空格字符串.(不管这意味着给您的存储/ DBMS /休眠/ JPA/Java堆栈.你没有给我们足够的信息来了解数据库是否你Cobol语言的观点由于没有映射空间为NULL您的JPA受到阻碍).使用您的数据,您仍然可以在列上声明UNIQUE索引.



1> philipxy..:

"所以要么他们支持,要么他们不支持"

TL; DR那种期望/感觉是没有道理的.您链接(以及我的下方)中不受支持的功能正是您的."不支持"意味着如果你这样做,那么Hibernate可以做任何他们想做的事情.你很幸运他们(似乎)回归了合理的价值观.(虽然只是猜测他们是如何行动的.你没有规范.)没有理由期待任何事情,更不用说一致性了.当行为只是一些不受支持的案例产生的结果时,任何"为什么"很可能只是一个关于代码是如何编写其他案例的工件.


这是Hibernate团队回答的(旧的)支持线程:

发布主题:一
列为空值的复合键PostPosted:Mon Jul 03,2006 2:21 am

我有复合主键的表,我为表创建了以下映射.因为只要所有列的组合都是唯一的,就可以为复合键中的任何列插入空值,我在表中有记录V_CHAR2列的空值(它是复合键的一部分).当我对这个实体执行查询时,我得到具有空值V_CHAR2列的记录的空值.我的映射和实现有什么问题..

发布时间:2006年7月11日星期二上午9:09
Hibernate Team

主键不能为空(既不完全也不是部分)

发布时间:2007年1月6日星期六上午5:35
Hibernate Team

抱歉disapoint你,但在主键无效,不支持-主要是因为这样做加盟的和比较需要的,这只是不需要其他任何地方painfullly愚蠢的代码很多.....仔细想想,你会看到(例如,你怎么了用这样的表做正确的连接)

这并不奇怪,因为SQL中的PK列不允许使用NULL.PRIMARY KEY声明是UNIQUE NOT NULL的同义词.NULL不等于具有(误导)意图的任何事物,即未知某些未记录的值是相等的.(你的某种异常的至少一些在PK NULL场合的预期等于在条件NULL是违背SQL)由于NULL不PK值允许,我们可以期待与1 PK优化:1映射和设置而不是行包以假设在方便的时候没有NULL.可以预料的是,Hibernate决定不担心它们的实现对SQL中不应出现的情况的影响.太糟糕了,他们没有告诉你编译或执行.希望它在文档中.)

即使findcreateQueryre NULL 不同也不足为奇.前者涉及一个值,而后者涉及预期不具有NULL(但不是)的行集(不是行包).

解决方法可能是不将主键的任何列视为NULL,而是将其作为存储中的实际空格字符串.(不管这意味着给您的存储/ DBMS /休眠/ JPA/Java堆栈.你没有给我们足够的信息来了解数据库是否你Cobol语言的观点由于没有映射空间为NULL您的JPA受到阻碍).使用您的数据,您仍然可以在列上声明UNIQUE索引.

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有