java - JPA 查询返回空值 - 具有空列的复合键

标签 java sql hibernate jpa composite-primary-key

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

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

在遗留数据中有相同的记录 CODE可以具有 SITE 的特定值, 或者在 SITE 中可能有一条为 NULL 的记录代表“所有站点”的列。这个文件的理论是,如果你找不到CODE为您的特定 SITE然后你在 SITE 中查找带有 NULL 的记录(“包罗万象”)。

我不能改变这个“表”的结构,因为它会涉及重写我们不想做的大部分遗留 Cobol 系统。我也无法创建数据 View 。

现在当我做 em.find主复合键类包含特定的 code site 为空,然后 Hibernate 会正确地找到列中具有 NULL 值的匹配记录 - 一切顺利!

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

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

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

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

因此,Hibernate 要么支持,要么不支持。为什么会出现em.find工作但不是 em.createQuery ?

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

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

如果我添加一个 @Type site上的定义使用此类型类的 PK 列,然后我可以使用 site 从 SELECT 查询中成功获取非空实体。包含我定义为 null 表示的任何字符串文本的字段.

但是,它的行为仍然不同。 find返回一个带有 site 的实体包含 null 的字段,但查询返回一个实体,其中 site包含“NaN”的字段( 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

最佳答案

"So either they support it or they don't"



TL;博士 这种期望/感觉是不合理的。您的链接中不受支持的功能(和我的下面)正是您的。 “不支持”意味着如果你这样做,那么 Hibernate 可以做任何他们想做的事情。你很幸运他们(似乎)返回了合理的值。 (虽然这只是猜测他们的表现。你没有规范。)没有理由期待任何事情,更不用说一致性了。当行为只是一些不受支持的情况出现的结果时,任何“为什么”很可能只是在考虑其他情况下编写代码的方式的产物。

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

帖子主题:一列空值复合键
发布时间:2006 年 7 月 3 日星期一上午 2:21

I have table with composite primary key and I created following mapping for the table.As it is possible to insert a null value for any column in composite key as long as the combination of all columns is Unique, I have record in teh table which has null value for V_CHAR2 column ( which is part of composite key ) . when I execute a query on this entity I get null values for the records which are having null value of V_CHAR2 column. What's wrong in my mapping and implementation..



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

a primary key cannot be null (neither fully or partial)



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

sorry to disapoint you but null in primary key is not supported - primarily because doing join's and comparisons will require alot of painfullly stupid code that is just not needed anywhere else.....think about it and you will see (e.g. how do you do a correct join with such a table)



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

find不同于 createQuery re NULL 并不奇怪。前者涉及一个值,而后者涉及没有 NULL 值(但不是)的行集合(不是包)。

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

关于java - JPA 查询返回空值 - 具有空列的复合键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34079524/

相关文章:

java - 如何在 Blackberry 中创建图像的网格布局

java - 使用JasperReports,Hibernate和Spring时发生奇怪的错误

mysql - 使用sql显示列中每个元素的总和?

java - sqlserver hibernate 日期映射

java - hibernate Tuplizer

java - Jackson 无法序列化 Hibernate 实体

java - com.microsoft.sqlserver.jdbc.SQLServerConnection 和 java.sql.Connection 之间有什么区别

java - 如何在 Apache Flink 循环的每次迭代中写入文件?

mysql - 将变量重置为 0

mysql - 错误代码: 1062 Duplicate entry for key 'PRIMARY'