[英]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):
我可以想到两种解决方案(两种重构):
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.