3

I am testing a Spring Boot Batch Application. I am using a in memory H2 DB that I would like to initialize with some data but its failing with a Unique index or primary key violation: PRIMARY_KEY_7 ON ....

I have tried tweaking the application.properties, adding and removing

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.default_schema=AD1

Also tweaking the spring.datasource.url.

The entity is as follows:

@Table(schema = "ad1",name = "Student")
public class Student {

    @Id
    @Column(name = "student_id")
    private String studentId;

    @Column(name = "student_name")
    private String studentName;

    @Column(name = "favourite_subject")
    private String favouriteSubject;

    @Column(name = "enrollment_date")
    private LocalDate enrollmentDate;

}

To note is that the schema attribute has been set to ad1

data-h2.sql which lives in src/test/resources is as follows:

Insert into ad1.Student (student_id,student_name,favourite_subject,enrollment_date) values ('1151AB26','John','Math',to_date('01-JAN-19','DD-MON-RR'));

application.properties also in src/test/resources is as follows:

spring.datasource.platform=h2
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS AD1
spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.default_schema=AD1
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

spring.batch.job.enabled=false

To note, is that spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS AD1. I had to initialize the schema to AD1

I am using Cucumber so I have a a cucumber test class:

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources", plugin = { "pretty", "html:target/cucumber" })
public class CucumberTest {

}

Last but not least the Spring boot test class

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = StudentBatchApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration
public abstract class SpringCucumberIntegrationTest {

What happens is that when I start up the test I get the following:

Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_7 ON AD1.Student(student_id) VALUES ('1151AB26', 1)"; SQL statement:
Insert into AD1.Student (student_id,student_name,favourite_subject,enrollment_date) values ('1151AB26','John','Math',to_date('01-JAN-19','DD-MON-RR')) [23505-197]

When I troubleshoot this, by putting a break-point at the moment the initialization is happening, the process runs the same line twice:

( /* key:1 */ '1151AB26', 'John', 'Math', TIMESTAMP '2019-01-01 00:00:00')
( /* key:2 */ '1151AB26', 'John', 'Math', TIMESTAMP '2019-01-01 00:00:00')

Right after this, it throws the exception.

1 Answer 1

4

As I mentioned, in the process of troubleshooting I noticed that the one line inside data-h2.sql was somehow being ran twice and hence giving this Unique index violation. Troubleshooting further, I traced back to the point in the process where it was loading the data script (ie. data-h2.sql) and noticed that it was loading this script twice. Once in target\classes\data-h2.sql and once in target\test-classes\data-h2.sql. I honestly don't know why this script file was being copied to target\classes\data-h2.sql.

In the end I found that this was an eclipse issue. When I ran the tests using command-line mvn clean test. The tests ran perfectly, but when I ran the tests with eclipse Run As -> JUnit Test I would encounter this problem. For some reason whenever I cleaned the application in eclipse Project -> Clean it copied all the resource files from src/main/resources and src/test/resources into target\classes. What I had to do was add the following line to my .classpath file.

<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
    <attributes>
        <attribute name="maven.pomderived" value="true"/>
        <attribute name="test" value="true"/>
    </attributes>
</classpathentry>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.