跳转到内容

Java 持久化/ElementCollection

来自 Wikibooks,开放世界中的开放书籍

ElementCollection

[编辑 | 编辑源代码]

JPA 2.0 定义了 ElementCollection 映射。它旨在处理几种非标准关系映射。ElementCollection 可用于定义与 Embeddable 对象的 一对多 关系,或 Basic 值(例如 String 集合)。ElementCollection 也可以与 Map 结合使用来定义关系,其中键可以是任何类型的对象,而值是 Embeddable 对象或 Basic 值。

在 JPA 中,ElementCollection 关系通过 @ElementCollection 注解或 <element-collection> 元素定义。

ElementCollection 值始终存储在单独的表中。该表通过 @CollectionTable 注解或 <collection-table> 元素定义。CollectionTable 定义了表的 name@JoinColumn@JoinColumns (如果使用复合主键)。

嵌入式集合

[编辑 | 编辑源代码]

ElementCollection 映射可用于定义 Embeddable 对象的集合。这不是 Embeddable 对象的典型用法,因为这些对象不会嵌入到源对象的表中,而是存储在单独的集合表中。这类似于 OneToMany,只是目标对象是 Embeddable 而不是 Entity。这允许轻松定义简单对象的集合,而无需要求简单对象定义 IdManyToOne 逆映射。ElementCollection 还可以覆盖其集合的映射或表,因此您可以让多个实体引用同一个 Embeddable 类,但每个实体将它们相关的对象存储在单独的表中。

使用 ElementCollection 而不是 OneToMany 的局限性在于,目标对象无法独立于其父对象进行查询、持久化、合并。它们严格来说是私有拥有的(依赖)对象,与 Embedded 映射相同。ElementCollection 上没有 cascade 选项,目标对象始终与其父对象一起持久化、合并、删除。ElementCollection 仍然可以使用 fetch 类型,并且默认情况下为 LAZY,与其他集合映射相同。

ElementCollection 关系数据库示例

[编辑 | 编辑源代码]

EMPLOYEE(表)

EMP_ID F_NAME L_NAME SALARY
1 Bob Way 50000
2 Joe Smith 35000

PHONE(表)

OWNER_ID TYPE AREA_CODE P_NUMBER
1 home 613 792-0001
1 work 613 494-1234
2 work 416 892-0005

ElementCollection 关系注解示例

[编辑 | 编辑源代码]
@Entity
public class Employee {
  @Id
  @Column(name="EMP_ID")
  private long id;
  ...
  @ElementCollection
  @CollectionTable(
        name="PHONE",
        joinColumns=@JoinColumn(name="OWNER_ID")
  )
  private List<Phone> phones;
  ...
}
@Embeddable
public class Phone {
  private String type;
  private String areaCode;
  @Column(name="P_NUMBER")
  private String number;
  ...
}

ElementCollection 关系 XML 示例

[编辑 | 编辑源代码]
<entity name="Employee" class="org.acme.Employee" access="FIELD">
    <attributes>
        <id name="id">
            <column name="EMP_ID"/>
        </id>
        <element-collection name="phones">
            <collection-table name="PHONE">
                <join-column name="OWNER_ID"/>
            </collection-table>
        </element-collection>
    </attributes>
</entity>
<embeddable name="Phone" class="org.acme.Phone" access="FIELD">
    <attributes>
        <basic name="number">
            <column name="P_NUMBER"/>
        </basic>
    </attributes>
</embeddable>

基本集合

[编辑 | 编辑源代码]

ElementCollection 映射可用于定义 Basic 对象的集合。Basic 值存储在单独的集合表中。这类似于 OneToMany,只是目标是 Basic 值而不是 Entity。这允许轻松定义简单值的集合,而无需为该值定义类。

ElementCollection 上没有 cascade 选项,目标对象始终与其父对象一起持久化、合并、删除。ElementCollection 仍然可以使用 fetch 类型,并且默认情况下为 LAZY,与其他集合映射相同。

ElementCollection 关系到基本值数据库示例

[编辑 | 编辑源代码]

EMPLOYEE(表)

EMP_ID F_NAME L_NAME SALARY
1 Bob Way 50000
2 Joe Smith 35000

PHONE(表)

OWNER_ID PHONE_NUMBER
1 613-792-0001
1 613-494-1234
2 416-892-0005

ElementCollection 关系到基本值注解示例

[编辑 | 编辑源代码]
@Entity
public class Employee {
  @Id
  @Column(name="EMP_ID")
  private long id;
  ...
  @ElementCollection
  @CollectionTable(
        name="PHONE",
        joinColumns=@JoinColumn(name="OWNER_ID")
  )
  @Column(name="PHONE_NUMBER")
  private List<String> phones;
  ...
}

ElementCollection 关系到基本值 XML 示例

[编辑 | 编辑源代码]
<entity name="Employee" class="org.acme.Employee" access="FIELD">
    <attributes>
        <id name="id">
            <column name="EMP_ID" />
        </id>
        <element-collection name="phones" target-class="java.lang.String">
            <column name="PHONE_NUMBER" />
            <collection-table name="PHONE">
                <join-column name="OWNER_ID" />
            </collection-table>
        </element-collection>
    </attributes>
</entity>

另请参见

[编辑 | 编辑源代码]

常见问题

[编辑 | 编辑源代码]
CollectionTable 中的主键
[编辑 | 编辑源代码]
JPA 2.0 规范没有提供定义 EmbeddableId 的方法。但是,为了删除或更新 ElementCollection 映射的元素,通常需要一些唯一的。否则,JPA 提供者将需要在每次更新时从 EntityCollectionTable 中删除所有内容,然后再插入值。因此,JPA 提供者很可能会假设 Embeddable 中所有字段的组合与外键(JoinColumn(s))组合是唯一的。然而,如果 Embeddable 很大或很复杂,这可能效率低下或不可行。
一些 JPA 提供者可能允许在 Embeddable 中指定 Id 来解决此问题。请注意,在这种情况下,Id 只需要在集合中是唯一的,而不是在表中是唯一的,因为外键包含在内。一些 JPA 提供者也可能允许使用 CollectionTable 上的 unique 选项来实现这一点。否则,如果 Embeddable 很复杂,您可能需要将其改为 Entity,并使用 OneToMany 代替。
华夏公益教科书