扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
一个嵌入对象是一个自己不具有id的持久化对象。它是另外一个实体的一部分。例如,我们可以假定Address对象没有自己的id,并且它作为Employee实体的一部分进行存储。因此,Address是一个嵌入对象。
你可以采用如下的方法来创建一个嵌入对象
@Embeddable public class Address { protected String streetAddr1; protected String streetAddr2; protected String city; protected String state; .. } |
下面是如何将一个对象嵌入到一个目标对象中
@Entity public class Employee { @Id @GeneratedValue(strategy=GenerationType.AUTO) protected Long id; ... @Embedded protected Address address; ... } |
关系
在一个典型的领域模型中,实体可能互相联系或者存在一定的关系。两个实体之间的关系可能是一对一(one-to-one),一对多(one-to-many),多对一(many-to-one),多对多(many-to-many)。实体之间的这些关系可以分别使用OneToOne, OneToMany, ManyToOne, or ManyToMany标注来描述。我们的示例在Department和Employee实体上采用了双向的OneToMany关系。
既然我们在实体中使用了基于字段的访问,那么我们就在Department实体的关系字段上使用标注,如下:
@OneToMany(mappedBy="department") protected Collection<Employee> employees ; |
对于一个双向的关系来说,你必须指定mappedBy元素,就像上面那样,通过指明拥有这个关系的字段名或者属性名来指出反向的关系如何进行映射。
标准化O-R 映射
你可以使用Java标注或者XML来进行实体的O-R映射的定义。EJB3 JPA定义了几个标注来进行O-R映射,例如Table,SecondaryTable, Column, JoinColumn, 以及 PrimaryKeyJoinColumn等标注。参考EJB3 JPA规范来获取所有标注的信息。
在我们的例子中,你可以使用Table标注来定义该实体应该映射到那个表中,例如:
@Table(name="DEPT") public class Department implements Serializable { |
EJB3 JPA中,各种映射都普遍具有默认值。如果你不定义表映射的话,持久化提供者会假定这个实体将要映射到和实体类类名同名的表中(在这个例子中就是Deparment表)。如果你的实体需要映射到多个表中,你可以使用SecondaryTable标注。
你可以使用Column标注将一个字段或者属性映射到数据库中的一个字段,就像下面这样:
@Column(name="DNAME") protected String name; |
这里,DNAME是需要持久化的字段name要映射的数据库中的字段名。如果你不使用Column定义字段的映射的话,持久化引擎会尝试使用与字段名或者属性名相同的数据库字段名来进行持久化。
实体继承
EJB3 JPA 采用多种方法来支持实体继承。它需要两种类型的继承表映射策略:Single-table-per-entity 继承层次策略和Joined-Subclass策略。最好避免使用可选的table-per-class层次。
single-table-per-entity 继承层次策略允许一个继承层次中的所有实体都映射到单一的表中。在我们的示例中,FullTime和Contractor都继承了Employee,所有它们的示例都会被映射到一个叫做EMP的表中。换句话说,所有与Employee,FullTime和Contractor相关的数据都会被存储到同一个表中。
如果你使用Joined-Subclass策略,你可以将通用的数据映射到超类(例如Employee)表中,同时为每个子类定义一个表来存储子类特有的数据。
必须在超类上使用Inheritance标注来指明采用的继承映射策略,就像下面的代码那样。这个例子演示了实体继承层次使用single-table-per-entity策略的方法。
@Entity @Table(name="EMP") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="EMPLOYEE_TYPE", discriminatorType=DiscriminatorType.STRING, length=1) public abstract class Employee implements Serializable { ... } |
每个子类必须指明用于区分实体类型的值,如下所示:
@Entity @DiscriminatorValue(value="F") public class FullTime extends Employee { @Column(name="SAL") protected Double salary; @Column(name="COMM") protected Double commission; @Column(name="DESIG") protected String designation; ... } |
Entity Manager API:实体操作的标准API
javax.persistence.EntityManager 用来管理实体的声明周期,它提供了几个方法来进行实体的CRUD操作。
EntityManager API 在一个事务上下文(transaction context)中被调用。你可以从EJB容器以外来调用它,例如,你可以从一个Web应用中来调用,使用EntityManager API并不一定需要一个sesssion bean门面(facade).
在你进行实体操作之前,你必须获取一个EntityManager的实例。你可以使用容器管理的实体管理器,也可以使用应用程序管理的实体管理器,同时你可以使用JNDI查询或者依赖注射来获取EntityManager得实例。顾名思义,在容器管理的Entity Manager的情况下,Java EE容器管理Entity Manager的生命周期。这通常在企业Java应用中使用。
你可以使用PersistenceContext标注来进行依赖注射而获取一个容器管理的entity manager的实例,如下:
@PersistenceContext(unitName="onjava") private EntityManager em; |
如果你想要使用应用程序管理的entity manager,你必须自己管理它的声明周期。你可以使用如下方法创建它的一个实例。
@PersistenceUnit(unitName="onjava") private EntityManagerFactory emf; private EntityManager em = emf.createEntityManager(); |
然后,就可以使用EntityManager实例来进行实体的CRUD操作了。为了关闭应用程序管理的entity manager的实例,在进行完操作以后调用em.close()方法。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者