Hibernate Jpa-主键(序列)上的约束违反异常

时间:2018-11-27 18:16:46

标签: spring multithreading oracle hibernate jpa

我在应用程序中使用了Hibernate JPA。我有一个具有主键(序列)的表。服务将记录插入到该表中。

版本:Oracle 12c

方言:org.hibernate.dialect.Oracle10gDialect

问题:

在负载测试过程中,我们遇到问题(在SEQUENCE键上违反唯一约束)。

问题:

  1. 此问题并非一直存在。但仅在负载测试期间。有人可以检查并帮助使用线程安全生成器吗?

  2. 是DB端序列定义问题还是Java端?

数据库序列:

CREATE SEQUENCE MY_SEQ    
START WITH 1
INCREMENT BY 1
NOMINVALUE
NOMAXVALUE
CACHE 30
NOORDER;

CREATE TABLE MY_TABLE    (  
    MY_PRIMARY_KEY INT default MY_SEQ.nextval NOT NULL,
    VALUE_COL VARCHAR2(10) NULL       
);

实体:

public class MyTableEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "MY_PRIMARY_KEY")
    @GenericGenerator(
        name = "mySequenceGenerator",
        strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
        parameters = {
                @Parameter(name = "sequence_name", value = "SEQUENCE MY_SEQ"),
                @Parameter(name = "increment_size", value = "1")
        }
    )
    @GeneratedValue(generator = "mySequenceGenerator")
    private long myPrimaryKey;

    @Column(name = "VALUE")
    private String value;

}

2 个答案:

答案 0 :(得分:0)

将long更改为Long

因为使用long类型,所以它(默认情况下)为0。不允许任何生成器更改现有值!

https://docs.oracle.com/javaee/7/api/javax/persistence/GeneratedValue.html

答案 1 :(得分:0)

Oracle 10方言

对于 Oracle10gDialect ,请使用此配置

@Id
@Column(name = "MY_PRIMARY_KEY")
@GeneratedValue(strategy=GenerationType.AUTO)
Long myPrimaryKey;

Hibernate创建一个表和一个序列:

create table MY_TABLE (
MY_PRIMARY_KEY number(19,0) not null, 
VALUE varchar2(255 char), 
primary key (MY_PRIMARY_KEY))

create sequence hibernate_sequence 

首先存储它,然后获得新的序列ID,然后将其传递到INSERT语句中

select hibernate_sequence.nextval from dual
insert into MY_TABLE (VALUE, MY_PRIMARY_KEY) values (?, ?)

Oracle 12方言

如果您使用本机支持IDENTITY column Oracle 12 ,则最好升级到 Oracle12cDialect (请注意,这需要Hibernate 5.3)

strategy设置为GenerationType.IDENTITY

@Id
@Column(name = "MY_PRIMARY_KEY", updatable = false, nullable = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
Long myPrimaryKey;

将创建下表-重要的部分是generated as identity,它提供了独特的风格。 请注意,不需要创建显式sequence,而是在内部对其进行管理。

create table MY_TABLE (
MY_PRIMARY_KEY number(19,0) generated as identity, 
VALUE varchar2(255 char), 
primary key (MY_PRIMARY_KEY))

虽然存储未在INSERT中传递任何ID ,但该ID由Oracle分配并返回到会话

insert into MY_TABLE (VALUE) values (?) RETURNING MY_PRIMARY_KEY INTO ? 

请注意,与Oracle 10相反,您节省了一次往返数据库的时间。