Spring JPA - 自定义Entity的identifier生成方式

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 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 {
 
    @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生成器。

参考文献

  1. How to combine the Hibernate assigned generator with a sequence or an identity column
  2. Why you should never use the TABLE identifier generator with JPA and Hibernate

你可能感兴趣的:(Spring JPA - 自定义Entity的identifier生成方式)