我有一個我需要實現以下約束的實體: 「對於列X和Y的任何組合,可能只有一條記錄,如果記錄的類型爲A,那麼列Z爲空。通過Hibernate驗證,我可以查詢被驗證的實體嗎?
最後一部分將其從簡單的唯一性約束轉變爲更復雜的東西。我正在編寫一個定製的Hibernate驗證器來檢查它。
我在做什麼是:
@Override
public boolean isValid(MyEntity value, ConstraintValidatorContext context) {
Query query = DB.createQuery(// DB is just a convenience class
"select count(*) from MyEntity" +
" where propertyX = :propertyX" +
" and propertyY = :propertyY" +
" and type = :type" +
" and propertyZ is null")
.setParameter("propertyX", value.getPropertyZ())
.setParameter("propertyY", value.getPropertyY())
.setParameter("type", MyType.PRIMARY);
return query.getResultList().size() <= 1;
}
如果有不止一個這樣的記錄驗證應該失敗。在插入新條目之前,這將強制始終設置propertyZ
。
然而這不起作用,因爲此驗證情況onPersist
並在該點查詢返回一個null
ID,這會導致異常的結果。
這裏是從堆棧跟蹤一些有趣的臺詞:其他
[junit] org.hibernate.AssertionFailure: null id in my.package.MyEntity entry (dont flush the Session after an exception occurs)
[junit] at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:82)
[junit] at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:190)
[junit] at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:147)
[junit] at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
[junit] at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
[junit] at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
[junit] at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:1185)
[junit] at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1261)
[junit] at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
[junit] at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:246)
[junit] at my.package.validation.UniqueCombinationTypeValidator.isValid(UniqueCombinationTypeValidator.java:42)
[junit] at my.package.validation.UniqueCombinationTypeValidator.isValid(UniqueCombinationTypeValidator.java:14)
[junit] at org.hibernate.validator.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:153)
[junit] at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:140)
...
[junit] at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
[junit] at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
[junit] at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
[junit] at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
[junit] at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:672)
[junit] at my.package.DB.persist(DB.java:278)
[junit] at my.package.test.model.validation.UniqueCombinationTypeValidatorTest.testInsert(UniqueCombinationTypeValidatorTest.java:72)
有一點要注意的是,當這第一次插入完成表是空的。
問題是,我可以查詢我想驗證的同一張表嗎?這似乎是一個非常合乎邏輯的要求,因爲可以在類上添加約束註釋。我的驗證取決於數據的狀態。
我不知道它是否在持久性事務中執行新的查詢查找? – 2012-03-28 13:29:59
從休眠[論壇](https://forum.hibernate.org/viewtopic.php?f=1&t=1004374):「在任何回調方法中調用/使用同一個會話都是不好的。會話「。這可能是問題所在。 – 2012-03-28 14:41:29