问题描述
我想在Account实体和Pushable接口之间创建一个单向的@ManyToMany。 Pushable只是一个由两个类实现的标记接口:Package和Plan
包是一个简单的实体:
@Entity
public class Package extends BasicEntity{
}
但Plan是放置在Service实体中的嵌入对象:
@Entity
public class Service extends BasicEntity{
@Embedded
Plan plan;
}
BacicEntity为它的孩子提供了ID:
@MappedSuperclass
public abstract class BasicEntity{
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "ID")
protected Long id;
}
我的映射看起来像这样:
@Entity
public class Account extends Basicentity{
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PUSHABLES_ACCOUNTS", joinColumns=@JoinColumn(name="ID"),
inverseJoinColumns=@JoinColumn(name="ID"))
private List<Pushable>pushables = new ArrayList<Pushable>();
}
我主要担心的是:
- 实体和接口之间的映射是否有效? (一般来说)
- 在连接表中有两个ID列会有问题吗? 帐户和服务都从BasicEntity获得@Id
1楼
实体和接口之间的映射是否有效? (一般来说)
JPA规范定义了实体之间的关系。
JPA Spec 2.1声明接口必须“不被指定为实体”。
所以Pushable
不能以任何便携方式成为关系的目标。
此外,您的Plan
对象是一个嵌入式对象,它本身不是一个实体,也不能成为关系的目标。
在连接表中有两个ID列会有问题吗? 帐户和服务都从BasicEntity获得@Id
您设置的@JoinTable存在一个主要问题,无论接口是否为目标。
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PUSHABLES_ACCOUNTS", joinColumns=@JoinColumn(name="ID"),
inverseJoinColumns=@JoinColumn(name="ID"))
在@JoinColumn(name="ID")
,'name'指的是链接表PUSHABLES_ACCOUNTS
列的名称,对于inverseJoinColumns=@JoinColumn(name="ID"))
也是如此inverseJoinColumns=@JoinColumn(name="ID"))
所以,(并忽略了事实上,Pushables不是实体),您的joinColumns和inverseJoinColumns引用PUSHABLES_ACCOUNTS
链接表中的相同列。
您需要将帐户的ID链接到Pushable的ID。
您可能希望连接表看起来如下所示:
PUSHABLES_ACCOUNTS
**Account_ID** **PUSHABLES_ID**
005 017
…. ….
因此,您的连接表将是:
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PUSHABLES_ACCOUNTS",
joinColumns=@JoinColumn(name=" Account_ID ", referencedColumnName=”ID”),
inverseJoinColumns=@JoinColumn(name=" PUSHABLES_ID " , referencedColumnName=”ID”))
我在这里添加了referencedColumnName
,但默认情况下会使用这些值。
这些是源表(joinColumns)和目标表(inverseJoinColumns)的列。
此关系可能是自引用的,也可能是源表=目标表。
选项
因此,当前类图中来自Account的唯一可能关系目标是Package和Service。 因此,您可以从Account定义两个ManyToMany关系 - 一个到Package,一个到Service。 然后从每个服务实体中挖掘出嵌入式计划,并以这种方式构建Pushables列表。
根据您的业务需求,您可以获得相当多的灵活性,当接口,嵌入式,映射超类等非实体看起来需要成为关系的一部分时,考虑将这些实体推广或制作实体也可能有所帮助。
例如,将BasicEntity更改为MappedSuperclass的实体 - 您需要定义继承策略 - 然后您可以在Account和BasicEntity之间建立关系。
另一个选项 - 我还没有尝试过这个 - 是定义和抽象实体类,它扩展了BasicEntity并且是一个超级的包和服务。 然后,该类可以成为帐户中“多对多”的便捷目标,再次您需要考虑继承策略。 。