2016-07-11 32 views
0

關係我有以下UML圖一組Java類:類與JPA

enter image description here

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之間存在構成關係,分別爲resolved,分別對Invoice和InvoiceDetail使用@Embedded和@Embeddable註釋。但是,通過建立InvoiceDetail,Class3和Class4之間的關係出現問題。在這些關係中,InvoiceDetail必須註釋爲@Entity。但是,當一個類同時註釋爲@Entity和@Embeddable時,相應的服務器將在部署過程中引發運行時錯誤。 在此基礎上website的信息,我寫了下面可能的解決方案:

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

將這一權利,以解決我的問題呢?

在此先感謝。

回答

1

雖然不知道類是什麼真的很難說,我想你有一個設計問題。 Class1和Class2之間的組合表示任何Class2實例只存在於相應Class1實例的生命週期中。但另一方面,您有Class3實例和Class4實例,它們可以/必須與Class2實例有關係。

我想說的是,從我的角度來看,Class1和Class2之間的關係應該是一個簡單的關聯而不是一個構圖。在此路徑之後,Class2將成爲JPA中的一個實體,然後您應該解決您的問題。

我通常使用@Embeddable來表示其實例從來不存在的類,@Entity對於任何其實例可以存在而沒有其他實例的類。例如,地址可以以任何方式實現,但不在同一個系統上。如果我不想鏈接地址,地址應該是@Embeddable,但如果我想確保同一地址沒有保存在多行中,它必須是@Entity。


[編輯:1和2級後加入已更名爲發票並InvoiceDetails]

具有發票和InvoiceDetails之間的組合物非常有意義。但我仍然認爲您應該避免InvoiceDetails需要雙重人格。我能想到的兩種解決方案(包括重構)的:

  1. 如果你喜歡有InvoiceDetails爲@Embeddable你可以改變Class3的和CLASS4的協會發票代替InvoiceDetails。 InvoiceDetails仍然可以通過Invoice對象遍歷。
  2. 如果您希望保持關聯,您可以將InvoiceDetails聲明爲實體。您仍然可以通過級聯刪除來實現組合(請參閱javax.persistence.CascadeType)。因爲InvoiceDetails似乎已經有它自己的表,所以這可能是更好的選擇。

我檢查了我的JPA應用程序,並沒有發現同一個類是@Entity和@Embeddable。老實說,我懷疑這是可能的,因爲在所有的official javadoc of @Embeddable說:

指定一個類,其實例存儲爲擁有實體的固有部分,並份額身份的實體

由於@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-value「invoice」引用實體字段,而名稱值「invoice_id」引用數據庫表。 刪除InvoiceDetails仍由您的Class3或Class4實例引用的Invoice對象時要小心 - 您必須首先釋放這些引用。

有關JPA參考這些資源的信息:

[/編輯]

+0

我會建議您編輯答案。 – julian

+0

看看並告訴我,如果你錯過了什麼。 – TheGrav

+0

你說得對。我已經檢查過,當一個類與Entity和Embeddable同時註釋時,相應的服務器將在部署期間引發運行時錯誤。 – julian