我有三个表使用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