Home > Enterprise >  Spring Boot Test schema.sql/data.sql contraint violation error
Spring Boot Test schema.sql/data.sql contraint violation error

Time:08-25

I have the following sql in a schema-h2.sql in my src/test/resources

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

My data.sql has the following

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

The entity that maps this.

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

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

//getters/setters nor shown...
}

Test case

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

  @Autowired
  private final GeneralTypesRepository generalTypesRepository = null;

  @Test
  void test() {

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

}

With PostgreSQL in production this works (prebuilt db and all the repos, entities, etc...). I'm now trying to setup a Spring Boot test with h2. If I run with just the schema.sql it builds fine and runs the test.

Adding the data.sql with the insert statement to create the default data set, Spring errors with the execution

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

I tried putting the Insert into the schema-h2.sql right after table creation and get the same error. Any ideas how a constraint violation is being caused. For a newly create table with no auto increment I'm unclear why an insert would be causing a constraint violation.

CodePudding user response:

my friend,

It would be good if you can throw the Entity class. But I had a similar error before, I solved my problem in the Entity class. If you are using @GeneratedValue, you should choose the right strategy. A reference: baeldung.com/hibernate-identifiers

This is the code that solved the problem for me. @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") private Long id;

Also a recommendation is to make all sql queries in the data.sql file

CodePudding user response:

It would helpful to show your test class as it would appear your data script is being executed twice

CodePudding user response:

As of this morning, it's now working and I have no idea why. I'll list out what was done and maybe someone can clarify why it would have started to work 12 hours later.

Since the data.sql was causing the duplicate key issue, I renamed it to data-disabled.yml. I then changed the test to using the @Sql( statement="" ) to insert an item and the test used the GeneralTypesRepository to findByName(string) (the method I was trying to test). This ran successfully by building the H2 DB (schema.sql), used the @Sql to insert 1 item (0, "Text") and then checked the method could find the record for "Text". This passed. Great.

Built out a few more tests for other repositories (about 8 in total) using this method (@Sql on each test method).

This morning when I saw the request for more information, I created a new test file to copy redo my original test. I renamed the data-disabled.sql back to data.sql. Ran the test and it passed. No exceptions and junit green.

I went back to the other test I created last night, removed all the @Sql lines, ran the test and they all passed.

No other changes were done (confirmed with git). I don't know why it started working. This test is now working as I expected it to in the first place since the data.sql was the only place inserts were being done.

Thanks to the few who pushed for more information. Sorry I didn't have it in the first place. And sorry this doesn't give a definitive answer to the original issue but again I was pretty sure having a data.sql file would only run once and do the inserts with the schema creating the db with no inserts.

  • Related