具有接口和嵌入式的多对多

时间:2015-07-23 09:42:22

标签: java hibernate jpa many-to-many

我想创建一个单向的@ManyToMany 在Account实体和Pushable接口之间。 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;
}

enter image description here

我的映射如下所示:

@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 个答案:

答案 0 :(得分: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"))也是如此 因此,(并忽略了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,是一个超级的包和服务。然后,该类可以成为帐户中“多对多”的便捷目标,再次您需要考虑继承策略。