Hiberate生成导致UniqueConstraint违规的@GeneratedValue

时间:2016-11-30 22:29:42

标签: java hibernate

我有使用Hibernate写入Oracle表的代码。它使用SequenceGenerator生成唯一的id。假设我在数据库中有id 1到40。如果从表中删除任何用户,它会在表中的id中留下间隙(例如,id = 24)。然后,当创建新用户时,新用户的id由Hibernate设置为24.

现在有一个问题,因为下一个新用户立即获得id = 25,这会导致UniqueConstraint异常。

我做错了吗?如何使Hibernate停止生成表中已存在的序列值?

@Entity
@Table(name="User")
public class User {
    @Id
    @SequenceGenerator(name="UserGen", sequenceName="UserSeq")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="UserGen")      
    private Integer id; 

    @Column(length=64, unique=true)
    private String username;
...

以下是Oracle中的序列信息:

CREATED 31-OCT-16
LAST_DDL_TIME   31-OCT-16
SEQUENCE_OWNER  USERSERVICE
SEQUENCE_NAME   USERSEQ
MIN_VALUE   1
MAX_VALUE   9999999999999999999999999999
INCREMENT_BY    1
CYCLE_FLAG  N
ORDER_FLAG  N
CACHE_SIZE  20
LAST_NUMBER 81
PARTITION_COUNT 
SESSION_FLAG    N
KEEP_VALUE  N

1 个答案:

答案 0 :(得分:1)

您必须将SequenceGenerator定义为与序列的allocationSize值具有相同的INCREMENT_BY

@SequenceGenerator(name="UserGen", sequenceName="UserSeq", allocationSize = 1)

我之前(在PostgreSQL中)遇到过这个问题,最后我把它改为@GeneratedValue( strategy = GenerationType.IDENTITY )并完全删除了SequenceGenerator,因为它们在未指定时已被用作插入时的默认值。当序列增量大小为1时,这会略微提升性能,因为SequenceGenerator Hibernate会手动调用序列,使用一个可以备用的额外查询。