我有一個JPA @Entity定義爲冬眠無法與空刪除@Entity @Version
private Timestamp lastModified;
@Version
@Column(name = "f_lastmodified")
@Attribute(required = false)
public Timestamp getLastModified() {
return lastModified;
}
在所得列定義爲
private UUID id;
@Id
@Column(name = "f_id")
@GeneratedValue(generator = "system-uuid")
@Type(type = "pg-uuid")
public UUID getId() {
return id;
}
一個@Id和@Version字段postgres(由使用create-drop的休眠生成)是「沒有時區的時間戳」。 這個類用於在postgres上運行的應用程序。刪除實體時,我用下面的代碼:
public T delete(UUID id) {
log.debug("deleting entity {}", id);
EntityManager em = ... //get from somewhere
em.flush(); //make sure we're in sync with DB
T object = em.find(getClassType(), id); //get latest version
if (object == null) {
throw new IllegalStateException("could not find an entity with id "+id);
}
em.refresh(object);
em.remove(object);
em.flush();
return object;
}
它曾經是一個簡單的發現(類型,編號)+刪除,但我已經添加了一些額外的絨毛設法得到它的工作。問題是上述代碼不起作用。在日誌中顯示的錯誤是:
08:25:15,940 INFO [STDOUT] Hibernate:
08:25:15,950 INFO [STDOUT] delete
08:25:15,950 INFO [STDOUT] from
08:25:15,950 INFO [STDOUT] dpa.filesystem_status
08:25:15,950 INFO [STDOUT] where
08:25:15,950 INFO [STDOUT] f_id=?
08:25:15,960 INFO [STDOUT] and f_lastmodified=?
08:25:45,123 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session: org.hibernate.StaleObjec
tStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [FilesystemStatus#78c839f0-0b12-4df6-b9ec-ac1e52e9b1f1]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1950) [:3.6.1.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2710) [:3.6.1.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2911) [:3.6.1.Final]
一些調試,我想我找到了問題的根源後:我試圖刪除該實體擁有的版本字段NULL。 hibernate爲刪除(在上面的日誌片段中打印)建立一個準備好的語句,正確設置id,然後爲版本字段設置NULL(邏輯上也是正確的)。這樣做的休眠代碼是在BasicBinder.java 78行(休眠核心3.6.1)
st.setNull(index, sqlDescriptor.getSqlType());
第二個參數在運行時解析爲93。最終,運行準備好的語句導致0行被刪除,並且休眠狀態假定它是因爲「f_lastmodified =?」部分不匹配,並決定有人必須提交一個不同的時間戳之間(==陳舊的實體傳遞給刪除)。這不是真的。
我該如何繼續?
更具體地說:
1.我如何知道93是否是傳遞給setNull()的正確的sql類型?我在哪裏可以找到一個「正確」的SQL類型表?它是數據庫特定的(這意味着我應該去看看postgres文檔)或一些JDBC標準?
2.我該如何解決該問題?我不能保證無空的@Version列,所以我需要這種情況下工作
3.這是一個已知的hibernate/postgresql-jdbc驅動程序問題,我錯過了?
IM使用JDK對Win7的X64 1.6u24 64時,JBoss 6.1快照,休眠3.6.1.final,9.0 Postgres的,Postgres的jdbc4司機9.0-801
正確,其外部應用程序 – radai 2011-05-29 08:16:56
對不起,解決方案是「沒有解決方案」...您需要編寫自己的查詢來更新實體,如果您使用它們,您可能需要禁用級聯。我有一個處於類似情況的同事,他的團隊決定使用ibatis,在頂層使用薄層而不是hibernate,因爲這個和其他一些限制。 – Augusto 2011-05-29 19:15:43
我已經提出這個作爲一個休眠的bug,讓我們希望它在未來的版本中得到修復: http://opensource.atlassian.com/projects/hibernate/browse/HHH-6259 – radai 2011-05-31 05:15:02