Uploaded image for project: 'Hibernate ORM'
  1. HHH-11416

Envers query API: cannot traverse relation if target entity is mapped with JOINED subclass mapping/Unrelated property joins do not work when target entity is Mapped with JOINED subclass mapping

    Details

    • Bug Testcase Reminder (view):

      Bug reports should generally be accompanied by a test case!

    • Last commented by a user?:
      true

      Description

      An exception is thrown when querying for entities with Envers where an association is traversed and the target entity is mapped with inheritance strategy 'joined subclass'. This issue only occurs when using AuditStrategy 'ValidityAuditStrategy'. Consider the following example:

      @Entity(name="EntityA")
      @Audited
      public class EntityA {
        @Id
        private Long id;
        @OneToOne
        private EntityC relationToC;
      }
      
      @Entity(name="EntityB)
      @Audited
      @Inheritance(strategy=InheritanceType.JOINED)
      public class EntityB {
        @Id
        private Long id;
      }
      
      @Entity(name="EntityC")
      @Audited
      public class EntityC extends EntityB {
      }
      
      getAuditReader().createQuery()
        .forEntitiesAtRevision(EntityA.class, 1)
        .traverseRelation("relationToC", JoinType.INNER)
        .getResultList();
      

      The problem is that the REVEND property (in the ValidityAuditStrategy) is not available for the joined class (EntityC) because EntityC has InheritanceStrategy JOINED.
      Envers creates a JPQL query for its audit queries, so this issue exists in hibernate core. It seems that whenever an entity is joined with unrelated property join and that Entity has InheritanceStrategy JOINED, no properties of a superclass may be used in the query. I have created a simple example which reproduces this problem in hibernate-core:

      @Entity(name="EntityA")
      public class EntityA {
        @Id
        private Long id;
        private String propA;
      }
      
      @Entity(name="EntityB)
      @Inheritance(strategy=InheritanceType.JOINED)
      public class EntityB {
        @Id
        private Long id;
        private String propB;
      }
      
      @Entity(name="EntityC")
      public class EntityC extends EntityB {
        private String propC;
      }
      
      getEntityManager()
        .createQuery("select a from EntityA a inner join EntityC c on a.propA=c.propC where c.propB='foo'")
        .getResultList();
      

      In this example the property 'propB' of EntityC is not available since it is defined on superclass EntityB.

      Here are the stack traces of the two examples:

      The Envers example:

      javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
      	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
      	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
      	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1419)
      	at org.hibernate.envers.query.internal.impl.EntitiesAtRevisionQuery.list(EntitiesAtRevisionQuery.java:127)
      	at org.hibernate.envers.query.internal.impl.AbstractAuditQuery.getResultList(AbstractAuditQuery.java:107)
      	at org.hibernate.envers.query.internal.impl.AuditAssociationQueryImpl.getResultList(AuditAssociationQueryImpl.java:99)
      	at org.hibernate.envers.test.integration.query.AssociationToOneInnerJoinQueryTest2.testAssociationQuery(AssociationToOneInnerJoinQueryTest2.java:149)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
      	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
      	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
      	at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
      	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
      	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
      	at org.hibernate.testing.junit4.FailureExpectedHandler.evaluate(FailureExpectedHandler.java:41)
      	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
      	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
      	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
      	at org.hibernate.testing.junit4.BeforeClassCallbackHandler.evaluate(BeforeClassCallbackHandler.java:26)
      	at org.hibernate.testing.junit4.AfterClassCallbackHandler.evaluate(AfterClassCallbackHandler.java:25)
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
      	at org.junit.runners.Suite.runChild(Suite.java:128)
      	at org.junit.runners.Suite.runChild(Suite.java:27)
      	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
      	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
      	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
      	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
      Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
      	at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
      	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
      	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
      	at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1940)
      	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)
      	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
      	at org.hibernate.loader.Loader.doQuery(Loader.java:932)
      	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
      	at org.hibernate.loader.Loader.doList(Loader.java:2615)
      	at org.hibernate.loader.Loader.doList(Loader.java:2598)
      	at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
      	at org.hibernate.loader.Loader.list(Loader.java:2425)
      	at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:502)
      	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:370)
      	at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
      	at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1481)
      	at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1441)
      	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)
      	... 40 more
      Caused by: org.h2.jdbc.JdbcSQLException: Column "ASSOCIATIO1_1_.REVEND" not found; SQL statement:
      select associatio0_.id as id1_1_, associatio0_.REV as REV2_1_, associatio0_.REVTYPE as REVTYPE3_1_, associatio0_.REVEND as REVEND4_1_, associatio0_.relationToC_id as relation5_1_ from EntityA_AUD associatio0_ inner join EntityC_AUD associatio1_ on (associatio0_.relationToC_id=associatio1_.id) where associatio0_.REV<=? and associatio0_.REVTYPE<>? and (associatio0_.REVEND>? or associatio0_.REVEND is null) and associatio1_.REV<=? and (associatio1_1_.REVEND>? or associatio1_1_.REVEND is null) [42122-176]
      	at org.h2.message.DbException.getJdbcSQLException(DbException.java:344)
      	at org.h2.message.DbException.get(DbException.java:178)
      	at org.h2.message.DbException.get(DbException.java:154)
      	at org.h2.expression.ExpressionColumn.optimize(ExpressionColumn.java:148)
      	at org.h2.expression.Comparison.optimize(Comparison.java:179)
      	at org.h2.expression.ConditionAndOr.optimize(ConditionAndOr.java:131)
      	at org.h2.expression.ConditionAndOr.optimize(ConditionAndOr.java:132)
      	at org.h2.expression.ConditionAndOr.optimize(ConditionAndOr.java:131)
      	at org.h2.command.dml.Select.prepare(Select.java:834)
      	at org.h2.command.Parser.prepareCommand(Parser.java:248)
      	at org.h2.engine.Session.prepareLocal(Session.java:442)
      	at org.h2.engine.Session.prepareCommand(Session.java:384)
      	at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1188)
      	at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:73)
      	at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:276)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
      	... 56 more
      

      The JPQL example:

      javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
      	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
      	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
      	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1419)
      	at org.hibernate.Query.getResultList(Query.java:427)
      	at org.hibernate.envers.test.integration.query.AssociationToOneInnerJoinQueryTest2.testJPQL(AssociationToOneInnerJoinQueryTest2.java:155)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
      	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
      	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
      	at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
      	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
      	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
      	at org.hibernate.testing.junit4.FailureExpectedHandler.evaluate(FailureExpectedHandler.java:41)
      	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
      	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
      	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
      	at org.hibernate.testing.junit4.BeforeClassCallbackHandler.evaluate(BeforeClassCallbackHandler.java:26)
      	at org.hibernate.testing.junit4.AfterClassCallbackHandler.evaluate(AfterClassCallbackHandler.java:25)
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
      	at org.junit.runners.Suite.runChild(Suite.java:128)
      	at org.junit.runners.Suite.runChild(Suite.java:27)
      	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
      	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
      	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
      	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
      Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
      	at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
      	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
      	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
      	at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1940)
      	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)
      	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
      	at org.hibernate.loader.Loader.doQuery(Loader.java:932)
      	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
      	at org.hibernate.loader.Loader.doList(Loader.java:2615)
      	at org.hibernate.loader.Loader.doList(Loader.java:2598)
      	at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
      	at org.hibernate.loader.Loader.list(Loader.java:2425)
      	at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:502)
      	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:370)
      	at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
      	at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1481)
      	at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1441)
      	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)
      	... 38 more
      Caused by: org.h2.jdbc.JdbcSQLException: Column "ASSOCIATIO1_1_.PROPB" not found; SQL statement:
      select associatio0_.id as id1_0_, associatio0_.propA as propA2_0_ from EntityA associatio0_ inner join EntityC associatio1_ on (associatio0_.propA=associatio1_.propC) where associatio1_1_.propB='b' [42122-176]
      	at org.h2.message.DbException.getJdbcSQLException(DbException.java:344)
      	at org.h2.message.DbException.get(DbException.java:178)
      	at org.h2.message.DbException.get(DbException.java:154)
      	at org.h2.expression.ExpressionColumn.optimize(ExpressionColumn.java:148)
      	at org.h2.expression.Comparison.optimize(Comparison.java:179)
      	at org.h2.expression.ConditionAndOr.optimize(ConditionAndOr.java:131)
      	at org.h2.command.dml.Select.prepare(Select.java:834)
      	at org.h2.command.Parser.prepareCommand(Parser.java:248)
      	at org.h2.engine.Session.prepareLocal(Session.java:442)
      	at org.h2.engine.Session.prepareCommand(Session.java:384)
      	at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1188)
      	at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:73)
      	at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:276)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
      	at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
      	... 54 more
      

        Attachments

          Issue links

            Activity

              People

              • Votes:
                1 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: