我正在嘗試在 spring 中構建一個資料模型,該模型通過一對多關系向下級聯多達 3 個級別,但我無法讓它與 liquibase 腳本一起使用。
我正在使用帶有 Kotlin 的 Spring Boot 和帶有 PostgreSQL 資料庫的 liquibase。
到目前為止我做了什么:
- 減少代碼以只包含不起作用的部分(見下文)
- 我嘗試了@OneToMany 和@JoinTable 以及@JoinColumn,我也嘗試了@ManyToMany 以排除@OneToMany 的問題
- 我在沒有 liquibase 的情況下運行了相同的代碼(如下),讓 Hibernate/JPA 從模型創建表
- 這確實有效,所以我從這些表中生成了 liquibase 腳本,但它們看起來和我自己的完全一樣(除了鍵名)
- 使用這些模型檢索資料有效(如果我直接通過 SQL 插入資料)
老實說,我不確定問題是出在模型、配置還是 liquibase 腳本中,所以我會發布所有這些。我缺少配置嗎?我是否正確配置了級聯?我的模型定義/liquibase 腳本是否錯誤?
我保存父母的例外是:
Hibernate: insert into parent (name) values (?)
2021-12-15 23:29:16.797 WARN 14115 --- [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 23502
2021-12-15 23:29:16.798 ERROR 14115 --- [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: null value in column "id" of relation "parent" violates not-null constraint
Detail: Failing row contains (null, Test 1).
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [id" of relation "parent]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "id" of relation "parent" violates not-null constraint
Detail: Failing row contains (null, Test 2).
我試圖運行的代碼:
val parent = Parent(
id = 0,
name = "Test 2"
).apply {
children = mutableSetOf(
Child(
id = 0,
name = "Test 21",
parent = this
).apply {
grandchildren =
mutableSetOf(
Grandchild(
id = 0,
name = "Test 211",
child = this
)
)
},
Child(
id = 0,
name = "Test 22",
parent = this
)
)
}
val saveParent: Parent = parentRepository.save(parent)
楷模:
@Entity
class Parent(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
var name: String,
@OneToMany(mappedBy = "parent", cascade = [CascadeType.ALL])
var children: MutableSet<Child> = mutableSetOf()
)
@Entity
class Child(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
var name: String,
@ManyToOne @JoinColumn(name = "child_id")
var parent: Parent,
@OneToMany(mappedBy = "child", cascade = [CascadeType.ALL])
var grandchildren: MutableSet<Grandchild> = mutableSetOf()
)
@Entity
class Grandchild(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
var name: String,
@ManyToOne @JoinColumn(name = "child_id")
var child: Child
)
應用程式.yml
spring:
datasource:
platform: postgres
url: jdbc:postgresql://localhost:5432/onetomany?ssl=false
driver-class-name: org.postgresql.Driver
initialization-mode: always
jpa:
database: postgresql
database-platform: org.hibernate.dialect.PostgreSQLDialect
generate-ddl: false
hibernate:
ddl-auto: none
liquibase:
enabled: true
change-log: classpath:db/master.xml
liquibase 腳本:
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet author="bruce (generated)" id="data-1">
<createTable tableName="parent">
<column name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_PARENT"/>
</column>
<column name="name" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet author="bruce (generated)" id="data-2">
<createTable tableName="child">
<column name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_CHILD"/>
</column>
<column name="name" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="parent_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet author="bruce (generated)" id="data-3">
<createTable tableName="grandchild">
<column name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_GRANDCHILD"/>
</column>
<column name="name" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="child_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet author="bruce (generated)" id="data-6">
<addForeignKeyConstraint baseColumnNames="parent_id" baseTableName="child" constraintName="FK_CHILD_PARENT"
deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT"
referencedColumnNames="id" referencedTableName="parent" validate="true"/>
</changeSet>
<changeSet author="bruce (generated)" id="data-8">
<addForeignKeyConstraint baseColumnNames="child_id" baseTableName="grandchild" constraintName="FK_CHILD_GRANDCHILD"
deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT"
referencedColumnNames="id" referencedTableName="child" validate="true"/>
</changeSet>
</databaseChangeLog>
uj5u.com熱心網友回復:
@GeneratedValue(strategy = GenerationType.IDENTITY)通常通過在資料庫中指定自動遞增的默認值來作業,例如nextval('my_entity_sequence'::regclass). 插入時,DB 將生成識別符號。
在 Postgres 中,有serial/bigserial偽型別來指定自動增量列(它將在內部創建序列以及列默認值),因此 DDL 可能如下所示:https :
create table my_entity ( id bigserial not null, primary key (id) )
//www.postgresql.org /docs/current/datatype-numeric.html
在您的情況下,liquibase 錯過了所有 ID 列的型別/默認值(現在只是“父”插入失敗,但其他物體的插入也會失敗)。
這是一個已知的 liquibase 問題:https : //github.com/liquibase/liquibase/issues/1009 - 解決它的建議包括autoIncrement="true"在變更集中手動指定。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/383390.html
