我有一个遗留数据库(实际上是Cobol文件),我正在使用Hibernate/JPA的专有JDBC驱动程序访问它。
实体有一个包含2列的复合主键:CODE
和SITE
。
在遗留数据中有相同CODE
的记录,这些记录可以具有SITE
的特定值,也可以在表示'All Sites'的SITE
列中具有NULL的记录。该文件的理论是,如果您找不到特定的SITE的CODE
,那么您可以在SITE
中使用NULL查找记录(the'catk-all')。
我不能改变这个“表”的结构,因为它将涉及重写遗留Cobol系统的大部分内容,这是我们不想做的。我也不能创建数据的视图。
现在,当我使用包含特定code
和site
的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
"所以他们要么支持要么不支持"
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不同的search
re 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查询,我将感到非常高兴。提前致谢。 问题答案: 经过大量研究,我决定实现一个自定义存储库,以