властивість not-null посилається на нульове або перехідне значення


83

Проблема зі збереженням батьківського / дочірнього об’єкта в режимі глибокого сну. Будь-яка ідея буде високо оцінена.

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-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;
    }
}

Рахунок.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"у багато-до-одного відображення.

Отже, основна ідея полягає в тому, що вам потрібно встановити це явне відношення в коді. Для цього існує багато способів. У вашому класі я бачу setItemsметод. Я НЕ бачу addInvoiceItemметоду. Коли ви встановлюєте елементи, вам потрібно прокрутити комплект і зателефонувати item.setInvoice(this)за всіма елементами. Якщо ви впроваджуєте addItemметод, вам потрібно зробити те саме. Або вам потрібно встановити інший рахунок для кожного InvoiceItemв колекції.


82

для послідовників це повідомлення про помилку може також означати "у вас є посилання на сторонній об'єкт, який ще не був збережений у БД" (хоча він там і не є нульовим).


1
І як я можу це вирішити? Приклад: У мене є Entity_A зі стовпцем Entity_B, а в Entity_B у мене є стовпець Entity_A, відношення має значення @OneToMany від A до B, і коли я намагаюся оновити Entity_A, то даю мені цей виняток, як я можу оновити Entity_A?
Фендрю

1
@FAndrew спочатку зберегти Entity_B?
rogerdpack

3
і якщо у мене є, наприклад, 100 Entity_B, я шукаю всі відредаговані Entity_B, і якщо він був відредагований, я оновлюю його? Чи не було б приємніше, якби я просто оновив Entity_A?
Фендрю

7

Це може бути так просто, як:

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

але при збереженні значення "Some_Column" є нульовим, навіть якщо "Some_Column" може не бути первинним або зовнішнім ключем.


2

Перевірте незбережені значення для вашого первинного ключа / ідентифікатора об’єкта у ваших файлах hbm. Якщо у вас є автоматичне створення ідентифікатора за допомогою режиму глибокого сну, і ви десь встановлюєте ідентифікатор, він викине цю помилку. За замовчуванням незбережене значення дорівнює 0, тому, якщо ви встановите ідентифікатор 0, ви побачите цю помилку.


0

Я отримував ту саму помилку, але врешті вирішив її, насправді я не встановлював об’єкт об’єкта, який вже збережений для іншої сутності, а отже, значення об’єкта, яке воно отримувало для зовнішнього ключа, було нульовим.


0

Я вирішив, видаливши властивість @Basic (необов’язково = false) або просто оновив логічне значення @Basic (необов’язково = true)


-11

Зробіть цю змінну перехідною. Ваша проблема буде вирішена ..

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

3
Ви говорите про вирішення помилки, а не про вирішення проблеми.
Karthik R
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.