我在休眠中使用JSR-303驗證。我創建了一個自定義驗證器註釋,通過查詢數據庫來檢查數據完整性。使用休眠驗證時Hibernate會話被刷新
例如:
public boolean isValid(Object value, ConstraintValidatorContext context) {
if(value == null){
return true;
}
//This method uses entityManager to fetch a list from database
Map<String, String> pickList = pickListProvider.getPickList(picklistName);
return pickList.contains(value);
}
用法:
public class UserProfile extends Persistent {
//Member fields come here
@PicklistConstraint(name="languages")
private String prefLanguage;
}
這裏用戶配置是一個實體持久使用休眠。 Hibernate在預插入或預先更新時調用此驗證。然而,當驗證器試圖從數據庫中提取記錄時,hibernate正在刷新會話。由於其上運行的驗證沒有完全出爐的域對象(不具備ID字段),我得到下面的異常
org.hibernate.AssertionFailure: null id in <domain object here> entry (don't flush the Session after an exception occurs)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:79)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:194)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:156)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:225)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1186)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1241)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:257)
經調查我發現,DefaultAutoFlushEventListener的flushMightBeNeeded返回true:
private boolean flushMightBeNeeded(final EventSource source) {
return !source.getFlushMode().lessThan(FlushMode.AUTO) &&
source.getDontFlushFromFind() == 0 &&
(source.getPersistenceContext().getEntityEntries().size() > 0 ||
source.getPersistenceContext().getCollectionEntries().size() > 0);
}
問題是FlushMode是AUTO和source.getPersistenceContext()。getEntityEntries()。size()有一些條目。 在這種情況下我的方法是什麼?我應該將FlushMode從AUTO更改爲MANUAL嗎?是否有可能獲得與實際實體不同的新會話或持久性上下文? 我正在使用spring mvc和hibernate。
編輯
我發現source.getPersistenceContext()。getEntityEntries()具有目前正在驗證的實體。插入前應該在這裏出現嗎?
我不會使用hibernate驗證來做到這一點。它看起來像是應該在特定用例中檢查的業務規則,而不是每次實體持續或更新時必須執行的檢查(例如驗證給定字段不爲空或它是肯定的)。相反,我會明確檢查pickList是否包含該值,然後堅持該實體。 –
在我看來,這不是一個商業規則。像性別這樣的領域可以有兩個值:「男」或「女」。這些值存儲在數據庫中,不會頻繁更改。這只是我們保留這些價值的問題。我可以使用屬性文件或硬編碼validator類中的值。所以這更像是數據完整性檢查。 – Vaibhav
然後使用性別枚舉而不是字符串,和/或創建包含男性和女性的性別表,並在您的實體的性別列上添加外鍵約束。 –