我有三個表使用PostgreSQL 9.4.5進行設置。刪除了一些細節。JPA /休眠多對多關聯列和可空連接列
Table: component
id | bigint | not null default nextval('component_seq'::regclass) |
Table: file
id | bigint | not null default nextval('file_seq'::regclass) |
Table: component_file
id | bigint | not null default nextval('component_file_seq'::regclass) |
component_id | bigint | not null |
file_id | bigint | |
usage | text | not null |
從本質上講,它與多對多連接表中的附加列是多對多的關係。
- 一個文件可以關聯到一個或多個組件。
- 組件可以關聯到一個或多個文件。
- 組件可能與沒有文件關聯,這就是爲什麼component_file.file_id可爲空。
我已經使用JPA和Hibernate作爲我的實現提供者對此進行了建模。我使用一對多協會(組件和文件),以有機會獲得相關的連接表的元數據和連接表對象表示2個多對一協會(ComponentFile)
public class Component {
...
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "component_seq")
@Column(name = "id", nullable = false, insertable = true, updateable = false)
private Long id;
@OneToMany(mappedBy = "component", cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY, orphanRemoval = true)
private List<ComponentFile> componentFiles;
...
}
public class File {
...
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "file_seq")
@Column(name = "id", nullable = false, insertable = true, updateable = false)
private Long id;
@OneToMany(mappedBy = "file", cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY, orphanRemoval = true)
private List<ComponentFile> componentFiles;
...
}
public class ComponentFile {
...
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "component_id", referencedColumnName = "id", nullable = false, insertable = true, updateable = false)
private Component component;
@ManyToOne(fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "file_id", referencedColumnName = "id", nullable = true, insertable = true, updateable = false)
private File file;
...
}
所有工作正常,除非我有indeterminite插入順序。
如果我插入一個沒有文件的組件(1個組件行和1個組件行),持久性就沒有問題。
如果我插入與單個文件關聯的多個組件(1個組件行,2個文件行,2個component_file行),則會發生錯誤,因爲Hibernate正在插入帶有空file_id引用的component_file行。這會導致違反約束條件,因爲Hibernate正在插入具有相同組件ID和NULL文件ID(不允許使用component_file.component_id,其中component_file.file_id爲NULL)的兩行。
2016-01-26 10:59:30,506 ERROR [SqlExceptionHelper] - Batch entry 1 insert into component_file (usage, component_id, file_id, id) values ('INCLUDED', '180', NULL, '202') was aborted. Call getNextException to see the cause.
2016-01-26 10:59:30,506 WARN [SqlExceptionHelper] - SQL Error: 0, SQLState: 23505
2016-01-26 10:59:30,507 ERROR [SqlExceptionHelper] - ERROR: duplicate key value violates unique constraint "uidx_component_file_component_id" Detail: Key (component_id)=(180) already exists.
2016-01-26 10:59:30,509 ERROR [BatchingBatch] - HHH000315: Exception executing batch [could not execute batch]
2016-01-26 10:59:30,512 INFO [DbConstraintNameRetriever] - Constraint name retrieval results [Name: uidx_component_file_component_id | Original class: java.sql.BatchUpdateException | Message: ERROR: duplicate key value violates unique constraint "uidx_component_file_component_id" Detail: Key (component_id)=(180) already exists. | Postgres exception?: true | Batch update exception?: true].
爲什麼會發生這種情況,以及解決這種類型的關係和持久性的解決方法或替代方法是什麼?
這是我的問題的根源...謝謝。 – user3699312