当前位置: 首页 > 知识库问答 >
问题:

返回null的JPA查询-包含null列的复合键

冯流觞
2023-03-14

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

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

在遗留数据中有相同CODE的记录,这些记录可以具有SITE的特定值,也可以在表示'All Sites'的SITE列中具有NULL的记录。该文件的理论是,如果您找不到特定的SITE的CODE,那么您可以在SITE中使用NULL查找记录(the'catk-all')。

我不能改变这个“表”的结构,因为它将涉及重写遗留Cobol系统的大部分内容,这是我们不想做的。我也不能创建数据的视图。

现在,当我使用包含特定codesite的null的主复合键类执行em.find时,Hibernate会正确地找到列中具有null值的匹配记录-一切正常!

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

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

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

如果我使用Hibernate用于此查询的SQL,那么“数据库”将返回两条记录,一条为空站点,另一条为特定站点。当Hibernate从这些结果加载实体时,它似乎正在将其映射到一个空实体对象。

所以Hibernate要么支持,要么不支持。为什么em.find能工作,而em.createQuery却不能工作?

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

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

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

然而,它的行为仍然不同。search返回一个Entity,其中site字段包含null,但是查询返回一个Entity,其中site字段包含"NaN"(null的默认表示形式)。

我仍然觉得它们的行为应该是一样的。

更新2:你们中的一些人想知道有关“数据库”的细节。

它是Trifox Inc.编写的Genesis RDBMS引擎。。数据存储在AcuCobol(现在的Micro Focus)视觉索引文件中。

我们将配置设置为将空白(空格)字母数字字段转换为NULL,因此包含PK字段空格的文件记录将被转换为NULL。我可以通过使用选择适当的记录,其中site_id为NULL,因此RDBMS将这些空白字段视为SQL NULL。

说了这么多,我不相信这个问题与“数据库”有任何关系,除了PK字段为空是不寻常的事实。

此外,如果我记录Hibernate用于查找和查询的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

并专门搜索空值:

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

共有1个答案

长孙骏
2023-03-14
匿名用户

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

TL;博士,这种期望/感觉是没有道理的。链接中不支持的功能(

下面是Hibernate团队回答的(n个旧)支持线程:

文章主题:复合键与空值为一列
发布时间:周一七月03, 2006 2:21

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

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

主键不能为null(完全或部分)

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

很抱歉让您失望,但主键中不支持null-主要是因为进行连接和比较需要大量其他地方不需要的愚蠢代码。。。。。仔细想想,您会发现(例如,如何使用这样的表进行正确的连接)

这并不奇怪,因为SQL中PK列中不允许NULL。主键声明是UNIQUE NOT NULL的同义词。NULL不等于任何(误导的)意图,即某些未记录的值不等于。(您对PK中至少某些情况下NULL等于条件中NULL的期望与SQL相反。)鉴于PK值中不允许NULL,我们可以期望与1:1映射和集合(而不是一袋行)相关的PK优化在方便的时候假设没有NULL。可以预料,Hibernate决定不担心他们的实现对SQL中不应该出现的情况所做的事情。可惜他们在编译或执行时没有告诉你。希望它在文档中。)

即使与createQuery不同的searchre NULL也不足为奇。前者涉及一个值,而后者涉及没有NULL(但没有)的行的集合(而不是包)。

解决方法可能是不将主键的任何列视为NULL,而是将其视为存储中的实际空格字符串。(考虑到您的存储/DBMS/hibernate/JPA/Java堆栈,不管这意味着什么。您还没有向我们提供足够的信息来了解您的数据库Cobol视图是否会因未将JPA的空格映射为NULL而受到阻碍)。使用数据,您仍然可以在列上声明唯一索引。

 类似资料:
  • 将从非null元素返回最小值。 我想编写一个查询,将NULL视为可能的最小值。 我见过使用特殊值的日期技巧,如下所示:https://stackoverflow.com/a/32240382/7810882 但是,如果列的类型是并且没有可以映射到的特殊值怎么办?

  • 我正在使用JDBC创建一个数据库,其中包含表和。两者都有一个名为 以下是我创建和填充表的SQL语句: 我试图运行以下查询: 或 或 使用 但是我没有得到任何结果。 这两个问题都可以解决。 SQLite数据库服务器显示相同的问题: 它与Firefox中的SQLite Manager一起工作。

  • 我有一个带有嵌入Id的类。当我尝试使用Jpa存储库进行搜索时,它只返回一个空对象。问题似乎出在嵌入式Id中,因为我用一个没有这个Id的类进行了测试,结果很好。 当我针对数据库进行测试时,JPA在控制台中输出的查询工作正常。 并且没有输出错误。 编辑:数据库中有数据 EDIT2:添加了equals和hashcode。 编辑3:findAll方法有效。 实体 嵌入ID 存储库 服务 正如你所看到的,我

  • Firebase查询返回此查询的值 该项由model类捕获 但是,返回null

  • 我有以下数据在我的表"设备" 我执行了下面的查询 它返回下面给出的结果 如何解决这个问题,让它忽略NULL,结果应该是

  • 问题内容: 我的查询如下所示: 到目前为止,一切都很好。即使playerShips为空,我也正在获得Pilot实例。 现在,我只想获取不活动的船只,因此我将查询修改为如下所示: 而且我作为飞行员变得空无一人,所以它显然行不通。 如果有人可以向我解释如何使用适用于子元素的WHERE子句创建JOIN FETCH查询,我将感到非常高兴。提前致谢。 问题答案: 经过大量研究,我决定实现一个自定义存储库,以