Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

postgresql - Is it possible to have autoincrement number without it being an ID?

I keep googling and find that the only way is to use

@Id
@GeneratedValue(strategy = GenerationType.Identity)

But I already have a primary key, I just need another field that auto increments. It's really hard to code it by manual calculation.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I see the following options:

1) You can use @Generated annotation.

You should have a table declared in the following way:

create sequence TST_DATA_SEQ increment by 1 start with 1;

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

and appropriate column in the entity:

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

Note that according to the documentation:

Properties marked as generated must additionally be non-insertable and non-updateable.

So, hibernate will make additional query to populate the auto field after flushing.

   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) You can use @GeneratorType annotation.

You should have an implementation of hibernate ValueGenerator. The simple example you can see below.

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();
   }
}

And then you can use it like this:

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

In this case you should not provide the default value for the column declaration as was required in n1. and the appropriate entity field should not have @Column(... insertable = false, updatable = false). Each time when this entity will be persisted, hibernate generates query:

select nextval('TST_DATA_SEQ')

and populate this value to the auto field.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...