identifier简介
identifiers在JPA中代表着数据实体的主键,JPA支持两种主要类型的标识符:
- 人为分配的(assigned)
- 自动产生的(generated)
对于assigned类型的identifier,在持久化之前,必须在每个给定实体上设置标识符。因此,assigned类型的标识符适用于自然键(实体的属性可以作为主键唯一标识该实体)。
对于合成主键(人为定义的字段作为唯一标识实体的标志),我们需要使用generated类型的实体标识符,JPA通过使用@GeneratedValue注解来自动生成标识符。
GenerationType枚举定义了四种类型的生成的标识符策略:
- AUTO
- IDENTITY
- SEQUENCE
- TABLE
AUTO标识符生成器策略根据基础关系数据库功能选择其他三个策略之一(IDENTITY,SEQUENCE或TABLE)。
IDENTITY生成器依赖数据库表中一个自动递增的列(例如SQL Server中的IDENTITY或MySQL中的AUTO_INCREMENT),SEQUENCE生长期依赖一个与表无关的数据库序列,TABLE生成器在关系数据库中没有直接实现,它是依赖在数据库中一张存储identifier的表。
Assigned类型的identifier实现如下:
@Id
private Long id;
Generated类型的identifier实现如下:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
自定义identifier生成方式
在使用JPA的过程有自定义identifier的需求,例如:在一个用户管理系统中,需要预留一部分id号码(如10000以内的号码)给特殊的用户,而普通用户则使用自动生成的id,这时使用默认的方式是不能满足需求的,好在Spring JPA中提供了便捷的自定义identifier的方式。
首先,需要让实体实现以下接口:
public interface Identifiable<T extends Serializable> {
T getId();
}
为了能自定义identifier,我们可以写一个如下的identifier生成策略:
public class AssignedIdentityGenerator extends IdentityGenerator {
@Override
public Serializable generate(SessionImplementor session, Object obj) {
if(obj instanceof Identifiable) {
Identifiable identifiable = (Identifiable) obj;
Serializable id = identifiable.getId();
if(id != null) {
return id;
}
}
return super.generate(session, obj);
}
}
如果实体没有设定id,则使用默认的自增策略,如果有设定的id,则使用设定的id,采用该策略的实体的写法为:
@Entity(
public class Post implements Identifiable<Long> {
@Id
@GenericGenerator(
name = "assigned-identity",
strategy = "com.vladmihalcea.book.hpjp.hibernate.identifier.AssignedIdentityGenerator"
)
@GeneratedValue(
generator = "assigned-identity",
strategy = GenerationType.IDENTITY
)
private Long id;
public Post() {
}
public Post(Long id) {
this.id = id;
}
@Override
public Long getId() {
return id;
}
}
在@GenericGenerator注解中标识出该生成器的名字和依赖的类,在@GeneratedValue注解中指明使用生成器的名字,即可实现使用自定义的id生成器。