Java Persistence/Embeddables

From Wikibooks, open books for an open world
Jump to: navigation, search

 

 

Embeddables[edit]

Embeddable.PNG

In an application object model some objects are considered independent, and others are considered dependent parts of other objects. In UML a relationship to a dependent object is considered an aggregate or composite association. In a relational database this kind of relationship could be modeled in two ways, the dependent object could have its own table, or its data could be embedded in the independent object's table. Which is another word to say the dependent data is included in the independent object's table.

In JPA a relationship where the target object's data is embedded in the source object's table is considered an embedded relationship, and the target object is considered an Embeddable object. Embeddable objects have different requirements and restrictions than Entity objects and are defined by the @Embeddable annotation or <embeddable> element.

An embeddable object cannot be directly persisted, or queried, it can only be persisted or queried in the context of the source object in which it is embedded. An embeddable object does not have an id or table. The JPA spec does not support embeddable objects having inheritance, although some JPA providers may allow this. Relationships from embeddable objects are supported in JPA 2.0.

Relationships to embeddable objects are defined through the @Embedded annotation or <embedded> element. The JPA 2.0 spec also supports collection relationships to embeddable objects.

Example of an Embeddable object annotations[edit]

@Embeddable 
public class EmploymentPeriod {
  @Column(name="START_DATE")
  private java.sql.Date startDate;

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

Example of an Embeddable object XML[edit]

<embeddable class="org.acme.EmploymentPeriod" access="FIELD">
    <attributes>
        <basic name="startDate">
            <column name="START_DATE"/>
        </basic>
        <basic name="endDate">
            <column name="END_DATE"/>
        </basic>
    </attributes>
</embeddable>

Example of an embedded relationship annotations[edit]

@Entity
public class Employee {
  @Id
  private long id;
  ...
  @Embedded
  private EmploymentPeriod period;
  ...
}

Example of an embedded relationship XML[edit]

<entity name="Employee" class="org.acme.Employee" access="FIELD">
    <attributes>
        <id name="id"/>
        <embedded name="period"/>
    </attributes>
</entity>

Advanced[edit]

Embedding more than one Instance of the same embeddable Type[edit]

Instances of an embeddable object can be embedded in the same parent entity more than once. However, without additional measures this creates a naming conflict, because it would require to have two or more columns with the same name in a table, which is not possible. The columns of all (except one of) the embedded instances of the same type need to be renamed to ensure unique column names. This renaming is done through the @AttributeOverride annotation, the <attribute-override> element, the @AssociationOverride annotation, or the <association-override> element.

  • @AttributeOverride is used to rename a basic mapping.
  • @AssociationOverride is used to rename the mapping for an entity relationship.
For example, @AssociationOverride is needed for an attribute in the embeddable class which is a @ManyToOne relation or a @OneToOne relation. I.e. when the embeddable class holds a foreign key.

@AttributeOverride and @AssociationOverride annotations are grouped together with @AttributeOverrides and @AssociationOverrides annotations respectively (note the plurals).

/** An Entity to which the Embeddable has a ManyToOne relation */
@Entity
public class Location {
  @Id
  private java.lang.Integer id; 

  ...
}

/** Embeddable that will be embed twice in the same table */
@Embeddable 
public class User {
  // Basic mapping
  @Column(name="USER_NAME")
  private java.lang.String userName;

  // Basic mapping
  @Column(name="USER_ACCOUNT")
  private java.lang.Integer userAccount;

  // Relationship
  @ManyToOne()
  @JoinColumn(name = "LOCATION_ID", referencedColumnName = "id")
  public Location location;

  ...
}

/** Entity holding two instances of the same Embeddable type */
@Entity
public class Employee {
  @Id
  private long id;
  ...
  
  // Embed an instance of User
  @Embedded
  // rename the basic mappings
  @AttributeOverrides({
    @AttributeOverride(name="userName", column=@Column(name="EMPLOYEE_NAME")),
    @AttributeOverride(name="userAccount", column=@Column(name="EMPLOYEE_ACCOUNT"))
  })
  // rename the relationship
  @AssociationOverrides({
    @AssociationOverride(name = "location",
                joinColumns = @JoinColumn(name = "EMPLOYEE_LOCATION_ID"))
  })
  private User employee;

  // Embed a second instance of User
  @Embedded
  // rename the basic mappings
  @AttributeOverrides({
    @AttributeOverride(name="userName", column=@Column(name="SUPERVISOR_NAME")),
    @AttributeOverride(name="userAccount", column=@Column(name="SUPERVISOR_ACCOUNT"))
  })
  // rename the relationship
  @AssociationOverrides({
    @AssociationOverride(name = "location",
                joinColumns = @JoinColumn(name = "SUPERVISOR_LOCATION_ID"))
  })
  private User supervisor;

  ...
}

Sharing[edit]

An embeddable object can be shared between multiple classes. Consider a Name object, that both an Employee and a User contain. Both Employee and a User have their own tables, with different column names that they desire to store their name in. Embeddables support this through allowing each embedded mapping to override the columns used in the embeddable. This is done through the @AttributeOverride annotation or <attribute-override> element.

Note that an embeddable cannot be shared between multiple instances. If you desire to share an embeddable object instance, then you must make it an independent object with its own table.

Example shared embeddable annotations[edit]

@Entity
public class Employee {
  @Id
  private long id;
  ...
  @Embedded
  @AttributeOverrides({
    @AttributeOverride(name="startDate", column=@Column(name="START_DATE")),
    @AttributeOverride(name="endDate", column=@Column(name="END_DATE"))
  })
  private Period employmentPeriod;
  ...
}
@Entity
public class User {
  @Id
  private long id;
  ...
  @Embedded
  @AttributeOverrides({
    @AttributeOverride(name="startDate", column=@Column(name="SDATE")),
    @AttributeOverride(name="endDate", column=@Column(name="EDATE"))
  })
  private Period period;
  ...
}

Example shared embeddable XML[edit]

<entity name="Employee" class="org.acme.Employee" access="FIELD">
    <attributes>
        <id name="id"/>
        <embedded name="employmentPeriod">
            <attribute-override name="startDate">
                <column name="START_DATE"/>
            </attribute-override>
            <attribute-override name="endDate">
                <column name="END_DATE"/>
            </attribute-override>
        </embedded>
    </attributes>
</entity>
<entity name="User" class="org.acme.User" access="FIELD">
    <attributes>
        <id name="id"/>
        <embedded name="period">
            <attribute-override name="startDate">
                <column name="SDATE"/>
            </attribute-override>
            <attribute-override name="endDate">
                <column name="EDATE"/>
            </attribute-override>
        </embedded>
    </attributes>
</entity>

Embedded Ids[edit]

An EmbeddedId is an embeddable object that contains the Id for an entity.

See: Embedded Id

Nulls[edit]

An embeddable object's data is contained in several columns in its parent's table. Since there is no single field value, there is no way to know if a parent's reference to the embeddable is null. One could assume that if every field value of the embeddable is null, then the reference should be null, but then there is no way to represent an embeddable with all null values. JPA does not allow embeddables to be null, but some JPA providers may support this.

TopLink / EclipseLink : Support an embedded reference being null. This is set through using a DescriptorCustomizer and the AggregateObjectMapping setIsNullAllowed API.
Hibernate : When loading an entity, embedded references are set to null if all of the columns in the embeddable are null.

Nesting[edit]

A nested embeddable is a relationship to an embeddable object from another embeddable. The JPA 1.0 spec only allows Basic relationships in an embeddable object, so nested embeddables are not supported, however some JPA products may support them. Technically there is nothing preventing the @Embedded annotation being used in an embeddable object, so this may just work depending on your JPA provider (cross your fingers).

JPA 2.0 supports nested embeddable objects.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

TopLink / EclipseLink : Support embedded mappings from embeddables. The existing @Embedded annotation or <embedded> element can be used.

A workaround to having a nested embeddable, and for embeddables in general is to use property access, and add get/set methods for all of the attributes of the nested embeddable object.

Example of using properties to define a nested embeddable[edit]

@Embeddable
public class EmploymentDetails {
  private EmploymentPeriod period;
  private int yearsOfService;
  private boolean fullTime;
  ....
  public EmploymentDetails() {
    this.period = new EmploymentPeriod();
  }
  @Transient
  public EmploymentPeriod getEmploymentPeriod() {
    return period;
  }
  @Basic
  public Date getStartDate() {
    return getEmploymentPeriod().getStartDate();
  }
  public void setStartDate(Date startDate) {
    getEmploymentPeriod().setStartDate(startDate);
  }
  @Basic
  public Date getEndDate() {
    return getEmploymentPeriod().getEndDate();
  }
  public void setEndDate(Date endDate) {
    getEmploymentPeriod().setEndDate(endDate);
  }
  ....
}

Inheritance[edit]

Embeddable inheritance is when one embeddable class subclasses another embeddable class. The JPA spec does not allow inheritance in embeddable objects, however some JPA products may support this. Technically there is nothing preventing the @DiscriminatorColumn annotation being used in an embeddable object, so this may just work depending on your JPA provider (cross your fingers). Inheritance in embeddables is always single table as an embeddable must live within its' parent's table. Generally attempting to mix inheritance between embeddables and entities is not a good idea, but may work in some cases.

TopLink / EclipseLink : Support inheritance with embeddables. This is set through using a DescriptorCustomizer and the InheritancePolicy.

Relationships[edit]

A relationship is when an embeddable has a OneToOne or other such mapping to an entity. The JPA 1.0 spec only allows Basic mappings in an embeddable object, so relationships from embeddables are not supported, however some JPA products may support them. Technically there is nothing preventing the @OneToOne annotation or other relationships from being used in an embeddable object, so this may just work depending on your JPA provider (cross your fingers).

JPA 2.0 supports all relationship types from an embeddable object.

TopLink / EclipseLink : Support relationship mappings from embeddables. The existing relationship annotations or XML elements can be used.

Relationships to embeddable objects from entities other than the embeddable's parent are typically not a good idea, as an embeddable is a private dependent part of its parent. Generally relationships should be to the embeddable's parent, not the embeddable. Otherwise, it would normally be a good idea to make the embeddable an independent entity with its own table. If an embeddable has a bi-directional relationship, such as a OneToMany that requires an inverse ManyToOne the inverse relationship should be to the embeddable's parent.

A workaround to having a relationship from an embeddable is to define the relationship in the embeddable's parent, and define property get/set methods for the relationship that set the relationship into the embeddable.

Example of setting a relationship in an embeddable from its parent[edit]

@Entity
public class Employee {
  ....
  private EmploymentDetails details;
  ....
  @Embedded
  public EmploymentDetails getEmploymentDetails() {
    return details;
  }
  @OneToOne
  public Address getEmploymentAddress() {
    return getEmploymentDetails().getAddress();
  }
  public void setEmploymentAddress(Address address) {
    getEmploymentDetails().setAddress(address);
  }
}

One special relationship that is sometimes desired in an embeddable is a relationship to its parent. JPA does not support this, but some JPA providers may.

Hibernate : Supports a @Parent annotation in embeddables to define a relationship to its parent.

A workaround to having a parent relationship from an embeddable is to set the parent in the property set method.

Example of setting a relationship in an embeddable to its parent[edit]

@Entity
public class Employee {
  ....
  private EmploymentDetails details;
  ....
  @Embedded
  public EmploymentDetails getEmploymentDetails() {
    return details;
  }
  public void setEmploymentDetails(EmploymentDetails details) {
    this.details = details;
    details.setParent(this);
  }
}

Collections[edit]

A collection of embeddable objects is similar to a OneToMany except the target objects are embeddables and have no Id. This allows for a OneToMany to be defined without a inverse ManyToOne, as the parent is responsible for storing the foreign key in the target object's table. JPA 1.0 did not support collections of embeddable objects, but some JPA providers support this.

JPA 2.0 does support collections of embeddable objects through the ElementCollection mapping. See, ElementCollection.

EclipseLink (as of 1.2) : Supports the JPA 2.0 ElementCollection mapping.
TopLink / EclipseLink : Support collections of embeddables. This is set through using a DescriptorCustomizer and the AggregateCollectionMapping.
Hibernate : Supports collections of embeddables through the @CollectionOfElements annotation and JPA 2.0 ElementCollection mapping.
DataNucleus : Supports the JPA 2.0 ElementCollection mapping.

Typically the primary key of the target table will be composed of the parent's primary key, and some unique field in the embeddable object. The embeddable should have a unique field within its parent's collection, but does not need to be unique for the entire class. It could still have a unique id and still use sequencing, or if it has no unique fields, its id could be composed of all of its fields. The embeddable collection object will be different than a typical embeddable object as it will not be stored in the parent's table, but in its own table. Embeddables are strictly privately owned objects, deletion of the parent will cause deletion of the embeddables, and removal from the embeddable collection should cause the embeddable to be deleted. Embeddables cannot be queried directly, and are not independent objects as they have no Id.

Querying[edit]

Embeddable objects cannot be queried directly, but they can be queried in the context of their parent. Typically it is best to select the parent, and access the embeddable from the parent. This will ensure the embeddable is registered with the persistence context. If the embeddable is selected in a query, the resulting objects will be detached, and changes will not be tracked.

Example of querying an embeddable[edit]

SELECT employee.period from Employee employee where employee.period.endDate = :param

 

 

[출처] https://en.wikibooks.org/wiki/Java_Persistence/Embeddables

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
35 [EMF] EMF Tutorial EMF 튜터리얼 file 졸리운_곰 2023.08.23 283
34 Eclipse RAP Tutorial for Beginners - Workbench Application (OLD) file 졸리운_곰 2021.01.30 323
33 Learn Eclipse GMF in 15 minutes file 졸리운_곰 2019.11.27 253
32 [Eclipse] GEF entry series (10, an implementation of the form) file 졸리운_곰 2019.11.25 212
31 GEF Programmer Guide 번역 졸리운_곰 2019.11.25 228
30 Learn Eclipse GMF in 15 minutes file 졸리운_곰 2019.11.20 224
29 RCP 에디터 정리 졸리운_곰 2019.11.20 333
28 다른 그림과 관련하여 GEF 편집기 레이아웃에서 그림의 위치 제한 조건을 동적으로 계산 Dynamically calculating the position constraints for a figure in a GEF editor layout in relation to another figure file 졸리운_곰 2019.11.20 277
27 RCP 등에서 .mf 파일로 다른 프로젝트 익스포트 포함시 라이브러리(메소드)를 찾지 못할 때, Eclipse RCP - cant resolve importing libraries in final build file 졸리운_곰 2019.10.15 410
26 ESE2006-EclipseModelingSymposium15_GMF.pdf file 졸리운_곰 2019.09.21 302
25 GMF_Creation_Review.pdf file 졸리운_곰 2019.09.21 367
24 Eclipse EMF and GMF Tutorial file 졸리운_곰 2019.09.21 222
23 GMF Tutorial/ko file 졸리운_곰 2019.09.20 347
22 Model Driven Architecture approach to domain of graphical editors file 졸리운_곰 2019.09.20 268
21 Single_Sourcing_RAP_RCP_en.pdf file 졸리운_곰 2019.05.15 311
20 Rich client platform 설명 및 배우기 참고 졸리운_곰 2019.05.15 309
19 Rich Ajax Platform, Part 1: 소개 file 졸리운_곰 2019.05.15 320
18 또 하나의 크로스 플랫폼: Eclipse RAP file 졸리운_곰 2019.05.15 319
17 Eclipse 4 RCP 튜토리얼(완료) file 졸리운_곰 2019.05.14 977
16 Updating UI in Eclipse RCP 졸리운_곰 2015.11.07 409
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED