简体   繁体   English

与JPA的类关系

[英]Classes Relationships with JPA

I have a set of Java classes with the following UML diagram: 我有一组具有以下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;

        }

My purpose is using JPA annotations to establish the different relationships between them. 我的目的是使用JPA批注在它们之间建立不同的关系。 There is a composition relationship between Invoice and InvoiceDetail, which is resolved using @Embedded and @Embeddable annotations for Invoice and InvoiceDetail respectively. Invoice和InvoiceDetail之间存在组成关系,可以分别使用@Embedded和@Embeddable批注分别解决 Invoice和InvoiceDetail的组成关系。 However, a problem appears by establishing the relationships between InvoiceDetail, Class3 and Class4. 但是,通过建立InvoiceDetail,Class3和Class4之间的关系会出现问题。 In these relationships InvoiceDetail must be annotated as @Entity. 在这些关系中,InvoiceDetail必须注释为@Entity。 However, when a class is annotated at the same time as @Entity and @Embeddable, the corresponding server will throw a runtime error during the deployment. 但是,如果在与@Entity和@Embeddable同时注释一个类时,则相应的服务器将在部署期间引发运行时错误。 Basing on the information of this website , I have written the following possible solution: 根据本网站的信息,我编写了以下可能的解决方案:

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

Would be this right in order to resolve my problem? 为了解决我的问题,这是正确的吗?

Thanks in advance. 提前致谢。

Although without knowing what the classes really are it is hard to tell, I suppose that you have a design problem. 尽管很难知道这些类的真正含义,但是我认为您有一个设计问题。 The composition between Class1 and Class2 says that any Class2 instance only exists within the lifecycle of a corresponding Class1 instance. Class1和Class2之间的组合表明,任何Class2实例仅存在于相应Class1实例的生命周期内。 But on the other hand you have Class3 instances and Class4 instances which can / must have a relationship to a Class2 instance. 但是另一方面,您具有Class3实例和Class4实例,它们可以/必须与Class2实例具有关系。

What I'm trying to say is that from my point of view the relationship between Class1 and Class2 should be a simple association and not a composition. 我要说的是,从我的角度来看,Class1和Class2之间的关系应该是简单的关联,而不是组成。 Following this path Class2 would be an Entity in JPA and then you should have your problem solved. 遵循此路径,Class2将成为JPA中的一个Entity,那么您应该已解决了问题。

I usually use @Embeddable for classes whose instances never exist by themselfes and @Entity for any class whose instances can exist without other instances. 我通常将@Embeddable用于实例自身不存在的类,并将@Entity用于其实例可以不存在其他实例的任何类。 An address for example could be implemented either way but not on the same system. 例如,可以以任何一种方式实现地址,但不能在同一系统上实现。 Address would be @Embeddable if I don't want to link addresses but it had to be @Entity if I want to make sure the same address isn't saved in more than one row. 如果我不想链接地址,则地址为@Embeddable,但如果我想确保同一地址没有保存在多行中,则地址必须为@Entity。


[edit: added after classes 1 and 2 were renamed to Invoice and InvoiceDetails] [编辑:在第1类和第2类重命名为Invoice和InvoiceDetails之后添加]

Having a composition between Invoice and InvoiceDetails makes perfect sense. 在Invoice和InvoiceDetails之间有一个组合很有意义。 But I still think you should avoid the need of double personality for InvoiceDetails. 但是我仍然认为您应该避免InvoiceDetails具有双重性格。 I can think of two solutions (both refactorings): 我可以想到两种解决方案(两种重构):

  1. If you prefer having InvoiceDetails as @Embeddable you could change the associations of Class3 and Class4 to Invoice instead of InvoiceDetails. 如果您希望将InvoiceDetails设置为@Embeddable,则可以将Class3和Class4的关联更改为Invoice,而不是InvoiceDetails。 InvoiceDetails would still be traversable via the Invoice object. InvoiceDetails仍可通过Invoice对象遍历。
  2. If you prefer keeping the associations as is you could declare InvoiceDetails to be an entity. 如果您希望保持原样的关联,则可以将InvoiceDetails声明为实体。 You could still achieve your composition with a cascading delete (see javax.persistence.CascadeType). 您仍然可以通过级联删除来实现合成(请参见javax.persistence.CascadeType)。 As it seems that InvoiceDetails already has it's own table, this probably is the better option. 看来InvoiceDetails已经拥有了自己的表,所以这可能是更好的选择。

I checked my JPA applications and haven't found any occurence of the same class being @Entity and @Embeddable. 我检查了JPA应用程序,未发现@Entity和@Embeddable属于同一类。 Honestly, I doubt if this is possible at all because the official javadoc of @Embeddable says: 老实说,我怀疑这是否有可能,因为@Embeddable官方javadoc说:

Specifies a class whose instances are stored as an intrinsic part of an owning entity and share the identity of the entity. 指定一个类,其实例存储为拥有实体的固有部分并共享该实体的标识

As @Entity has it's own identity, you would try to declare the same object having two identities - and this can't work. 由于@Entity具有自己的身份,因此您将尝试声明具有两个身份的同一对象-这是行不通的。

[/edit] [/编辑]


[edit2: adding code for solution proposal #2] [edit2:为解决方案建议2添加代码]

This code should work with some assumptions (see below). 该代码应在某些假设下工作(请参见下文)。 This is the implementation of bi-directional navigation for a 1:n-relationship. 这是针对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;
}

Assumptions: Tables are named like the entities, the foreign key column for invoice_details table is named "invoice_id" and both tables have a primary key column named "id". 假设:表的命名方式与实体相同,invoice_details表的外键列的名称为“ invoice_id”,两个表的主键列的名称均为“ id”。 Note that the mappedBy-value "invoice" refers to the entity field while the name-value "invoice_id" refers to the database table. 请注意,mappedBy值“发票”是指实体字段,而名称值“ invoice_id”是指数据库表。 Be cautious when deleting an Invoice object whose InvoiceDetails still are referenced by your Class3 or Class4 instances - you have to release these references first. 删除仍由您的Class3或Class4实例引用其InvoiceDetails的Invoice对象时要小心-您必须首先释放这些引用。

For information about JPA refer to these resources: 有关JPA的信息,请参考以下资源:

[/edit] [/编辑]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM