首页 文章

使用haschanged查询审计表时出错

提问于
浏览
0

我有Template实体,它有:

@ManyToOne
    @JsonView(JsonDefinitionMapper.SecondLevel.class)   
    @Audited
    private TemplateType templateType;

实例 .

当我要使用循环实体属性查询所有更改时,如下所示:属性是通过实体的元数据获取的:

for(String property:PropertiesList){
newValue = auditReader.createQuery()
                                            .forRevisionsOfEntity(Template.class, false, true)
                                            .addProjection(AuditEntity.property(property))
                                            .add(AuditEntity.property(property).hasChanged())
                                            .add(AuditEntity.id().eq(templateId))
                                            .add(AuditEntity.revisionNumber().eq(revisionNumber)).getSingleResult();
}

生成的Template_AUD表有template_type_mod,template_type_id列(自动生成)

运行上面的查询时出现此错误:

org.hibernate.QueryException:无法解析属性:templateType of:com.templates.domain.Template_AUD [select e __ . templateType from com.templates.domain.Template_AUD e ,com.template.domain.AuditedRevisionEntity r where e __ . templateType_MOD = :p0和e.originalId.id =:p1和e.originalId.REV.id =:p2和e_.originalId.REV.id = r.id]在org.hibernate.QueryException.generateQueryException(QueryException.java:120)在org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)在org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:218)在org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile (QueryTranslatorImpl.java:142)org.hibernate.engine.query.spi.HQLQueryPlan . (HQLQueryPlan.java:115)org.hibernate.engine.query.spi.HQLQueryPlan . (HQLQueryPlan.java:76)at org . org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSe)中的hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ssionImpl.java:302)位于org.hibernate.envers.internal.tools的org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240)org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894) .query.QueryBuilder.toQuery(QueryBuilder.java:226)在org.hibernate.envers.query.internal.impl.AbstractAuditQuery.buildQuery(AbstractAuditQuery.java:79)在org.hibernate.envers.query.internal.impl.AbstractAuditQuery .buildAndExecuteQuery(AbstractAuditQuery.java:85)在org.hibernate.envers.query.internal.impl.RevisionsOfEntityQuery.list(RevisionsOfEntityQuery.java:108)在org.hibernate.envers.query.internal.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery .java:97)at com.template.dataRepository.TemplateRevisionRepository.getAllChangedPropertiesWithREvisions(TemplateRevisionRepository.java:211)at com.template.dataRepository.TemplateRevisionRepository $$ FastClassBySpringCGLIB $$ 5bf5efd1.invoke()at org.springframework.cglib.proxy.MethodProxy .invoke(MethodProxy.java: 204)在org.springframework.ao上的Org.springframework.aop.frame.CglibAopProxy $ CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)org.springframework.dao.support位于org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWithInvocation(TransactionInterceptor.java:99)的org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)中的.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)在org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)在org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:179)org.springframework.aop.framework.CglibAopProxy $ DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)位于com.template.dataRepository.TemplateRevisionRepository $$ EnhancerBySpringCGLIB $$ 952a9450.getAllChangedPropertiesWithREvisions()at com.template.EnversTest.getAllChangedPropertiesWithREvisions(EnversTest.java:151)at sun.reflect.NativeMethodAccessorImpl . invoke0(本机方法)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在java.lang.reflect.Method.invoke(Method.java: 498)org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50)位于org.junit.runners的org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) . model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)在org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)在org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(茹nBeforeTestMethodCallbacks.java:75)atorg.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)在org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)在org.junit . runners.ParentRunner.runLeaf(ParentRunner.java:325)org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner . 的java:94)在在在org.junit.runners.ParentRunner.runChildren org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71)org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290) (ParentRunner.java:288)在org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58)在org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:268)在org.springframework.test . org.springframework.test.con中的context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner)中的org.junit.runners.ParentRunner.run(ParentRunner.java:363)中的text.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) . 的java:191)在org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)在org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)在处org.eclipse org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) .jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

我正在使用postgres数据库

1 回答

  • 0

    我最初的想法是利用Envers 5.2中添加的新关系遍历API,您可以通过它编写查询,如下所示:

    final List results = auditReader.createQuery()
      .forEntitiesModifiedAtRevision( Template.class, revNo )
      .traverseRelation( "templateType", JoinType.INNER )
        .addProjection( AuditEntity.selectEntity( false ) )
        .up()
      .add( AuditEntity.property( "templateType" ).hasChanged() )
      .getResultList();
    

    这里的想法是,我们基本上要求在结果列表中返回 TemplateType ,但前提是它被视为在根实体上被修改, Template ;但是,这个查询引入了我认为是一个bug:

    org.hibernate.QueryException:未设置命名参数[revision]

    这是因为添加到根查询的子查询指定了一个命名参数 revision ;但是,查询逻辑永远不会绑定修订值;导致这个问题 .

    我已经提交了问题HHH-11981来解决这个问题 .

    所以现在,我唯一的建议是如果你的实体类有超出基本类型属性的东西,你可能需要在你的代码中使用反射来实际从返回的bean中获取值 .

    final List results = auditReader.createQuery()
      .forEntitiesModifiedAtRevision( Template.class, revNo )
      .add( AuditEntity.property( propertyName ).hasChanged() )
      .getResultList();
    

    对于列表中的条目,您需要使用反射为 propertyName 标识的相应属性调用相应的getter . 它不太理想,但至少可以避免您遇到的查询问题 .

相关问题