Bug 1127919 - [HHH-9256] Receiving "Error in named query: org.hibernate.QueryException: could not resolve property xxx" if annotating on property not on field
Summary: [HHH-9256] Receiving "Error in named query: org.hibernate.QueryException: cou...
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: JBoss Enterprise Application Platform 6
Classification: JBoss
Component: Hibernate
Version: 6.2.0
Hardware: Unspecified
OS: Unspecified
high
high
Target Milestone: ---
: ---
Assignee: Gail Badner
QA Contact: Martin Simka
Russell Dickenson
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2014-08-07 20:25 UTC by Gary Hu
Modified: 2018-12-06 17:41 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2014-08-08 21:25:55 UTC
Type: Bug


Attachments (Terms of Use)
hibernate.test.01121653.namedquery.zip (29.81 KB, application/zip)
2014-08-08 17:13 UTC, Gary Hu
no flags Details

Description Gary Hu 2014-08-07 20:25:21 UTC
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

Comment 1 Gail Badner 2014-08-07 22:10:14 UTC
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)

Comment 2 Gary Hu 2014-08-08 14:36:16 UTC
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.

Comment 3 Gary Hu 2014-08-08 17:13:13 UTC
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]

Comment 4 Gail Badner 2014-08-08 21:17:33 UTC
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"


Note You need to log in before you can comment on or make changes to this bug.