![](/img/trans.png)
[英]spring boot is executing data.sql and schema.sql twice?
[英]Spring Boot Test schema.sql/data.sql contraint violation error
我的 src/test/resources 中的 schema-h2.sql 中有以下 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');
應用測試.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
映射它的實體。
@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 設置 Spring 啟動測試。 如果我僅使用 schema.sql 運行,它可以正常構建並運行測試。
將data.sql與insert語句相加,創建默認數據集,執行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 並得到相同的錯誤。 關於如何導致約束違規的任何想法。 對於沒有自動遞增的新創建的表,我不清楚為什么插入會導致違反約束。
我的朋友,
如果你能拋出 Entity class 就好了。 但是我之前也遇到過類似的錯誤,我在 Entity class 中解決了我的問題。 如果您使用@GeneratedValue,您應該選擇正確的策略。 參考:baeldung.com/hibernate-identifiers
這是為我解決問題的代碼。 @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") private Long id;
另外一個建議是在 data.sql 文件中進行所有 sql 查詢
顯示您的測試 class 會有所幫助,因為您的數據腳本似乎正在執行兩次
截至今天早上,它現在正在工作,我不知道為什么。 我會列出所做的事情,也許有人可以澄清為什么它會在 12 小時后開始工作。
由於 data.sql 導致重復密鑰問題,我將其重命名為 data-disabled.yml。 然后我將測試更改為使用 @Sql( statement="" ) 插入項目,並且測試使用 GeneralTypesRepository 來 findByName(string) (我試圖測試的方法)。 這通過構建 H2 DB (schema.sql) 成功運行,使用 @Sql 插入 1 項(0,“Text”),然后檢查該方法是否可以找到“Text”的記錄。 這過去了。 偉大的。
使用此方法(每個測試方法上的@Sql)為其他存儲庫(總共大約 8 個)構建了更多測試。
今天早上,當我看到更多信息的請求時,我創建了一個新的測試文件來復制重做我原來的測試。 我將 data-disabled.sql 重命名為 data.sql。 運行測試,它通過了。 沒有例外,junit 綠色。
我回到昨晚創建的另一個測試,刪除了所有@Sql 行,運行測試,它們都通過了。
沒有進行其他更改(通過 git 確認)。 我不知道為什么它開始工作。 這個測試現在正如我預期的那樣工作,因為 data.sql 是唯一完成插入的地方。
感謝推動更多信息的少數人。 對不起,我一開始就沒有。 抱歉,這並沒有對原始問題給出明確的答案,但我再次非常確定有一個 data.sql 文件只會運行一次,並使用創建數據庫的架構進行插入,而無需插入。
今天我有一個類似的失敗案例,並且能夠找出導致它的原因。 把它放在這里是為了將來幫助其他人。
基本上我進行測試,然后在添加 @PostContruct 之后我的一個數據庫測試開始失敗。 PostContruct 方法進行了數據庫調用以獲取最新記錄作為緩存。
這里的問題是 @PostContruct 將在 Spring App Context 啟動期間被調用。 這導致在 Spring 測試有機會使用測試資源文件初始化數據庫之前發生數據庫調用。 更改為在首次使用時構建緩存,現在問題消失了。 另一種選擇可能是更改為 @EventListener(ApplicationReadyEvent.class) 以使其在完全加載后在應用程序上下文之后啟動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.