【问题标题】:Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.xxx"; SQL statement唯一索引或主键违规:“PRIMARY KEY ON PUBLIC.xxx”; SQL 语句
【发布时间】:2019-09-28 00:30:54
【问题描述】:

每当我的应用程序启动时,我都会收到以下错误消息:

Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.SERMON_SESSION(ID)"; SQL statement:
INSERT INTO SERMON_SESSION (id, session_enum) VALUES ('1', 'SUN_MRN'), ('2', 'SUN_EVE'), ('3', 'TUE_BIB'), ('4', 'FRI_BIB'), ('5', 'WKD_CNF') [23505-197]

我该如何解决这个问题?我必须自己分配讲道会话 ID,因为它在后面的专栏中使用。

application.properties

spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:mem:erc;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.initialization-mode=embedded
spring.jpa.properties.hibernate.hbm2ddl.import_files=classpath://resources/data.sql
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor=org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
logging.level.com.erc.api.*=DEBUG
logging.level.org.hibernate=OFF
logging.level.org.hibernate.SQL=INFO
logging.level.org.hibernate.type.descriptor.sql=INFO
logging.level.org.jaudiotagger=WARN
spring.servlet.multipart.max-file-size=60MB
spring.servlet.multipart.max-request-size=60MB
application.sermon_path=classpath://resources/files/sermons/}

SermonSession.java

@Table(name = "sermon_session", uniqueConstraints = @UniqueConstraint(columnNames = {"id", "sessionEnum"}))
@Entity
public class SermonSession {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false, unique = true)
    private int id;
    @Enumerated(EnumType.STRING)
    @Column(unique = true)
    private SessionEnum sessionEnum;

    public SermonSession(String session) {
        setSessionEnum(session);
    }

    public SermonSession() {
        this.sessionEnum = null;
    }

    public String toString() {
        return String.format("{ id: %d, session_enum: %s }", getId(), getSessionEnum());
    }

    String getSessionEnum() {
        return this.sessionEnum.getSession();
    }

    private void setSessionEnum(String session) {
        this.sessionEnum = SessionEnum.fromSession(session);
    }

    private int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

data.sql

INSERT INTO SERMON_SESSION (id, session_enum)
VALUES ('1', 'SUN_MRN'),
       ('2', 'SUN_EVE'),
       ('3', 'TUE_BIB'),
       ('4', 'FRI_BIB'),
       ('5', 'WKD_CNF');

将 data.sql 更改为:

INSERT INTO SERMON_SESSION (session_enum)
VALUES ('SUN_MRN'),
       ('SUN_EVE'),
       ('TUE_BIB'),
       ('FRI_BIB'),
       ('WKD_CNF');

产生以下错误消息:

Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "UK_AA7KWY8HO9GLHF1VI4HDB61X8_INDEX_8 ON PUBLIC.SERMON_SESSION(SESSION_ENUM) VALUES ('SUN_MRN', 1)"; SQL statement:
INSERT INTO SERMON_SESSION (session_enum) VALUES ('SUN_MRN'), ('SUN_EVE'), ('TUE_BIB'), ('FRI_BIB'), ('WKD_CNF') [23505-197]

【问题讨论】:

  • INSERT INTO SERMON_SESSION (id, session_enum) VALUES ('1', 'SUN_MRN') 也会插入 id。至少它试图这样做......看看id 的列定义。它可以配置为UNIQUE和/或AUTO INCREMENT,这意味着数据库将处理id,您只需插入剩余列的值(INSERT INTO SERMON_SESSION (session_enum) VALUES ('SUN_MRN'));
  • 嗨@deHaar,非常感谢您的回复。请看更新
  • 嗯...这个('SUN_MRN', 1) 有点可疑,因为与您的第一次尝试相比,值的顺序显然是相反的。能否提供表或列id的定义?
  • 嗨,表的定义如上:SermonSession.java可以在问题中看到,枚举在这里:pastebin.com/E6eMuW7u
  • @methuselah 那里有什么进展吗?我正在尝试做同样的事情并获得相同的JdbcSQlException

标签: java spring h2


【解决方案1】:

@GeneratedValue(strategy = GenerationType.IDENTITY) 将允许自动生成唯一 ID,无需自己放置。

以下应该足够了

DELETE FROM SERMON_SESSION;
INSERT INTO SERMON_SESSION (session_enum)
VALUES ('SUN_MRN'),
       ('SUN_EVE'),
       ('TUE_BIB'),
       ('FRI_BIB'),
       ('WKD_CNF');

【讨论】:

  • 我已经尝试过了,现在收到错误消息:Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "UK_AA7KWY8HO9GLHF1VI4HDB61X8_INDEX_8 ON PUBLIC.SERMON_SESSION(SESSION_ENUM) VALUES ('SUN_MRN', 1)"; SQL statement: INSERT INTO SERMON_SESSION (session_enum) VALUES ('SUN_MRN'), ('SUN_EVE'), ('TUE_BIB'), ('FRI_BIB'), ('WKD_CNF') [23505-197]
  • @methuselah 你enum 长什么样子?对我来说,枚举列也应该是独一无二的,这让我闻起来很腥......
  • @methuselah 在插入值之前尝试截断表。我刚刚编辑了我的答案
  • 我试过这个并得到错误:org.h2.jdbc.JdbcSQLException: Cannot truncate "PUBLIC.SERMON_SESSION"; SQL statement: TRUNCATE TABLE SERMON_SESSION [90106-197]
  • @methuselah 你可能对它有限制。试试下面的DELETE FROM SERMON_SESSION
【解决方案2】:

我最近遇到了类似的问题。问题可能是,当您没有正常关闭应用程序时(您没有向端点发布消息以关闭应用程序),会话管理器可能没有机会执行删除(请参阅本主题:Spring boot ddl auto generator)。

我们找到的解决方案是手动删除数据库并更改

spring.jpa.hibernate.ddl-auto=create

spring.jpa.hibernate.hbm2ddl.auto=create

为什么会这样?我还在等answer这里。

【讨论】:

  • 我试过这个并得到错误:org.h2.jdbc.JdbcSQLException: Cannot truncate "PUBLIC.SERMON_SESSION"; SQL statement: TRUNCATE TABLE SERMON_SESSION [90106-197]
【解决方案3】:

对我来说,我收到了完全相同的错误消息。它并没有影响我的 CRUD 操作,但仍然很烦人。我跟着this article 解决了这个错误。

TLDR

要解决此问题,请将主键列值作为唯一而不是 NULL。只需在 DDL 末尾添加 NOT NULL UNIQUE

【讨论】:

    猜你喜欢
    • 2021-01-23
    • 2017-04-28
    • 2014-12-27
    • 2019-12-24
    • 2021-05-19
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 2021-08-16
    相关资源
    最近更新 更多