【问题标题】:Cannot set boolean to null无法将布尔值设置为 null
【发布时间】:2012-10-12 08:51:06
【问题描述】:

我有一个带有以下变量的类 Shop

@Column(columnDefinition = "bit")
private boolean atShop;

使用此值,我正在使用 HSQL 从应用程序中检索此信息

from Person person
left join fetch person.shop

当我尝试调用此 HSQL 语句时,我收到以下错误

org.springframework.orm.hibernate3.HibernateSystemException: could not set a field value by reflection setter of com.test.dataobject.Shop.atShop; nested exception is org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.test.dataobject.Shop.atShop

之所以抛出这个,是因为它试图在 HSQL 中将布尔值设置为 null。我可以通过将private boolean atShop; 更改为private Boolean atShop; 来解决此问题,但我想将其保留为boolean,因为我将其作为位保存在我的数据库中

有没有办法在不将boolean 更改为Boolean 的情况下解决这个问题?

编辑:

我知道 boolean 只能是 true/false,并且 Boolean 可以设置为 null,但是有没有办法让 hibernate/spring 将此值设置为 false(我认为它应该自动执行)而不是尝试将其设置为 null 并抛出此异常?

我也尝试添加注释以自动将值设置为 false,但这也不起作用

@Column(nullable = false, columnDefinition = "bit default 0")
private boolean atShop;

【问题讨论】:

  • 是的,我知道 boolean 和 Boolean 之间的区别,我的应用程序抛出了这个异常,因为 spring/hibernate 试图将 atShop 设置为 null 而不是 false,但是我怎样才能让它设置为 false并且不为空?
  • 哎呀,我讨厌人们在没有任何解释的情况下对答案投反对票,只是因为他们不完全是他们想要的。最重要的是像这样的问题,这个问题最初还不够清楚。这让我失去了提供帮助的意愿。
  • @Edwin Dalorzo:但不是我对答案投了反对票,这就是为什么我在我的问题中添加了编辑部分,因为我没有解释我已经理解这些差异是我的错布尔值和布尔值之间
  • 据我所知,数据库中的布尔值将被映射为 1 或 0,因此您不需要 columnDefinition。如果你想确定,你可以像 true 1, false 0 那样在持久化文件中添加映射

标签: java spring hibernate


【解决方案1】:

- boolean 是一个原始类型,只能有 true or false 的值。

- 而Boolean 是一个Wrapper Object,可以被赋予一个null 值。

- 从Java 1.5 提供AutoBoxing,因此您可以使用简单赋值运算符将布尔值转换为布尔值并返回到布尔值 (=),所以您可以在需要布尔值而不是布尔值的地方执行此操作。

【讨论】:

  • AutoBoxing(即布尔值 --> 布尔值)总是可以正常工作。但是你真正应该小心的是AutoUnboxing(即布尔值-->布尔值),因为如果你的布尔包装对象为空,它会抛出 NullPointerException。通常,当您需要以 NPE 安全的方式拆箱包装布尔对象时,使用 BooleanUtils.isTrue() 或 Boolean.TRUE.equals() 之类的东西是个好主意。
  • 感谢您的信息!!
【解决方案2】:

与其摆弄休眠代码,不如将表定义更改为默认空值,将其设置为 false(或 0)。这样,当您从数据库中读取数据时,它将始终具有有效值(因为它是布尔值,所以更有意义)

【讨论】:

  • 我尝试将表中的列更新为默认值 0 (ALTER TABLE Shop ALTER COLUMN atShop bit NOT NULL DEFAULT (0)),但我仍然遇到相同的错误
  • 您可能需要修复当前保存的所有值,它们将为空。您也应该将列设置为 NOT NULL。
  • 我最终完全从表中删除了该列并使用ALTER TABLE Shop ADD atShopbit NOT NULL DEFAULT (0) 将其重新添加,即使所有值都设置为 0 并且一切看起来都正常,但错误仍然出现
  • @HipHipArray 对于现有列,请尝试ALTER TABLE Shop ADD DEFAULT 0 FOR atShop。
【解决方案3】:

null 与false 不同(也与true 不同)。 null 有一个非常具体的含义。这就是为什么 Hibernate 做它所做的事情......因为它确实是唯一有意义的事情,尽管你认为它应该做。

如果您想指示 Hibernate 将这些列中的 null 视为 false,唯一真正的解决方案是开发自定义 Hibernate 类型映射,用于“null 不是真正的 null”的这种特殊处理。您可以通过实现org.hibernate.type.Type 接口或org.hibernate.usertype.UserType 接口来实现。你最好的办法是扩展标准布尔类型映射并编织特殊的空处理。

然而,需要注意的一点是查询,因为在 ANSI SQL 中检查 null 的相等性永远不会有效。它解析为 SQL 调用的UNDEFINED,通常表示FALSE。

【讨论】:

    【解决方案4】:

    boolean 是原始的,它可以是true 或false,默认是false。获取null,其对象类型为Boolean。

    【讨论】:

      【解决方案5】:

      我想我会为此付出 2 美分,因为我遇到了类似的问题,但解决方案不同。

      所以我的问题是它正在从数据库中检索数据并尝试将这些数据保存回来。它为布尔字段检索的数据为空。因此,当它试图将其保存回来时,它抱怨它无法将 null 保存为布尔值。

      解决方法是更新数据库数据,使这些字段都没有空值。

      【讨论】:

        【解决方案6】:

        你知道你可以在它周围放一个try catch,如果它抛出一个异常,意味着它是空的,因此将它设置为false。

        【讨论】:

        • 如果您可以控制完成分配的代码,但在这种情况下,OP 从 Hibernate 获取值,它会为您完成所有分配和映射,因此无需实现他的自己的 Hibernate 类型处理程序,如上面 Steve Ebersole 的回答中所述,这不是一个真正的选择
        猜你喜欢
        • 1970-01-01
        • 2023-03-07
        • 2018-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多