jpa嵌入与实体的双向关系

时间:2014-02-11 04:23:34

标签: java jpa orm jpa-2.0

是否存在可嵌入和实体之间的双向关系或仅存在单向关系?

@Entity
public class Employee {
  @Id
  private long id;
  ...
  @Embedded
  private EmploymentPeriod period;
  ...
}
@Embeddable 
public class EmploymentPeriod {
  @Column(name="START_DATE")
  private java.sql.Date startDate;

  @Column(name="END_DATE")
  private java.sql.Date endDate;

  @OneToMany
  private EntityABCD entityABCD ;
  ....
}
@Entity
public class EntityABCD {
  @Id
  private long id;
  ...
  @ManyToOne(mappedby="entityABCD")
  private EmploymentPeriod period;
  ...
}

根据JPA规范:2.5 Embeddable Classes

 An entity cannot have a unidirectional relationship to the embeddable class of another entity (or itself).

请按照JPA规范的规定澄清上述行。

2 个答案:

答案 0 :(得分:1)

解释起来真的很复杂,但我会试一试。这就是规范所说的

可嵌入类可能包含与实体或实体集合的关系。自实例以来 可嵌入类本身没有持久性标识,与引用实体的关系是 包含可嵌入实例的实体,而不包含嵌入本身。[17]一个 用作嵌入式ID或地图键的嵌入式类不得包含此类关系。

[17]实体不能与另一个实体(或其自身)的可嵌入类具有单向关系。

情景是......

Entity1具有Embeddable属性,Embeddable也有一个指向entity2的属性。

  

请注意,这是一个复杂的嵌入式对象,因为它是“共享的”   两个实体之间。即使规范说嵌入式不应该   共享,它可能只是具有未定义的语义。

规范所讨论的部分是Embeddable中发生的事情,在这种情况下,你可以嵌入一个指向实体的引用。如果你考虑它需要一个双向关系,因为embeddable没有主键,所以它需要某种方式来指向它所指的实体(Foriegn key),例如@OneToOne,因为可嵌入永远不能是它不能创建foriegn密钥的所有者,embeddable引用的实体(Entity2)必须为它分配外键,唯一的方法是在其自身内部标记为@embedded,因此你有双向关系。

下面是一些代码

@Entity
public class Entity1 {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Embedded
    private Embeddable embeddable;

     //getter/setter
}

@Embeddable
public class Embeddable {

    @OneToOne
    private Entity2 entity2;

    public Entity2 getEntity2() {
        return entity2;
    }

    public void setEntity2(Entity2 entity2) {
        this.entity2 = entity2;
    }
}

@Entity
public class Entity2 {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Embedded
    private Embeddable embeddable;

     //getter/setter
}

答案 1 :(得分:1)

当每个实体指向另一个实体时,关系是双向 如果只有一个实体指向另一个实体,则关系是单向

在您的特定情况下,句子:

  

实体不能与该实体具有单向关系   另一个实体(或其自身)的可嵌入类

可以翻译成:

  

EntityABCD 实体不能具有单向关系   另一个员工实体的可嵌入类 EmploymentPeriod

所以换句话说:

  

如果员工实体具有嵌入式 EmploymentPeriod ,则不是   可以从 EntityABCD 定义单向关系   实体嵌入 EmployPeriod 实体员工

为什么?

因为可嵌入对象没有自己的标识(缺少主键),所以它只需要作为封装它的实体的一部分来处理。 从数据库的角度来看,嵌入对象与其余实体属性一起存储在一行中。

由于上述原因,如果有人试图从EntityABCD EmploymentPeriod创建单向关系 由于缺乏EmploymentPeriod的身份,根本不可能, 因此无法在嵌入对象中创建外键。

如何克服外键问题?

外键需要在可嵌入类之外进行物理创建,这取决于关系类型。一个例子(:

@Entity
public class Employee {
  @Id
  private long id;

  @Embedded
  private EmploymentPeriod period;
}

@Embeddable
public class EmploymentPeriod {
    @ManyToOne //owning relationship
    @JoinColumn //FK in EMPLOYEE table (by default: ENTITYABCD_ID) 
    private EntityABCD entityABCD;

    @ManyToMany //owning relationship
    @MapKey(name="id") //refers to EntityABCD.id
    @JoinTable //FK in the join table (by default: EMPLOYEE_ENTITYABCD)
    private Map<Long, EntityABCD> entitiesABCD;
}

@Entity
public class EntityABCD {
    @Id
    private long id;

    @OneToMany(mappedBy = "period.entityABCD") //non-owning relationship
    List<Employee> employee;

    @ManyToMany(mappedBy="period.entitiesABCD") //non-owning relationship
    private List<Employee> employees;
}

当嵌入对象中存在双向关系时,它们被视为拥有实体中存在的那些(Employee) 并且目标实体(EntityABCD)指向拥有实体,而不是指向嵌入对象(EmploymentPeriod)。

值得一提的是,嵌入式只能嵌入:

  • 其他嵌入式
  • 与实体的关系
  • 基本/可嵌入类型的元素集合