not-nullプロパティは、nullまたは一時的な値を参照します


83

親/子オブジェクトを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;
    }
}

回答:


49

すべてはInvoiceItem持っている必要がありますInvoiceので、のそれに接続されているnot-null="true"、多対1のマッピング。

したがって、基本的な考え方は、コードでその明示的な関係を設定する必要があるということです。それを行うには多くの方法があります。あなたのクラスにsetItemsメソッドがあります。addInvoiceItemメソッドが表示されません。アイテムを設定するときは、セットをループしてitem.setInvoice(this)すべてのアイテムを呼び出す必要があります。addItemメソッドを実装する場合は、同じことを行う必要があります。またはInvoiceItem、コレクション内のすべての請求書を設定する必要があります。


82

フォロワーの場合、このエラーメッセージは、「まだDBに保存されていない外部オブジェクトを参照している」ことを意味する場合もあります(DBに保存されていて、nullではない場合でも)。


1
そして、どうすればこれを解決できますか?例:Entity_B列を持つEntity_Aがあり、Entity_BにEntity_A列がある場合、関係はAからBへの@OneToManyであり、Entity_Aを更新しようとすると、この例外が発生します。Entity_Aを更新するにはどうすればよいですか?
FAndrew 2016年

1
@FAndrewは最初にEntity_Bを保存しますか?
rogerdpack 2016年

3
たとえば、100個のEntity_Bがある場合、編集されたすべてのEntity_Bを検索し、編集されている場合は更新しますか?Entity_Aを更新するだけでいいのではないでしょうか?
FAndrew 2016年

7

これは次のように簡単です。

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

ただし、「Some_Column」が主キーまたは外部キーでなくても、永続化中は「Some_Column」の値はnullになります。


2

hbmファイルの主キー/オブジェクトIDの未保存の値を確認してください。hibernateフレームワークによる自動ID作成があり、どこかにIDを設定している場合、このエラーがスローされます。デフォルトでは、保存されていない値は0であるため、IDを0に設定すると、このエラーが表示されます。


0

同じエラーが発生しましたが、最終的に解決しました。実際には、すでに他のエンティティに保存されているオブジェクトエンティティを設定していなかったため、外部キーに対して取得したオブジェクト値はnullでした。


0

@Basic(optional = false)プロパティを削除するか、ブール値@Basic(optional = true)を更新することで解決しました


-11

その変数を一時的なものにします。問題は解決されます。

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

3
あなたはエラーを解決することについて言っているのであって、問題を解決しないことについて言っています。
Karthik R 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.