从本篇文章开始,会系统性地介绍JPA中用来实现对象关系映射(Object Relational Mapping)的核心注解,以及基础类型,关系类型,嵌套类型以及集合类型的映射方式。
注解种类
在探讨实现JPA中各种映射的方式之前,可以先看看JPA中的注解类型。
由于ORM这一机制涉及到了两个方面:对象(内存模型)以关系数据(关系型数据库)。而显然我们在配置ORM的各种规则时,只能在Java程序中完成。数据库是不知道有JPA这种机制存在的,数据库只是单纯的执行输入的各种SQL语句而已。
因此,我们可以将JPA中的注解笼统地分为两种类型:
- 逻辑关系注解(Logical Annotation)
- 物理关系注解(Physical Annotation)
所谓的逻辑关系注解,就是声明ORM中的O方,也就是对象实体模型的一些元数据。比如@Basic
注解,它能够规定基本类型的加载方式,即正常加载(Eager)还是懒加载(Lazy)。
所谓的物理关系注解,就是声明ORM中的R方,也就是关系模型中的一些元数据。比如@Column
注解,它能够规定一个字段应该被映射到数据库表中的哪个列。
访问实体状态的方式
只有实体类型(被标注为@Entity
的Java类)才能够通过JPA和数据库中的记录进行互相转换。那么在转换的过程中,JPA的实现必然需要对实体类型进行操作。比如在将实体保存到数据库中的时候,JPA的实现需要通过某种方式访问到实体的状态;在将数据库中查询得到的行记录转换成实体对象的时候,JPA的实现需要设置实体的状态。
在JPA中,两种方式完成实体状态的访问:
- 通过Field
- 通过Property(也就是Getter/Setter)
通过Field
采用这种方式,JPA实现会通过反射的方法来对实体对象的字段进行操作。即使你提供了Getter/Setter,也不会使用它们。那么如何定义试用这种方式呢?通过@Id
注解:
@Entity
public class Person {
@Id
private int id;
private String name;
}
上述代码中,将@Id
放在了Field之上。JPA实现根据这一点决定采用基于Field来访问实体状态的方式。
通过Property(Getter/Setter)
采用这种方式,JPA时限会通过调用Getter/Setter来对实体对象的字段进行操作。还是一样,通过@Id
注解来定义:
@Entity
public class Person {
private int id;
private String name;
@Id
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getNickname() { return nickname; }
public void setNickname(String nickname) { this.name =