【问题标题】:Is it possible to have autoincrement number without it being an ID?是否可以在没有 ID 的情况下拥有自动增量编号?
【发布时间】:2020-05-28 14:41:41
【问题描述】:

我一直在谷歌上搜索,发现唯一的方法就是使用

@Id
@GeneratedValue(strategy = GenerationType.Identity)

但是我已经有一个主键,我只需要另一个自动递增的字段。人工计算编码真的很难。

【问题讨论】:

  • 没有,刚刚试过 @Column(name = "internalID") @Generated(GenerationTime.INSERT) private Long internalID;它什么也没做。插入后值为空
  • 如果你先@Column(name = "internalID")然后@GeneratedValue(strategy=GenerationType.IDENTITY)呢?
  • 不,插入后为空
  • @erotsppa 你能解释一下你为什么要这么做吗?您最初尝试解决的问题是什么。

标签: postgresql hibernate jpa


【解决方案1】:

我看到以下选项:

1) 可以使用@Generated注解。

您应该有一个以下列方式声明的表:

create sequence TST_DATA_SEQ increment by 1 start with 1;

create table TST_DATA (
   ...
   dat_auto integer default nextval('TST_DATA_SEQ'),
   ...
);

以及实体中的相应列:

   @Generated(value = GenerationTime.INSERT)
   @Column(name = "dat_auto", insertable = false, updatable = false)
   private Long auto;

注意根据documentation

标记为已生成的属性还必须是不可插入和不可更新的。

因此,hibernate 将在刷新后进行额外查询以填充 auto 字段。

   Data data = new Data();
   // filling fields except data.auto
   session.persist(data);
   session.flush();
insert into TST_DATA (dat_name, dat_id) 
values (?, ?)

Hibernate: /* get generated state com.example.hibernate.Data */
  select data_.dat_auto as dat_auto_0_ 
  from TST_DATA data_ 
  where data_.dat_id=?

2) 可以使用@GeneratorType注解。

您应该有一个休眠ValueGenerator 的实现。您可以在下面看到一个简单的示例。

import java.math.BigInteger;
import org.hibernate.Session;
import org.hibernate.tuple.ValueGenerator;

public class MyGenerator implements ValueGenerator<Long> 
{
   public Long generateValue(Session session, Object owner)
   {
      return (
         (BigInteger) session
            .createNativeQuery("select nextval('TST_DATA_SEQ')")
            .getSingleResult()
         ).longValue();
   }
}

然后你可以像这样使用它:

   @GeneratorType(type = MyGenerator.class, when = GenerationTime.INSERT)
   @Column(name = "dat_auto")
   private Long auto;

在这种情况下,您不应按照 n1 中的要求为列声明提供默认值。并且相应的实体字段不应该有@Column(... insertable = false, updatable = false)。每次持久化这个实体时,hibernate 都会生成查询:

select nextval('TST_DATA_SEQ')

并将此值填充到auto 字段。

【讨论】:

  • 这两种解决方案都需要创建序列 TST_DATA_SEQ,您知道如何在春季启动过程中自动执行此操作吗?我不想诉诸我的 CD 管道来做这种事情
  • 其实我试过你的第二个解决方案,它进入了 generateValue() 内部的无限循环
  • 至于序列创建看spring bootdocumentation。我在简单的应用程序上测试了两种提议的方法(只有 hibernate 5.4.4.Final 依赖项),它们工作正常。看起来您对an infinite loop inside generateValue() 的问题与与您的项目的集成有关。
【解决方案2】:

或许你可以试试:

@GeneratedValue(GenerationType.strategy=SEQUENCE, generator="internal_seq")
@SequenceGenerator(name="internal_seq", sequenceName="internal_seq", allocationSize=1)
@Column(name="internalID")
public Long internalID;

【讨论】:

  • 不,创建时为空
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多