Issue Details (XML | Word | Printable)

Key: HHH-1851
Type: Improvement Improvement
Status: Reopened Reopened
Priority: Major Major
Assignee: Steve Ebersole
Reporter: Gunther Schadow
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
Hibernate Core

relax special handling of 'id' property

Created: 23/Jun/06 04:31 PM   Updated: 20/May/09 05:32 AM
Component/s: query-hql
Affects Version/s: None
Fix Version/s: 3.5

Time Tracking:
Issue & Sub-Tasks
Issue Only
Not Specified

File Attachments: 1. Zip Archive IdClassAndAnotherPropertyNamedId.zip (1 kB)

Environment: independent, all versions all databases.

Sub-Tasks  All   Open   

 Description  « Hide
Hibernate has long treated 'id' in a special manner in HQL and Criteria queries. The drawback to this has always been that it effectively means users cannot define non-identifier properties named id and refer to those properties in HQL/Criteria queries.

Thus, I will change this such that:
(1) 'id' can still be used to refer to the identifier property, whatever the property's actual name, as long as the entity does not define a non-identitifer property named id.
(2) if the entity defines a non-identifier property named 'id', using 'id' in HQL or Criteria queries will refer to this non-identifier property; users would need to refer to the identifier property by its actual name.

FYI, the original reason for this feature was to support entity's which did not define an identifier property at all (users were responsible for managing the ids seperately. That feature was never really recommended and has been deprecated since early in the 3.x development.

 All   Comments   Work Log   Change History   FishEye      Sort Order: Ascending order - Click to sort in descending order
Emmanuel Bernard added a comment - 23/Jun/06 05:04 PM
this feature is useful for object not holding an id property.
<id column="id"/>

Emmanuel Bernard added a comment - 23/Jun/06 05:04 PM
well
<id column="id">
  <generator class="native"/>
</id>

Gunther Schadow added a comment - 22/Aug/06 12:08 PM
Emmanuel, I may fail to see the utility of objects "not holding an id property" (and yet having one mapped), but you don't need the "special id property name" for this. If I define an <id> in the mapping I can set the name and if it is important not to map to an object, then can't one just specify another attribute such as virtual="yes"?

<id name="internalId" column="INTERNAL_ID" virtual="yes"> ...</id>

then I can write HQL as ... WHERE internalId='123' and still avoid to shadow the name "id" as a normal property name.

Steve Ebersole added a comment - 22/Aug/06 12:19 PM
Regardless, this still requires significant code changes.

I will get to it; but I have much more pressing things to work on. If you want to work on a patch, I'll take a look at your patch and prioritize this up higher...

Gunther Schadow added a comment - 23/Aug/06 08:33 AM
Thank you, that makes me hopeful. I wish I could help but I don't seem to be clear about the usecase that Emanuel and you have in mind which makes this difficult. My one-line patch works for me. So, perhaps, just a little syntax hack in the HQL grammar and we can turn "id" or "hid" into "@id" and that way overcome any further issues with overlap with any user properties. As far as I can see there should be no such serious ripple effects from this than there would be from this "virtual='yes'" attribute.

Steve Ebersole added a comment - 23/Aug/06 08:47 AM
There is a feature of Hibernate where a user can map a java class as an entity, even though that java class may not define a property to hold the id value. consider:

class MyEntity {
    private String name;
}

<class name="MyEntity">
    <id column="ID" .../>
    <property name="name"/>
</class>

I mean, i think you understand this issue. As you say, you just fail to see the utility of it. Well, perhaps. The feature is actually being deprecated. But regardless, the ramifications of the initial choice to use the special "id" keyword to always refer to the id property is subtly much deeper than you realize, I am certain. A simple "use some other keyword" is not going to address all situations.

Steve Ebersole added a comment - 23/Aug/06 08:48 AM
And adding some new mapping construct is fine, but there still needs to be code "under the covers" which knows what to do with this...

Steve Ebersole added a comment - 21/Nov/06 11:39 AM
trunk / 3.2

James Carman added a comment - 27/Jan/07 10:14 AM
Any idea when 3.2.2 will be released? We have an "id" property in our domain that we would like to use, but we can't until this is fixed/released.

Max Rydahl Andersen added a comment - 27/Jan/07 11:58 AM
hint: Go look at the downloads page before asking about when a release is out ;)

Gunther Schadow added a comment - 19/Mar/07 04:58 PM
Steve: thanks, Thank you, THANK YOU! Wonderful solution.

Anthony Patricio added a comment - 18/Apr/08 03:16 AM
I think it's more efficient to reopen this issue than opening a new one as this problem is closely related.
It seems there is a special case where this problem isn't fixed: usage of composite id + another basic property named "id".

See attached entity and its IdClass.
When querying like "Select b from Bird b", following exception is thrown:
java.lang.NullPointerException
at org.hibernate.util.StringHelper.root(StringHelper.java:150)
at org.hibernate.persister.entity.AbstractEntityPersister.getSubclassPropertyTableNumber(AbstractEntityPersister.java:1374)
at org.hibernate.persister.entity.BasicEntityPropertyMapping.toColumns(BasicEntityPropertyMapping.java:31)
at org.hibernate.persister.entity.AbstractEntityPersister.toColumns(AbstractEntityPersister.java:1350)
at org.hibernate.hql.ast.tree.FromElement.getIdentityColumn(FromElement.java:296)
at org.hibernate.hql.ast.tree.IdentNode.resolveAsAlias(IdentNode.java:131)
at org.hibernate.hql.ast.tree.IdentNode.resolve(IdentNode.java:77)
at org.hibernate.hql.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:94)
at org.hibernate.hql.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:90)
at org.hibernate.hql.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:728)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.propertyRef(HqlSqlBaseWalker.java:1105)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectExpr(HqlSqlBaseWalker.java:1881)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectExprList(HqlSqlBaseWalker.java:1825)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectClause(HqlSqlBaseWalker.java:1394)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:553)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:281)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:229)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:228)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:160)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:93)
at org.jboss.ejb3.entity.TransactionScopedEntityManager.createQuery(TransactionScopedEntityManager.java:127)
at case175572.Case175572TestCase.testCriteria(Case175572TestCase.java:96)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)


Anthony Patricio added a comment - 18/Apr/08 03:18 AM
tested with 3.2.4 sp1

Sanne Grinovero added a comment - 20/May/09 05:32 AM
please have Projections.id() return the identifier, whatever it is called.