簡體   English   中英

與JPA的類關系

[英]Classes Relationships with JPA

我有一組具有以下UML圖的Java類:

在此處輸入圖片說明

 public class Invoice {
           @Id
          private long id;
...
        }

public class InvoiceDetail {
          @Id
          private long id;
          ...
          private String productName;
          private int quantity;
          private double price;

        }

我的目的是使用JPA批注在它們之間建立不同的關系。 Invoice和InvoiceDetail之間存在組成關系,可以分別使用@Embedded和@Embeddable批注分別解決 Invoice和InvoiceDetail的組成關系。 但是,通過建立InvoiceDetail,Class3和Class4之間的關系會出現問題。 在這些關系中,InvoiceDetail必須注釋為@Entity。 但是,如果在與@Entity和@Embeddable同時注釋一個類時,則相應的服務器將在部署期間引發運行時錯誤。 根據本網站的信息,我編寫了以下可能的解決方案:

@Entity
public class Invoice {
  @Id
  private long id;
  ...
  @ElementCollection
  @CollectionTable(name="INVOICEDETAIL", joinColumns=@JoinColumn(name="INVOICE_ID"))
  private List<InvoiceDetail> invoiceDetails;
  ...
}

為了解決我的問題,這是正確的嗎?

提前致謝。

盡管很難知道這些類的真正含義,但是我認為您有一個設計問題。 Class1和Class2之間的組合表明,任何Class2實例僅存在於相應Class1實例的生命周期內。 但是另一方面,您具有Class3實例和Class4實例,它們可以/必須與Class2實例具有關系。

我要說的是,從我的角度來看,Class1和Class2之間的關系應該是簡單的關聯,而不是組成。 遵循此路徑,Class2將成為JPA中的一個Entity,那么您應該已解決了問題。

我通常將@Embeddable用於實例自身不存在的類,並將@Entity用於其實例可以不存在其他實例的任何類。 例如,可以以任何一種方式實現地址,但不能在同一系統上實現。 如果我不想鏈接地址,則地址為@Embeddable,但如果我想確保同一地址沒有保存在多行中,則地址必須為@Entity。


[編輯:在第1類和第2類重命名為Invoice和InvoiceDetails之后添加]

在Invoice和InvoiceDetails之間有一個組合很有意義。 但是我仍然認為您應該避免InvoiceDetails具有雙重性格。 我可以想到兩種解決方案(兩種重構):

  1. 如果您希望將InvoiceDetails設置為@Embeddable,則可以將Class3和Class4的關聯更改為Invoice,而不是InvoiceDetails。 InvoiceDetails仍可通過Invoice對象遍歷。
  2. 如果您希望保持原樣的關聯,則可以將InvoiceDetails聲明為實體。 您仍然可以通過級聯刪除來實現合成(請參見javax.persistence.CascadeType)。 看來InvoiceDetails已經擁有了自己的表,所以這可能是更好的選擇。

我檢查了JPA應用程序,未發現@Entity和@Embeddable屬於同一類。 老實說,我懷疑這是否有可能,因為@Embeddable官方javadoc說:

指定一個類,其實例存儲為擁有實體的固有部分並共享該實體的標識

由於@Entity具有自己的身份,因此您將嘗試聲明具有兩個身份的同一對象-這是行不通的。

[/編輯]


[edit2:為解決方案建議2添加代碼]

該代碼應在某些假設下工作(請參見下文)。 這是針對1:n關系的雙向導航的實現。

@Entity
public class Invoice {
  @Id
  private long id;

  @OneToMany(mappedBy="invoice", cascade = CascadeType.ALL)
  private List<InvoiceDetail> details;
}

@Entity
public class InvoiceDetails {
  @Id
  private long id;

  @ManyToOne
  @JoinColumn(name="invoice_id")
  private Invoice invoice;
}

假設:表的命名方式與實體相同,invoice_details表的外鍵列的名稱為“ invoice_id”,兩個表的主鍵列的名稱均為“ id”。 請注意,mappedBy值“發票”是指實體字段,而名稱值“ invoice_id”是指數據庫表。 刪除仍由您的Class3或Class4實例引用其InvoiceDetails的Invoice對象時要小心-您必須首先釋放這些引用。

有關JPA的信息,請參考以下資源:

[/編輯]

暫無
暫無

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

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