天天看點

Hibernate JPA —— could not insert 或 detach entity passed to persist 或Found shared references 錯誤

錯誤一:

Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: 

[com.fsnip.tms.core.template.model.Template],

或detach entity passed to persist錯誤。

分析:

檢查主鍵生成政策,判斷級聯增加的資料列是否滿足定義的條件,如非空等。(即兩點:映射是否正确;插入的資料或級聯插入的資料的各列是否滿足限制,如非空等)。

如果是自動生成主鍵值(如自增主鍵),persistent方法前應該設定id為null。

此外,如果定義與資料庫裡面的bigint 類型對應的實體屬性的資料類型為Long 類型,則該值沒有預設值(即使資料庫中指定了預設值),插入資料前必須判斷其是否為null,為null則設定一個預設值0L。否則會出現類似錯誤:ERROR org.hibernate.util.JDBCExceptionReporter - Column 'ISREADONLY' cannot be null

錯誤二:

Found shared references to a collection

分析:

出現此錯誤的原因是實體的關聯關系的集合不能共享(即使為空)。如下假設:

Teacher 實體與Student 實體為關聯關系,且Teacher 與 Student為一對多關系,用Hibernate JPA 在實體類中通過集合展現如下:

1、映射Student 實體中的外鍵列TEACHER_ID:(省去getter、setter方法)

@ManyToOne(cascade={CascadeType.REFRESH,CascadeType.DETACH},optional=false, fetch = FetchType.LAZY)
@JoinColumn(name="TEACHER_ID")
private Teacher teacher;
           

說明:CascadeType.REFRESH 指定當參考的Teacher 實體重新整理時,該Student 實體對象擷取的其Teacher 對象自動重新整理;optional=false 指定TEACHER_ID 在教師表中必須存在;@ManyToOne聲明為多對一關系。

2、在Teacher 實體中定義Student 集合:(省去getter、setter方法)

@OneToMany(cascade={CascadeType.REMOVE},fetch=FetchType.LAZY,mappedBy="teacher")
private Set<Student> students = new HashSet<Student>();
           

經過以上定義後,當我在程式中通過需要複制一個Teacher 實體對象時,不能共享其students集合:

Template temp = old;//假設old是通過JPA 擷取的
Teacher newT = new Teacher();
//修改相關資訊後将新的Teacher 對象插入資料庫
newT.setId(null);//假設主鍵自增
newT.setStudents(temp.getStduents());//執行此語句時不會出錯,但再次查找此newT 或 old 時将提示錯誤二。
//正确做法
newT.setStudents(null);
//如果需為newT增加原來的students 集合資料,則隻能通過JPA 将Student集合資料插入資料庫(因為第2步中隻定義了REMOVE級聯操作)