not-null属性引用null或transient值

时间:2011-06-17 17:41:09

标签: hibernate

使用hibernate保存父/子对象时遇到麻烦。任何想法都将受到高度赞赏。

org.hibernate.PropertyValueException: not-null property references a null or transient value: example.forms.InvoiceItem.invoice
    at org.hibernate.engine.Nullability.checkNullability(Nullability.java:100)
        .... (truncated)

hibernate映射:

<hibernate-mapping package="example.forms">
    <class name="Invoice" table="Invoices">
        <id name="id" type="long">
            <generator class="native" />
        </id>
        <property name="invDate" type="timestamp" />
        <property name="customerId" type="int" />
        <set cascade="all" inverse="true" lazy="true" name="items" order-by="id">
            <key column="invoiceId" />
            <one-to-many class="InvoiceItem" />
        </set>
    </class>
    <class name="InvoiceItem" table="InvoiceItems">
        <id column="id" name="itemId" type="long">
            <generator class="native" />
        </id>
        <property name="productId" type="long" />
        <property name="packname" type="string" />
        <property name="quantity" type="int" />
        <property name="price" type="double" />
        <many-to-one class="example.forms.Invoice" column="invoiceId" name="invoice" not-null="true" />
    </class>
</hibernate-mapping>

InvoiceManager.java

class InvoiceManager {

    public Long save(Invoice theInvoice) throws RemoteException {
        Session session = HbmUtils.getSessionFactory().getCurrentSession();
        Transaction tx = null;
        Long id = null;
        try {
            tx = session.beginTransaction();
            session.persist(theInvoice);
            tx.commit();
            id = theInvoice.getId();
        } catch (RuntimeException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
            throw new RemoteException("Invoice could not be saved");
        } finally {
            if (session.isOpen())
                session.close();
        }
        return id;
    }
}

Invoice.java

public class Invoice implements java.io.Serializable {
    private Long id;
    private Date invDate;
    private int customerId;
    private Set<InvoiceItem> items;

    public Long getId() {
        return id;
    }
    public Date getInvDate() {
        return invDate;
    }
    public int getCustomerId() {
        return customerId;
    }
    public Set<InvoiceItem> getItems() {
        return items;
    }
    void setId(Long id) {
        this.id = id;
    }
    void setInvDate(Date invDate) {
        this.invDate = invDate;
    }
    void setCustomerId(int customerId) {
        this.customerId = customerId;
    }
    void setItems(Set<InvoiceItem> items) {
        this.items = items;
    }
}

InvoiceItem.java

public class InvoiceItem implements java.io.Serializable {
    private Long itemId;
    private long productId;
    private String packname;
    private int quantity;
    private double price;
    private Invoice invoice;

    public Long getItemId() {
        return itemId;
    }
    public long getProductId() {
        return productId;
    }
    public String getPackname() {
        return packname;
    }
    public int getQuantity() {
        return quantity;
    }
    public double getPrice() {
        return price;
    }
    public Invoice getInvoice() {
        return invoice;
    }
    void setItemId(Long itemId) {
        this.itemId = itemId;
    }
    void setProductId(long productId) {
        this.productId = productId;
    }
    void setPackname(String packname) {
        this.packname = packname;
    }
    void setQuantity(int quantity) {
        this.quantity = quantity;
    }
    void setPrice(double price) {
        this.price = price;
    }
    void setInvoice(Invoice invoice) {
        this.invoice = invoice;
    }
}

9 个答案:

答案 0 :(得分:72)

对于关注者,此错误消息也可能意味着“您已经引用了尚未保存到数据库的外部对象”(即使它存在,并且非空)。

答案 1 :(得分:37)

由于多对一映射中的InvoiceItem,每个Invoice必须附加not-null="true"

所以基本的想法是你需要在代码中建立明确的关系。有很多方法可以做到这一点。在课堂上,我看到了setItems方法。我没有看到addInvoiceItem方法。设置项目时,需要循环设置并在所有项目上调用item.setInvoice(this)。如果实现addItem方法,则需要执行相同的操作。或者您需要另外设置集合中每个InvoiceItem的发票。

答案 2 :(得分:3)

这可以很简单:

@Column(name = "Some_Column", nullable = false)

但是在持久化的过程中,&#34; Some_Column&#34;的值为null,即使&#34; Some_Column&#34;可能不是任何主键或外键。

答案 3 :(得分:2)

检查hbm文件中主键/对象ID的未保存值。如果您通过hibernate框架创建了自动ID,并且您在某处设置了ID,则会抛出此错误。默认情况下,未保存的值为0,因此如果将ID设置为0,您将看到此错误。

答案 4 :(得分:0)

我得到了同样的错误,但最终解决了它,实际上我没有设置已经保存到另一个实体的Object Entity,因此它为foreeign键获取的Object值为null。

答案 5 :(得分:0)

我通过删除@Basic(optional = false)属性来解决 要么 只需更新布尔值@Basic(optional = true)

答案 6 :(得分:0)

我的情况,我有 _menu 表。 _manu 用于存储仪表板菜单,它有 menu_parent。所以关系是与自身的关系。

假设我们有 _menu:

Id Name             menu_parent
1  User Management  null

因为用户管理的menu_parent为空,所以称为父菜单。让我们制作子菜单:

Id Name             menu_parent
2  User Edit        1
3  User Other       1

用户编辑用户其他菜单管理的子级。 因此,关系是多对一的。

这是我们的旧代码:

@NotFound(action = NotFoundAction.IGNORE)
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "menu_parent", nullable = true)
private Menu menuParent;

你看,它使用了 OneToOne,甚至 nullable = true。 错误:

not-null property references a null or transient value: com.va.core.entity.role.Menu.menuParent; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.va.core.entity.role.Menu.menuParent

我的解决方案只是改变与 ManyToOne 的关系,如下所示:

@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "menu_parent", nullable = true)
private Menu menuParent;

答案 7 :(得分:-1)

cascade = CascadeType.PERSIST

我认为这会有所帮助。

答案 8 :(得分:-8)

将该变量设为瞬态。您的问题将得到解决..

@Column(name="emp_name", nullable=false, length=30)
    private transient String empName;