2016-11-30 25 views
0

我有使用Hibernate写入Oracle表的代码。它使用SequenceGenerator生成唯一的ID。假设我在数据库中有ID从1到40。会发生什么情况是,如果有任何用户从表中删除,它会在表中的ID中留下空隙(例如,id = 24)。然后,当创建新用户时,新用户的ID由Hibernate设置为24.Hiberate生成@GeneratedValue,导致UniqueConstraint违反

现在有一个问题,因为紧接着的下一个新用户获得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

您的诊断错误。该序列不关心表中ID的空位。这只是一个序列,每次请求下一个值时都会递增。您只需用最小值初始化您的序列,这会使生成器生成已在表中用作ID的值。 –

+0

你说得对。我确实诊断错了。真正的问题是这样的:http://stackoverflow.com/questions/9861416/hibernate-generates-negative-id-values-when-using-a-sequence – leontp587

回答

0

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

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

我遇到这个问题之前(在PostgreSQL的),最终我只是把它改为@GeneratedValue(strategy = GenerationType.IDENTITY)和完全删除SequenceGenerator S,因为他们没有指定的时候已经用作插入默认值。当序列增量大小为1时,性能略有提升,因为Hibernate通过SequenceGenerator手动调用序列,并使用一个可以省略的额外查询。

+0

同意。分配大小= 1。这对我有效。 需要注意的是,对于Oracle。不支持GenerationType.IDENTITY: 根据:http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing “身份排序使用数据库中的特殊IDENTITY列来允许数据库自动为其分配一个ID对象,当它的行被插入时,许多数据库(如MySQL,DB2,SQL Server,Sybase和Postgres)都支持标识列,Oracle不支持IDENTITY列,但可以通过使用序列对象和触发器来模拟它们。 – leontp587