The following error occurs in @NamedQuery if the annotations are put on property(getter) not on the field(member variable). ERROR org.hibernate.internal.SessionFactoryImpl - HHH000177: Error in named query: myNamedQuery org.hibernate.QueryException: could not resolve property: xxx of: xxxx [from EntityA a where a.entityB.someId = :someId ] at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:83) at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:77) at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1968) at org.hibernate.hql.internal.ast.tree.FromElementType.getPropertyType(FromElementType.java:313) at org.hibernate.hql.internal.ast.tree.FromElement.getPropertyType(FromElement.java:490) at org.hibernate.hql.internal.ast.tree.DotNode.getDataType(DotNode.java:616) at org.hibernate.hql.internal.ast.tree.DotNode.prepareLhs(DotNode.java:267) at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:214) at org.hibernate.hql.internal.ast.tree.DotNode.resolveFirstChild(DotNode.java:178) at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:578) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:4719) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1260) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4426) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:3898) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2076) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:794) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:595) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:299) at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:247) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:250) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:138) at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:105) at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:80) at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:168) at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:1083) at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:520) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1794) Example code snippets and a workable reproducer could be found from https://hibernate.atlassian.net/browse/HHH-9256
This is not a bug. The test does not specify an explicit access type, so the section of the JPA spec, "Default Access Type", applies. It says: "All such classes in the entity hierarchy whose access type is defaulted in this way must be consistent in their placement of annotations on either fields or properties, such that a single, consistent default access type applies within the hierarchy." EntityA does not comply with this as it has a field and a property annotated. The test will pass if the EntityA class is annotated with: @Access(value=AccessType.PROPERTY) and the entityB field is explicitly annoated with: @Access(value=AccessType.FIELD)
Hi Gail, The test case I provided didn't specify a consistent way of annotation. After making all of the annotations on the property(getter) in both EnityA and EntityB classes, the original error goes away. Thanks for pointing this out. However, our customer actually runs into a different issue here. Please note that the variable name of EntityB that is referenced in EntityA is in a camel case format. In my example, private EntityB entityB; @ManyToOne @JoinColumn(name="ENTITY_B_ID") public EntityB getEntityB() { return this.entityB; } public void setEntityB(EntityB entityB) { this.entityB = entityB; } If this variable name is changed to something like: private EntityB eB; // or anything starts with a single lower case letter + capital letter // such as eBenity, eBxx, etc //the @NamedQuery would be // query = "from EntityA s where s.eB.entityBId = :entityBId") then the original error "could not resolve property" comes back again.
Created attachment 925253 [details] hibernate.test.01121653.namedquery.zip attached the updated test case project that 1) make all of the annotations consistent on the property(getter) 2) change the variable name to private EntityB eB; in EntityA; and namedquery to query = "from EntityA s where s.eB.entityBId = :entityBId") This updated project could demonstrate that the following error would show after the changes: ERROR HHH000177: Error in named query: getEntityBById org.hibernate.QueryException: could not resolve property: eB of: gss.hibernate.test.entity.annotations.EntityA [from gss.hibernate.test.entity.annotations.EntityA s where s.eB.entityBId = :entityBId]
This is not a bug either. According to the JPA 2.1 spec, section "2.2 Persistent Fields and Properties": "It is required that the entity class follow the method signature conventions for JavaBeans read/write properties (as defined by the JavaBeans Introspector class) for persistent properties when property access is used." and in the footnotes: "[2] Specifically, if getX is the name of the getter method and setX is the name of the setter method, where X is a string, the name of the persistent property is defined by the result of java.beans.Introspector.decapitalize(X)." According to the Javadoc for java.beans.Introspector.decapitalize(String name): "Utility method to take a string and convert it to normal Java variable name capitalization. This normally means converting the first character from upper case to lower case, but in the (unusual) special case when there is more than one character and both the first and second characters are upper case, we leave it alone. Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays as "URL". " For this test, the query should be: "from EntityA s where s.EB.entityBId = :entityBId"