【问题标题】:In Spring Boot JPA, why would I get "Table already exists; SQL statement:"在 Spring Boot JPA 中,为什么我会得到“表已存在;SQL 语句:”
【发布时间】:2018-09-22 00:20:45
【问题描述】:

我正在使用 JPA 存储库构建一个 Spring Boot 项目。对于测试,我使用 H2 内存数据库。我用一个schema.sql文件初始化数据库,摘录如下:

CREATE TABLE `config_user_preset_dataclass` (
  `user_preset_dataclass_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_preset_id` int(11) NOT NULL,
  `dataclass_name` varchar(100) NOT NULL,
  `ngdp_audit_timestamp` datetime NOT NULL,
  `ngdp_update_timestamp` datetime NOT NULL, 
  PRIMARY KEY (`user_preset_dataclass_id`),
  UNIQUE KEY `idx_config_user_preset_dataclass_1` (`user_preset_id`,`dataclass_name`),
  CONSTRAINT `fk_config_user_preset_dataclass_1` FOREIGN KEY (`user_preset_id`) REFERENCES `config_user_preset` (`user_preset_id`)
);

通过将数据库 URL 设置为 DB_URL=jdbc:h2:mem:data360;INIT=RUNSCRIPT FROM 'classpath:schema.sql';DATABASE_TO_UPPER=false 来连接 schema.sql 以初始化数据库,并且我已经验证这是正常的。

在我的src/test/resources/application.properties 中,我设置了spring.jpa.hibernate.ddl-auto=validate,因此不应该有任何二次尝试来生成表。但是,当我运行一个简单的测试来保存 JPA 模型时,我得到:

2018-04-11 17:59:17.847 ERROR 11540 --- [o-auto-1-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : Table "CONFIG_USER_PRESET" already exists; SQL statement:
CREATE TABLE `config_user_preset` (
  `user_preset_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(6) NOT NULL,
  `preset_name` varchar(200) NOT NULL,
  `ngdp_audit_timestamp` datetime NOT NULL,
  `ngdp_update_timestamp` datetime NOT NULL,
  PRIMARY KEY (`user_preset_id`),
  UNIQUE KEY `idx_user_preset_config_1` (`user_id`,`preset_name`)
) [42101-196]

错误清楚地表明某些东西正在尝试再次生成表。

会是什么?

有趣的是,如果我使用 GenerationType.IDENTITY 作为主键,这个错误就会消失。但是,这会导致另一个问题,所以我不能这样做。

[编辑]

@Entity
@Table(name = "config_user_preset_dataclass")
public class UserPresetDataclass {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_preset_dataclass_id")
    private long presetDataClassId;

    @Column(name = "user_preset_id")
    private long userPresetId;

    @Column(name = "dataclass_name")
    private String dataclassName;

...

[/编辑]

【问题讨论】:

  • SpringBoot 有一个复杂的机制来检查数据库的类型、hibernate/jpa 属性等,并决定是否使用 sql 脚本初始化数据库。我们只需要配置 spring.datasource.initialization-mode 就可以了。只是想知道为什么要使用 INIT=RUNSCRIPT FROM 'classpath:schema.sql' 而不是使用开箱即用的功能?
  • 在您的src/main/resources/application.properties 中您的属性spring.jpa.hibernate.ddl-auto 是否设置为update
  • 我正在使用 INIT=RUNSCRIPT 的东西,因为初始化模式不起作用,开箱即用的东西也不起作用。我公司糟糕的弹簧靴包装中可能有什么东西破坏了它。
  • 我遇到了同样的问题(schema.sql 执行了两次),我刚刚做了一个 Maven 更新,错误就消失了。

标签: java spring hibernate spring-boot jpa


【解决方案1】:

可能您的数据库仍在内存中,这就是您收到此错误的原因。 我提出了两种选择:

  1. 更改 SQL 语句。 您可以使用 CREATE TABLE IF NOT EXISTS config_user_preset ... 而不是 CREATE TABLE config_user_preset...
  2. 如果您使用的是 Spring,则可以创建嵌入式数据库。在这里查看Spring embeddeb db table already exists error

【讨论】:

    猜你喜欢
    • 2018-03-21
    • 2020-07-04
    • 2015-05-01
    • 1970-01-01
    • 2022-07-24
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多