jpa Spring启动测试schema.sql/data.sql约束冲突错误

inkz8wg9  于 2022-11-14  发布在  Spring
关注(0)|答案(4)|浏览(259)

我的src/test/resources中有一个模式中的sql-h2.sql

CREATE TABLE IF NOT EXISTS project.general_types(
  id SMALLINT PRIMARY KEY NOT NULL,
  name VARCHAR(15) NOT NULL);

我的data.sql包含以下内容

INSERT INTO project.general_types(id, name) VALUES 
   (0, 'Text'),
   (1, 'Binary');

application-test.yml

spring:
  datasource:
    url: jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_UPPER=false;
    username: sa
    password: 
    driver-class-name: org.h2.Driver
    initialization-mode: always
    platform: h2    
  jpa:
    generate-ddl: false
    defer-datasource-initialization: true
    show-sql: true
    open-in-view: false
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        format_sql: true
        default_schema: project
        dialect: org.hibernate.dialect.H2Dialect  
        globally_quoted_identifiers: true

Map这个的实体。

@Entity(name = "general_types")
public class GeneralTypesEntity {

  @Id
  private short id;
  @Basic
  private String name;

//getters/setters nor shown...
}

测试用例

@SpringBootTest
@ActiveProfiles("test")
class GeneralTypesDbTest {

  @Autowired
  private final GeneralTypesRepository generalTypesRepository = null;

  @Test
  void test() {

    assertNotNull(generalTypesRepository);
    assertEquals(2, generalTypesRepository.count());
  }

}

在PostgreSQL的生产环境中,这是可行的(预构建的数据库和所有的存储库、实体等)。我现在尝试使用h2设置一个Sping Boot 测试。如果我只使用schema.sql运行,它构建得很好,并运行测试。
使用insert语句添加data.sql以创建默认数据集,执行时出现Spring错误

Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PRIMARY KEY ON project.general_types(id) [0, 'Text']"; SQL statement:
INSERT INTO project.general_types(id, name) VALUES (0, 'Text'), (1, 'Binary') [23505-200]
   at org.h2.message.DbException.getJdbcSQLException(DbException.java:459) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.mvstore.db.MVPrimaryIndex.add(MVPrimaryIndex.java:127) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.mvstore.db.MVTable.addRow(MVTable.java:531) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.dml.Insert.insertRows(Insert.java:195) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.dml.Insert.update(Insert.java:151) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.CommandContainer.update(CommandContainer.java:198) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.Command.executeUpdate(Command.java:251) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:228) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:201) ~[h2-1.4.200.jar:1.4.200]
   at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) ~[HikariCP-4.0.3.jar:na]
   at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-4.0.3.jar:na]
   at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:261) ~[spring-jdbc-5.3.18.jar:5.3.18]
   ... 96 common frames omitted

我试着在表创建后立即将Insert插入schema-h2.sql,但得到了同样的错误。知道约束冲突是如何引起的吗?对于一个没有自动增量的新创建表,我不清楚为什么插入会引起约束冲突。

hrysbysz

hrysbysz1#

到今天早上,它已经开始工作了,我不知道为什么。我会列出做了什么,也许有人可以澄清为什么它会在12小时后开始工作。
由于data.sql导致了重复键的问题,我将其重命名为data-disabled. yml。(statement="”)来插入项目,而测试使用GeneralTypesRepository来findByName(字符串)(我尝试测试的方法)。通过构建H2 DB,该方法成功运行(schema.sql),使用@Sql插入1项(0,“Text”),然后检查该方法是否可以找到“Text”的记录。这通过了。很好。
使用此方法为其他存储库构建了一些测试(总共大约8个)(每个测试方法上使用@Sql)。
今天早上,当我看到更多信息的请求时,我创建了一个新的测试文件来复制重做我的原始测试。我将data-disabled.sql重命名为data.sql。运行测试,它通过了。没有异常,junit绿色。
我回到了我昨晚创建的另一个测试,删除了所有的@Sql行,运行了测试,它们都通过了。
没有做其他的修改(用git确认过)。我不知道为什么它开始工作了。这个测试现在和我最初预期的一样工作,因为data.sql是唯一一个插入的地方。
非常感谢几位提供更多信息的人。很抱歉,我一开始就没有这些信息。很抱歉,这并没有给予最初的问题一个明确的答案,但我再次非常肯定,拥有一个data.sql文件只会运行一次,并使用模式进行插入,创建没有插入的数据库。

rjjhvcjd

rjjhvcjd2#

我朋友,
如果你能抛出Entity类就好了。但是我以前也有过类似的错误,我在Entity类中解决了我的问题。如果你使用@GeneratedValue,你应该选择正确的策略。参考:baeldung.com/hibernate-identifiers
这是为我解决问题的代码。@Id @GeneratedValue(strategy = GenerationType.AUTO)@Column(name =“ID”)private Long id;
此外,建议在data.sql文件中进行所有sql查询

jq6vz3qz

jq6vz3qz3#

显示测试类会很有帮助,因为它会显示数据脚本被执行了两次

qoefvg9y

qoefvg9y4#

今天我遇到了一个类似的失败案例,并能够弄清楚是什么导致了它。把这个放在这里,以帮助其他人在未来。
基本上,我正在进行测试,然后在添加了一个@ PostConstruct之后,我的一个DB测试开始失败。PostConstruct方法执行了一个DB调用,以获取最新的记录作为缓存。
这里的问题是在Spring应用程序上下文启动期间将调用@ PostConstruct。这导致在Spring测试有机会使用测试资源文件初始化DB之前发生DB调用。改为在第一次使用时构建该高速缓存,现在问题解决了。另一个选项可能是更改为@EventListener(ApplicationReadyEvent.class),让它在完全载入应用程序内容之后启动。

相关问题