Java Persistence API(JPA)
定义了一种规范,可以将常规的普通Java类(有时被称作POJO
)映射到数据库.这些Java类被称作Entity Bean
.
除了是用Java Persistence元数据将其映射到数据库外,Entity Bean与其他Java类没有任何区别:创建一个Entity Bean对象相当于数据库新建一条记录;删除一个Entity Bean会同时从数据库中删除对应记录;修改一个Entity Bean时,容器会自动将Entity Bean的状态和数据库同步。
而POJO与数据库表之间的映射,称为ORM(Object Relational Mapping, 对象关系映射)
注解
@Entity
@Entity
声明这个类是Entity Bean
,并且使用默认的ORM规则,即class名即数据库表中表名,class字段名即表中的字段名.
映射规则:
1. 映射的表名为: @Table.name
> @Entity.name
> Class类名
2. 必须使用@Id
来注解一个主键
3. 必须拥有一个publich或者protected的无参构造函数
4. 实体类必须是一个顶级类(top-level class),枚举(enum)或接口(interface)不能注解为实体类
5. 实体类不能是final,也不能有final方法
6. 实体类需要用传值的方式调用(例如远程调用),则这个实体类必须实现 java.io.Serializable接口
@Table
@Table
对@Entity
标注的类进行详细设定.
属性:
属性名 | 作用 |
---|---|
name | 表名,默认”“时值为@Entity.name ,若@Entity.name 也为”“,则为Class类名 |
catalog | 数据库catalog |
schema | 数据库schema |
uniqueConstraints | 定义一个UniqueConstraint 数组,指定需要建立唯一约束的列 |
indexes | 建立索引 |
- uniqueConstraints
@Entity
@Table(uniqueConstraints={
@UniqueConstraint(name="uq_name", columnNames="name"),
@UniqueConstraint(name="uq_nick_name", columnNames="nickName")
})
public class User extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Column
private String name;
@Column
private String nickName;
}
建立了两个唯一约束,等同于
alter table user add constraint uq_name unique (name)
alter table user add constraint uq_nick_name unique (nick_name)
也可以建立多列组合唯一约束
@Table(uniqueConstraints={
@UniqueConstraint(name="uq_name", columnNames={"name","nickName"})
})
等同于
alter table user add constraint uq_name unique (name, nick_name)
- indexes
@Entity
@Table(indexes={
@Index(name="index1",unique=true,columnList="name")
})
public class User extends AbstractEntity {
....
}
alter table user add constraint index1 unique (name)
@Id
声明Entity Bean
的主键
@GeneratedValue
设置主键的生成策略
属性名 | 作用 |
---|---|
strategy | 主键生成策略 |
strategy
可选值 | 说明 |
---|---|
TABLE | |
SEQUENCE | |
IDENTITY | 以id自增序列增长,主要用于mysql,oracle无法使用 |
AUTO | 默认值 |
@Column
设置字段与列的映射
属性:
属性名 | 作用 |
---|---|
name | (可选) 列名,默认为属性名或字段名 |
unique | (可选)该列是否为唯一值.当与@Table的uniqueConstraint注解了同一个字段时,该注解的优先级更高 |
nullable | (可选)该列是否可空 |
insertable | (可选) 该列是否可作为sql的insert语句 |
updatable | (可选)该列是否可作为sql的update语句 |
columnDefinition | 该列为生成DDL时使用的SQL片段 默认为生成的sql创建一个推断类型的列 |
table | 包含该列的表的名称,如果没有该列,则假定该列位于主表中 |
length | 列的长度(只有使用了字符串类型的列才应用该属性) |
precision | 小数(精确数字)列的精度(仅使用小数列时才适用).在生成DDL时,必须由开发人员设置值 |
scale | 十进(精确数字)制列的精度(仅使用小数列时才适用) |
@OrderBy
@OneToOne
一对一映射策略, 用于实体类中的对象属性
属性:
属性名 | 作用 | 类型 |
---|---|---|
cascade | 指定级联操作的行为(可多选) | |
fetch | 懒加载 | |
optional | ||
mappedBy | ||
orphanRemoval | ||
targetEntity |
cascade
指定级联操作的行为(可多选)
CascadeType.PERSIST 级联新增(又称级联保存)
获取A对象里也同时也重新获取最新的B时的对象。即会重新查询数据库里的最新数据,并且,只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态),对应EntityManager的presist方法,调用JPA规范中的persist(),不适用于Hibernate的save()方法CascadeType.MERGE 级联合并(又称级联更新)
指A类新增或者变化,会级联B对象(新增或者变化) ,对应EntityManager的merge方法,调用JPA规范中merge()时,不适用于Hibernate的update()方法CascadeType.REMOVE 级联删除
只有A类删除时,会级联删除B类,即在设置的那一端进行删除时,另一端才会级联删除,对应EntityManager的remove方法,调用JPA规范中的remove()时,适用于Hibernate的delete()方法CascadeType.REFRESH 级联刷新
获取order(一或多)对象里也同时也重新获取最新的items(多)的对象,对应EntityManager的refresh(object),调用JPA规范中的refresh()时,适用于Hibernate的flush()方法CascadeType.ALL
包含所有持久化方法
fetch
指定数据加载方式(是否懒加载)
FetchType.LAZY 懒加载
默认不加载关联的对象,当使用时才生成语句进行查询(需要保证使用时仍处于DataSource Session周期中)FetchType.EAGER 积极加载
直接进行外键关联加载数据
optional
mappedBy
orphanRemoval
targetEntity
@ManyToOne
多对一映射策略, 用于实体类中的对象属性。
属性:
属性名 | 作用 | 类型 |
---|---|---|
cascade | 指定级联操作的行为(可多选) | |
fetch | 懒加载 | |
optional | ||
targetEntity |
@OneToMany
一对多映射策略, 用于实体类中的列表,数组属性。
属性:
属性名 | 作用 | 类型 |
---|---|---|
cascade | 指定级联操作的行为(可多选) | |
fetch | 懒加载 | |
mappedBy | ||
targetEntity | ||
orphanRemoval |
@ManyToMany
多对多映射策略, 用于实体类中的列表,数组属性。
属性:
属性名 | 作用 | 类型 |
---|---|---|
cascade | 指定级联操作的行为(可多选) | |
fetch | 懒加载 | |
mappedBy | ||
targetEntity | ||
mappedBy |
@JoinColumn
外键映射策略的属性的的映射规则
@JoinTable
@Transient
忽略该属性不做映射
@Embeddable
嵌入式类,当类使用该注解时,类中的属性将作为为所属类的属性转化
@Temporal
做日期类型转换
@Lob
声明字段为Clob或Blob
关系映射模型
一对一
一对一映射包含4种映射方式
- 单向外键关联
- 双向外键关联
- 单向主键关联
双向主键关联
- 主键关联: 使用主键关联.不需要额外设置唯一性约束.主键默认唯一性
- 外键关联: 使用外键关联,需要额外设置外键的唯一性约束.否则将无法保证为一对一.但换个角度来说,如果需要将一对一映射转变为一对多,只需要将外键的唯一性约束去掉即可
- 单向关联
- 双向关联
单向外键关联
单向外键一对一关联,即A表中有指向B表主键的外键,且外键为unique(若非unique,则将成为一对多关联)
@Data
@Entity
@Table
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne
private Address address;
}
@Data
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String city;
}
双向外键关联
双向外键一对一关联,即A表中有指向B表主键的外键,B表中也有指向A表主键的外键, 且外键均为unique(若非unique,则将变成一对多关联)
@Data
@Entity
@Table
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne
private Address address;
}
@Data
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String city;
@OneToOne
private User user;
}
单向主键关联
单向主键关联。 即A类的主键必须是B的主键。
双向主键关联
双向主键关联. 即A类与B类主键相等
多对一
外键关联
在一对一外键关联
的基础上, 取消外键的唯一性约束,即可形成一对多关联.
多对一关联是对于外键所在类而言的. 即
@Data
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String city;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
第三表关联
多对一在默认情况下(不使用@JoinColumn
)使用的是外键关联.也可以通过@JoinTable
指定第三表的映射关系
一对多
外键关联
一对多与多对一的外键关联模型是一样的.只是在一对多中.是处于多的一方
而言
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "user_id")
private List<Address> addressList;
}
第三表关联
在一对多模映射中, 若@ManyToOne
不带@JoinColumn
声明外键, 则将会自动生成第三表关联的映射模式. 即
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
@OneToMany
private List<Address> addressList;
}
或通过@JoinTable
指定第三表的映射关系
多对多
多对多映射通过第三表关联.
@Data
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String city;
@ManyToMany
@JoinTable(
name="user_address",
joinColumns={
@JoinColumn(name="address_id",referencedColumnName="id")
},
inverseJoinColumns={
@JoinColumn(name="user_id",referencedColumnName="id")
}
)
private List<User> userList;
}
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
@JoinTable(
name="user_address",
joinColumns={
@JoinColumn(name="user_id",referencedColumnName="id")
},
inverseJoinColumns={
@JoinColumn(name="address_id",referencedColumnName="id")
}
)
private List<Address> addressList;
}
若是双向多对多映射,则必须设定@JoinTable
并指定第三方表.
继承策略
实体类继承后的映射策略