gpt4 book ai didi

hibernate - 使用 Hibernate 验证,我可以查询正在验证的实体吗?

转载 作者:行者123 更新时间:2023-12-04 17:20:30 24 4
gpt4 key购买 nike

我有一个实体,我需要在其上实现以下约束:“X 和 Y 列的任意组合可能只有一条记录,如果记录是 A 类型,则 Z 列为空。”

最后一部分将其从简单的唯一性约束转变为更复杂的事物。我正在编写自定义 Hibernate validator 来检查它。

我正在做的是:

@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 的结果,这会导致一个异常(exception)。

以下是堆栈跟踪中的一些有趣行:

[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)

另一件需要注意的事情是,当第一次插入完成时,表是空的。

问题是,我可以查询要验证的同一个表吗?这似乎是一个非常合乎逻辑的要求,因为可以在类上放置约束注释。我的验证取决于数据的状态。

最佳答案

灵感来自 this post以及it is never OK的知识为了在从 session 触发的任何回调方法中调用/使用相同的 session ,我通过获取我的 EntityManagerFactory 设法非常简单地解决了这个问题,这反过来又让我得到了一个 EntityManager,它为我提供了一个新的 Session。现在我可以使用它来进行查询。

EntityManager em = emFactory.createEntityManager();
session = (Session) em.getDelegate();
Query query = session.createQuery(...

注意:来自 EntityManager docs , getDelegate() 是特定于实现的。我正在使用 tomcathibernate,它运行良好。

关于hibernate - 使用 Hibernate 验证,我可以查询正在验证的实体吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9908061/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com