Hibernate不允许带有int字段的嵌入对象为null?

时间:2010-05-15 01:23:28

标签: java hibernate orm jpa

Hibernate不允许我持久化包含带有整数字段的空嵌入对象的对象。例如,如果我有一个名为Thing的类,看起来像这样

@Entity
public class Thing {

    @Id
    public String id;

    public Part part;

}

其中Part是一个可嵌入的类,看起来像这样

@Embeddable
public class Part {

    public String a;    

    public int b;

}

然后尝试使用null Part持久保存Thing对象会导致Hibernate抛出异常。特别是,这段代码

Thing th = new Thing();
th.id = "thing.1";
th.part = null;
session.saveOrUpdate(th);

导致Hibernate抛出此异常

org.hibernate.PropertyValueException: not-null property references a null or transient value: com.ace.moab.api.jobs.Thing.part

我的猜测是发生了这种情况,因为Part是一个嵌入式类,因此Part.a和Part.b只是Thing数据库表中的列。由于Thing.part为null,Hibernate希望将thing.1的行的Part.a和Part.b列值设置为null。但是,Part.b是一个整数,Hibernate不允许数据库中的整数列为null。这是导致异常的原因,对吧?

所以我正在寻找解决此问题的方法。我注意到使Part.b成为一个Integer而不是一个int似乎有效,但是由于我不会厌烦你,这对我们来说不是一个好选择。谢谢!

4 个答案:

答案 0 :(得分:7)

我找到了另一种解决方法,并认为我会分享它。事实证明,如果你使int列可以为空,那么Hibernate不会抛出PropertyValueException。

@Column(nullable = true)
public Integer b;

这对我们有用,因为我们启用hibernate的应用程序是触及数据库的唯一东西,所以我们可以保证只有当part为null时b才为null。虽然null部分建议和Integer包装器类型的使用是很好的建议,但由于很多原因我无法控制,将列设置为nullable对我们来说效果最好。谢谢,我希望这有助于其他人。

答案 1 :(得分:3)

非常不舒服,是的。您可以将默认值设置为part字段:

private Part part = new Part();

甚至

private Part part = Part.NULL_PART;

(见Null object patern

请记住,如果您的@Embeddable类不包含基元(具有默认值),并且使用所有null s保存对象,则整个结构将保留在数据库为null,因为没有办法使hibernate在数据库中产生差异,无论你没有对象,或者你有一个空对象。要解决此问题,如果出现这种情况,则必须创建一个虚拟字段(boolean最好)。

答案 2 :(得分:2)

你对发生的事情是完全正确的。当嵌入类的对象为null时,Hibernate通过使其所有列在数据库中为空来表示它;不幸的是,这意味着Hibernate无法区分null可嵌入对象和具有所有空值的可嵌入对象。

据我所知,如果你不能使字段可以为空(通过使它成为Integer,正如你所猜测的那样),唯一的办法就是创建一个自定义的Hibernate类型。应该是可行的,但这样做会很痛苦。事实上,它可能比你无法使用整数的原因更糟糕 - 那么究竟是什么原因呢?

答案 3 :(得分:0)

请尽可能使用Wrapper类(Integer,Long,Double ...):特别是如果您必须将一列或2固定到现有表上。自动装箱是您的朋友。