簡體   English   中英

為什么單向@OneToMany 更新不起作用

[英]Why unidirectional @OneToMany update is not working

我對 JPA 和 ORM 概念完全陌生,所以我希望有人能清楚地解釋我的代碼可能存在什么問題。

@Entity
@Table(name = "PERSISTENCE_customer")

public class Customer implements Serializable {
    
     private static final long serialVersionUID = 1005220876458L;
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     private Long id;
     private String firstName;
     private String lastName;
     @OneToMany (cascade = CascadeType.ALL, orphanRemoval = true)
     private List<CustomerOrder> orders;
}
@Entity
@Table(name = "PERSISTENCE_ORDER")
public class CustomerOrder implements Serializable{
    private static final long serialVersionUID = 199102142021L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @NotNull
    String status;
    @NotNull
    @OneToMany (cascade = CascadeType.ALL, orphanRemoval = true)
    private List<LineItem> lineItems = new ArrayList();
    @NotNull
    private String orderNumber;
    ................
    ................
}

@Entity
@Table(name = "PERSISTENCE_LINEITEM")
public class LineItem implements Serializable {
    private static final long serialVersionUID = 1991217202100959L;
     @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @NotNull
    private Integer quantity;
    @NotNull
    private Part part;
}

最初,客戶實體是通過用戶界面創建並成功持久化的。 后來,客戶有訂單,我用 CustomerOrder 更新客戶如下:

private void UpdateCustomer(Customer customer) {
        FacesContext fc = FacesContext.getCurrentInstance();
        List<ShoppingCartItem> shoppingCart = getShoppingCart();
        CustomerOrder order = new CustomerOrder();
        List<CustomerOrder> orders = customer.getOrders();
        order.setLastUpdated(new Date());
        order.setOrderNumber(getInvoiceNumber());
        List<LineItem> lineItems = shoppingCart
                .stream()
                .map(e -> (new LineItem(e.getPart(), e.getQuantity())))
                .collect(Collectors.toList());
        order.setLineItems(lineItems);
        order.setStatus("Pending Shipment");
        order.setTotal(getTotal());
        orders.add(order);
        customer.setOrders(orders);
        try {
            updateOrders(customer, orders);
            fc.addMessage(null,
                    new FacesMessage("Customer order added successfuly"));
        } catch (ListServiceException e) {
            FacesMessage errMsg = new FacesMessage(FacesMessage.SEVERITY_FATAL,
                    "Error while adding customer order: ", e.getMessage());
            fc.addMessage(null, errMsg);
        }
    }
private void updateOrders(Customer cust, List<CustomerOrder> orders) throws ListServiceException {
            
        try { //em is the EntityManager injected as the field member
            if (em != null) {
                if (em.isOpen()) {
                    Customer c = getCustomer(cust.getId());
                    c.setOrders(orders);
                    em.merge(c);
                 } else {
                    logger.severe("Entity manager is closed");
            }
            else {
                logger.severe("Entity manager is NULL");
            }
        } catch (Exception e) {
            throw ThrowListServiceException.wrapException(e);
        }
    }

EntityManage 合並后,我得到以下異常。 我的印象是我不需要自己顯式地保留 LineItem 和 CustomerOrder 實體。 我認為 JPA 將保留 object 圖中的所有實體。 為什么我會收到此異常? (我正在使用帶有 EclipseLink JPA 的 GlassFish 5.1 服務器)

提前致謝。

Internal Exception: java.sql.SQLIntegrityConstraintViolationException: Column 'ORDERS_ID'  cannot accept a NULL value.
Error Code: 30000
Call: INSERT INTO PERSISTENCE_CUSTOMER_PERSISTENCE_ORDER (orders_ID, Customer_ID) VALUES (?, ?)
    bind => [2 parameters bound]
Query: DataModifyQuery(name="orders" sql="INSERT INTO PERSISTENCE_USER_PERSISTENCE_ORDER (orders_ID, User_ID) VALUES (?, ?)")
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:905)
 ...............................
.................................
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'ORDERS_ID'  cannot accept a NULL value.

更新

使用 IDE (Netbeans) 調試器,我逐步完成了代碼,正如我所預測的,在實體合並期間,JPA 不會將屬於 ZA8CFDE6331BD59EB2AC96F89111C6 的新實體添加到上下文中。 例如,在 updateOrders() 方法中,當我嘗試使用新的 CustomerOrder object 的列表更新現有的 Customer object 時,JPA 的列表中的元素還不需要持久化的部分並且它們不需要的部分上下文是要添加。 結果,我不得不修改我的代碼,首先將 List 添加到持久化上下文中,然后將 Customer object 與新持久化的 List 合並。 通過這樣做,我不再得到異常。

順便說一句,目前,所有映射關系都是單向的,因為我沒有看到任何使用雙向映射的理由。 但是,通過使這些映射雙向進行,我會得到什么嗎?

您的 OneToMany 映射缺少連接規范或 mappedBy 值

我注意到了。 首先你應該向數據庫提交新訂單。然后你應該將它與用戶鏈接。我不確定這是否解決了你的問題,但這是一個問題。你能檢查一下嗎?

在我看來,如果您將客戶信息保存在您的 Order 實體中,它可能會解決這個問題。

@ManyToOne ()
    private Customer customer;

在您的客戶實體中,您應該將mappedBy=customer作為訂單字段。

之后,您可以為特定訂單給客戶,而不是為客戶下訂單。 在我看來,它將實現更好的關系映射;

order.setCustomer(customer);

我希望我理解正確,這將解決您的問題。 當您為訂單提供客戶詳細信息時,您不需要為同一客戶提供訂單列表詳細信息。 只有其中一個就足夠了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM