Hibernate的saveOrUpdate忽略非空列属性

3
我有一个映射文件,将某个列指定为not-null="true"。这是一个错误,因为Oracle数据库中的表列设置为NULL。但是我们直到现在(创建映射文件一年多之后),才注意到了这一点,因为Hibernate一直在“忽略”它。这可能吗?
为了更清楚地说明。在数据库中:

CREATE TABLE db.my_table
(...)
my_column NUMBER(10,0) NULL, (...)

在映射文件中:

<column name="MY_COLUMN" precision="10" scale="0" not-null="true">

然后在Java代码中:

getHibernateTemplate().saveOrUpdate(myEntity);

getHibernateTemplate().flush();

这段代码在我们的环境中可以工作。一直都是这样。但是一些客户遇到了not-null property references a null or transient value的问题,当我调试代码时,这没有任何意义。据我所知,这段代码根本不应该能运行。
当然,解决客户的问题很简单,我只需更正映射文件,使其正确地表示我的实体即可。但真正的问题是为什么Hibernate没有抱怨呢?
我已经问过一些在Hibernate方面更有经验的工程师,但他们中没有人见过这种情况。
那么,有人能给我一个提示吗?
编辑:只想强调我们的测试环境和客户端的代码完全相同,在两种情况下,myEntity对象的myColumn属性都设置为NULL。因此,令我困惑的是,为什么它在我们的环境中不会产生任何异常。

这是一个bug。我猜每个软件都有一个。 - David Jashi
这肯定是个 bug。但我想知道为什么它只在客户端环境中出现,而不在我们的环境中出现。 - Alvaro Cavalcanti
2个回答

3

这是正确的行为。

not-null 属性有两个含义:

  • 支持模式导出工具
  • 在运行时检查实体(即不检查数据库列设置)

详见:5.1. 映射声明,摘录如下:

映射文档还包含一些额外的可选属性和元素,影响由模式导出工具导出的数据库模式(例如 not-null 属性)。

同时参见 5.1.11. 属性,摘录如下:

not-null(可选):启用生成空值约束的 DDL 列。

因此,如果您的客户运行一些代码,试图:

getHibernateTemplate().saveOrUpdate(myEntity);

myEntity缺少设置为not-null =“true”的某些属性时,抛出运行时异常是正确的。但在您的测试环境中,您很可能总是将该属性设置为非空值some

甚至还有一个优点。数据库和应用程序之间松散耦合。因此,如果需要,在不触及数据库的情况下可以在应用程序端增加更多的约束(例如,您不被允许这样做)


它对DDL产生影响是有道理的,但是另一部分我有点困惑:如果调用 getHibernateTemplate().saveOrUpdate(myEntity);,其中 myEntity 的属性映射到 MY_COLUMN 并具有 null,会导致运行时错误吗? - acdcjunior
如果有一个映射:not-null=true,并且实体具有NULL而不是值...它将导致运行时错误。事实上,在异常中:not-null属性引用了空或瞬态值 - Radim Köhler
1
好的,明白了!也许你应该考虑更改那个“因此,如果您的客户端运行一些代码,尝试:getHibernateTemplate().saveOrUpdate(myEntity);myEntity缺少一些设置为not-null="true"的属性,则是正确的。”这最后一个(粗体)部分让我感到困惑。我期望看到类似“在抛出运行时异常时是正确的”之类的内容。无论如何,回答很好!+1! - acdcjunior
非常感谢您的建议和澄清帮助。我的英语仍然代表了我的捷克思维;) 谢谢。 - Radim Köhler
我明白你的观点@radim-kohler。但是我们的环境和我的客户端都运行着完全相同的代码。当在这里调试时,myEntity具有相同的属性sel为NULL,但它不会产生任何异常。这就是让我感到困惑的地方。我将编辑我的问题以强调这一点。 - Alvaro Cavalcanti
我刚刚又尝试了一下(就像几个小时前做的那样),以确保。它确实会抛出异常(至少在我的情况下,通常应该也是这样)。很难说是什么问题,但您的客户端和我的环境都在正确地执行工作。本地发生了什么,很难说。可能是某些AOP异常过滤器......很抱歉我没有更好的答案 ;( - Radim Köhler

1
我遇到了完全相同的问题:
在我的Hibernate映射文件中,我为特定列设置了not-null="true"
在我的开发机器上,我可以持久化空值而不会有任何异常。在客户机器上,我们总是收到PropertyValueException/DataIntegrityViolationException
这是一种危险的行为。手动和自动测试都不会失败。 解决方法: 在我的开发机器上,我必须将属性hibernate.check_nullability设置为true。只有这样,我才能在我的开发系统上获得异常。 结论 这种奇怪的行为可能来自于将hibernate validator添加到类路径中。这会将check_nullability变为false。 请参见相关问题: 如何启用Spring验证 不知何故,这仅适用于我的开发系统,而不适用于生产环境。这可能源于不同应用服务器中的不同依赖项加载。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接