在Spring Boot实体中自动生成唯一键。

huangapple go评论69阅读模式
英文:

Unique key auto generated in Spring Boot Entity

问题

我在实体表中有一个自动生成的主键,但现在我想要自动生成唯一键,该如何做呢?
请帮我解决。

@Entity
@Table(name = "director")
public class Director {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long id;

    //如何使这个字段像上面的那个一样自动生成
    @Column(name = "subid", unique=true)
    private long sub_id;
}

这是我数据库表的结构,请参考:
在Spring Boot实体中自动生成唯一键。

英文:

I have a primary key in my entity table which is autogenerated but now I want unique keys to be auto generated so how to do it
Please help me out.

    @Entity
    @Table(name = "director")
    public class Director {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private long id;
    
//how to make this field auto generated like above one
        @Column(name = "subid", unique=true)
        private long sub_id;

My database table picture is here please refer
在Spring Boot实体中自动生成唯一键。

答案1

得分: 0

你可以使用时间戳或者static AtomicLong计数器作为sub_id的值。尝试在你的实体类中使用@PrePersist注解来定义一个方法,你的JPA提供程序会在持久化对象之前执行它。
<br>
注意:在并发环境中使用时间戳可能会导致冲突,值将不会是唯一的。

private final static AtomicLong subIdCounter = new AtomicLong(System.nanoTime());

@PrePersist
void sub_id() {
    this.sub_id = subIdCounter.incrementAndGet();
}
英文:

You can use timestamp or static AtomicLong counter as sub_id value. Try to define method with annotation @PrePersist in your entity class and your JPA provider will execute it before persisting an object.
<br>
Note: using timestamp in concurrent environment may lead to collisions and values won't be unique.

private final static AtomicLong subIdCounter = new AtomicLong(System.nanoTime());

@PrePersist
void sub_id() {
    this.sub_id = subIdCounter.incrementAndGet();
}

答案2

得分: 0

经过简要研究,似乎 Hibernate 仅在使用 @Id 注解的字段上支持生成值的特性。使用 @Id 和默认的 @GeneratedValue,Hibernate 会根据所使用的数据库和方言创建适当的方式来生成 id 字段的值。通常情况下,这类似于创建一个 sequence(序列),并设置列定义,例如(以下示例来自于 PostgreSQL 12):

id bigint not null nextval('director_id_seq'::regclass)

有趣的是,这是通过发出以下创建语句来完成的:

create table director (id bigserial not null, primary key (id))

因此,列类型 bigserial 实际上生成用于将默认值插入到 id 列的序列。

如果你想要像对待 id 列一样为 sub_id 列生成值,有两个选项,但两者都取决于数据库。

  1. 手动在数据库中创建序列,然后修改 sub_id 列以从序列获取默认值。

  2. 更改列定义,使用适当的列类型,例如:

@Column(name = "subid", insertable = false,
        nullable = false, unique = true, columnDefinition = "bigserial")
private long sub_id;

这将导致 Hibernate 生成类似以下的表:

create table director (id bigserial not null, subid bigserial not null, primary key (id))

并且生成类似以下的列:

subid bigint not null nextval('director_subid_seq'::regclass)

但需要注意的是:JPA 仅知道存储在 id 字段中的值。虽然 subid 会被插入到数据库表中,但在刷新实体的持久化上下文之前,sub_id 字段不会被填充。

英文:

After a short study it seems that that Hibernate supports the feature of generated values only with fields annotated with @Id. With @Id and default @generatedValue Hibernate creates - depending on the database and dialect used - appropriate way to generate the value of id field. usually this is something like creating a sequence and setting the column definition like (examples are from Postgres 12):

> id bigint not null nextval('director_id_seq'::regclass)

Interesting thing is that this is done by issuing create statement like this:

> create table director (id bigserial not null, primary key (id))

So, the column type bigserial actually generates sequence that is used to insert default value to the id column.

There are two options it you want to generate the value for column sub_id as it is generated to the column id. Both are database dependent.

Just create the sequence manually to the database and alter column sub_id to fetch the default value from the sequence.

OR

Change your column definition to use appropriate column type, like:

@Column(name = &quot;subid&quot;, insertable = false,
        nullable = false, unique = true, columnDefinition = &quot;bigserial&quot;)
private long sub_id;

This will cause Hibernate to generate table like:

> create table director (id bigserial not null, subid bigserial not null, primary key (id))

and result to a column like:

> subid bigint not null nextval('director_subid_seq'::regclass)

But again: this is database specific stuff.

Also note: that JPA is aware only of the value that is stored to the id field. The subid is inserted to the database table but the sub_id field is not populated until entity is refreshed in its persistence context.

huangapple
  • 本文由 发表于 2020年9月5日 16:08:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/63751761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定