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似乎有效,但是由于我不会厌烦你,这对我们来说不是一个好选择。谢谢!
答案 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;
请记住,如果您的@Embeddable
类不包含基元(具有默认值),并且使用所有null
s保存对象,则整个结构将保留在数据库为null
,因为没有办法使hibernate在数据库中产生差异,无论你没有对象,或者你有一个空对象。要解决此问题,如果出现这种情况,则必须创建一个虚拟字段(boolean
最好)。
答案 2 :(得分:2)
你对发生的事情是完全正确的。当嵌入类的对象为null时,Hibernate通过使其所有列在数据库中为空来表示它;不幸的是,这意味着Hibernate无法区分null可嵌入对象和具有所有空值的可嵌入对象。
据我所知,如果你不能使字段可以为空(通过使它成为Integer
,正如你所猜测的那样),唯一的办法就是创建一个自定义的Hibernate类型。应该是可行的,但这样做会很痛苦。事实上,它可能比你无法使用整数的原因更糟糕 - 那么究竟是什么原因呢?
答案 3 :(得分:0)
请尽可能使用Wrapper类(Integer,Long,Double ...):特别是如果您必须将一列或2固定到现有表上。自动装箱是您的朋友。