2016-01-26 75 views
0

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

從本質上講,它與多對多連接表中的附加列是多對多的關係。

  1. 一個文件可以關聯到一個或多個組件。
  2. 組件可以關聯到一個或多個文件。
  3. 組件可能與沒有文件關聯,這就是爲什麼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]. 

爲什麼會發生這種情況,以及解決這種類型的關係和持久性的解決方法或替代方法是什麼?

回答

0

嘗試添加:

cascade = { CascadeType.PERSIST, CascadeType.MERGE } 

的組件和ComponentFile文件@ManyToOne註解。

+0

這是我的問題的根源...謝謝。 – user3699312

0

既然你已經在OneToMany註解指定mappedBy屬性,請確保您也可以通過調用ComponentFile.setComponent(...)ComponentFile.setFile(...)適當每當你在ComponentFile實體添加ComponentFile到ArrayList設置關係的另一端。

如果您仍然看到相同的錯誤,或者您已經在使用它,發佈實體創建和關聯邏輯將有所幫助。