From hibernate-commits at lists.jboss.org Tue Nov 21 12:39:20 2006 Content-Type: multipart/mixed; boundary="===============8813753014308743992==" MIME-Version: 1.0 From: hibernate-commits at lists.jboss.org To: hibernate-commits at lists.jboss.org Subject: [hibernate-commits] Hibernate SVN: r10852 - in trunk/Hibernate3: doc/reference/en/modules src/org/hibernate/hql/ast/tree src/org/hibernate/persister/entity src/org/hibernate/tuple/entity test/org/hibernate/test test/org/hibernate/test/idprops test/org/hibernate/test/legacy Date: Tue, 21 Nov 2006 12:39:20 -0500 Message-ID: --===============8813753014308743992== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: steve.ebersole(a)jboss.com Date: 2006-11-21 12:39:14 -0500 (Tue, 21 Nov 2006) New Revision: 10852 Added: trunk/Hibernate3/test/org/hibernate/test/idprops/ trunk/Hibernate3/test/org/hibernate/test/idprops/IdentifierPropertyRefer= encesTest.java trunk/Hibernate3/test/org/hibernate/test/idprops/LineItem.java trunk/Hibernate3/test/org/hibernate/test/idprops/LineItemPK.java trunk/Hibernate3/test/org/hibernate/test/idprops/Mapping.hbm.xml trunk/Hibernate3/test/org/hibernate/test/idprops/Order.java trunk/Hibernate3/test/org/hibernate/test/idprops/Person.java Modified: trunk/Hibernate3/doc/reference/en/modules/query_hql.xml trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java trunk/Hibernate3/src/org/hibernate/hql/ast/tree/FromElement.java trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersis= ter.java trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractPropertyMapp= ing.java trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityMetamodel.java trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java Log: HHH-1851 : relax special 'id' property handling Modified: trunk/Hibernate3/doc/reference/en/modules/query_hql.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/doc/reference/en/modules/query_hql.xml 2006-11-21 17:3= 8:43 UTC (rev 10851) +++ trunk/Hibernate3/doc/reference/en/modules/query_hql.xml 2006-11-21 17:3= 9:14 UTC (rev 10852) @@ -1,6 +1,6 @@ - + HQL: The Hibernate Query Language - = + Hibernate is equipped with an extremely powerful query language th= at (quite intentionally) looks very much like SQL. But don't be fooled by the syntax; HQL i= s fully object-oriented, @@ -20,12 +20,12 @@ foo.barSet is not foo.BARSET. - = + - This manual uses lowercase HQL keywords. Some users find queri= es with uppercase keywords = + This manual uses lowercase HQL keywords. Some users find queri= es with uppercase keywords more readable, but we find this convention ugly when embedded = in Java code. - = + = @@ -34,17 +34,17 @@ The simplest possible Hibernate query is of the form: - = + - = + which simply returns all instances of the class eg.Ca= t. We don't usually need to qualify the class name, since auto-import is the default. So we almost always just write: - = + - = + Most of the time, you will need to assign an alias, since you will want to refer to the Cat in other = parts of the @@ -58,33 +58,33 @@ instances, so we could use that alias later in the query. The = as keyword is optional; we could also write: - = + - = + Multiple classes may appear, resulting in a cartesian product = or "cross" join. - = + - = + It is considered good practice to name query aliases using an = initial lowercase, consistent with Java naming standards for local variables (eg. domesticCat). - = + = Associations and joins = - We may also assign aliases to associated entities, or even to = elements of a = + We may also assign aliases to associated entities, or even to = elements of a collection of values, using a join. = - = @@ -118,50 +118,50 @@ - = + - The inner join, left outer join and = + The inner join, left outer join and right outer join constructs may be abbrevia= ted. = - - = + You may supply extra join conditions using the HQL wi= th keyword. = - 10.0]]> = - In addition, a "fetch" join allows associations or collections= of values to be = - initialized along with their parent objects, using a single se= lect. This is particularly = + In addition, a "fetch" join allows associations or collections= of values to be + initialized along with their parent objects, using a single se= lect. This is particularly useful in the case of a collection. It effectively overrides t= he outer join and lazy declarations of the mapping file for associations and col= lections. See for more information. - = - - = + - A fetch join does not usually need to assign an alias, because= the associated objects = - should not be used in the where clause (or = any other clause). Also, = - the associated objects are not returned directly in the query = results. Instead, they may = + A fetch join does not usually need to assign an alias, because= the associated objects + should not be used in the where clause (or = any other clause). Also, + the associated objects are not returned directly in the query = results. Instead, they may be accessed via the parent object. The only reason we might ne= ed an alias is if we are recursively join fetching a further collection: - = - - = + Note that the fetch construct may not be us= ed in queries called using iterate() (though scroll() can be used). Nor should @@ -171,18 +171,18 @@ you'd expect. Nor may fetch be used together with an ad h= oc with condition. It is possible to create a cartesian product by join fetching = more than one collection in a - query, so take care in this case. Join fetching multiple colle= ction roles also sometimes gives = - unexpected results for bag mappings, so be careful about how y= ou formulate your queries in this = - case. Finally, note that full join fetch an= d right join fetch = + query, so take care in this case. Join fetching multiple colle= ction roles also sometimes gives + unexpected results for bag mappings, so be careful about how y= ou formulate your queries in this + case. Finally, note that full join fetch an= d right join fetch are not meaningful. - = + If you are using property-level lazy fetching (with bytecode i= nstrumentation), it is possible to force Hibernate to fetch the lazy properties immed= iately (in the first query) using fetch all properties. - = + = @@ -210,16 +210,52 @@ = + + Refering to identifier property + + + There are, generally speaking, 2 ways to refer to an entity's = identifier property: + + + + + The special property (lowercase) id= may be used to reference the identifier + property of an entity provided that entity d= oes not define a non-identifier property + named id. + + + + + If the entity defines a named identifier property, you= may use that property name. + + + + + + References to composite identifier properties follow the same = naming rules. If the + entity has a non-identifier property named id, the composite i= dentifier property can only + be referenced by its defined named; otherwise, the special id property + can be used to rerference the identifier property. + + + + Note: this has changed significantly starting in version 3.2.2= . In previous versions, + id always referred to = the identifier property no + matter what its actual name. A ramification of that decision = was that non-identifier + properties named id could never be referenc= ed in Hibernate queries. + + + The select clause = - The select clause picks which objects and p= roperties to return in = + The select clause picks which objects and p= roperties to return in the query result set. Consider: = - = @@ -239,37 +275,37 @@ = - Queries may return multiple objects and/or properties as an ar= ray of type = + Queries may return multiple objects and/or properties as an ar= ray of type Object[], = - - = + or as a List, - = + - = + or as an actual typesafe Java object, - = + - = + assuming that the class Family has an appro= priate constructor. - = + You may assign aliases to selected expressions using = as: @@ -280,14 +316,14 @@ This is most useful when used together with select ne= w map: - = + = This query returns a Map from aliases to se= lected values. - = + = @@ -302,11 +338,11 @@ = = @@ -331,21 +367,21 @@ - = + You may use arithmetic operators, concatenation, and recognize= d SQL functions in the select clause: - = - - = + - = + - The distinct and all key= words may be used and = + The distinct and all key= words may be used and have the same semantics as in SQL. = @@ -354,7 +390,7 @@ select count(distinct cat.name), count(cat) from Cat cat]]> = - = + Polymorphic queries = @@ -366,30 +402,30 @@ = returns instances not only of Cat, but also= of subclasses like - DomesticCat. Hibernate queries may name any Java = - class or interface in the from clause. The = query will return instances = - of all persistent classes that extend that class or implement = the interface. The following = + DomesticCat. Hibernate queries may name any Java + class or interface in the from clause. The = query will return instances + of all persistent classes that extend that class or implement = the interface. The following query would return all persistent objects: - = + - = + The interface Named might be implemented by= various persistent classes: - = + - = + Note that these last two queries will require more than one SQ= L SELECT. This means that the order by clause does not cor= rectly order the whole result set. (It also means you can't call these queries using Que= ry.scroll().) - = + = - + The where clause = @@ -398,18 +434,18 @@ = - = + If there is an alias, use a qualified property name: - = + = returns instances of Cat named 'Fritz'. = - = @@ -429,7 +465,7 @@ something like = - = @@ -437,19 +473,20 @@ = - The =3D operator may be used to compare not= only properties, but also = + The =3D operator may be used to compare not= only properties, but also instances: = = - = - The special property (lowercase) id may be = used to reference the = - unique identifier of an object. (You may also use its property= name.) + The special property (lowercase) id may be = used to reference the + unique identifier of an object. See + for more information. = = - Properties of composite identifiers may also be used. Suppose = Person = - has a composite identifier consisting of country and = - medicareNumber. + Properties of composite identifiers may also be used. Suppose = Person + has a composite identifier consisting of country and + medicareNumber. Again, see + for more information regarding referencing identifier properti= es. = = = Once again, the second query requires no table join. - = + Likewise, the special property class access= es the discriminator value - of an instance in the case of polymorphic persistence. A Java = class name embedded in the = + of an instance in the case of polymorphic persistence. A Java = class name embedded in the where clause will be translated to its discriminator value. = - = + - You may also specify properties of components or composite use= r types (and of components = - of components, etc). Never try to use a path-expression that e= nds in a property of component = - type (as opposed to a property of a component). For example, i= f store.owner - is an entity with a component address + You may also use components or composite user types, or proper= ties of said + component types. See = for more details. = - - An "any" type has the special properties id= and class, allowing us to express a join in the following way (where AuditLog.item is a property mapped with <any>). - = - - = + Notice that log.item.class and pay= ment.class would refer to the values of completely different database col= umns in the above query. - = + = @@ -550,14 +583,14 @@ is not null, is empty, is not empty, - member of and = + member of and not member of "Simple" case, case ... when ... then ... else .= .. end, and - "searched" case, case when ... then ... else = ... end = + "searched" case, case when ... then ... else = ... end @@ -573,8 +606,8 @@ - second(...), minute(...), = - hour(...), day(...), = + second(...), minute(...), + hour(...), day(...), month(...), year(...), @@ -592,14 +625,14 @@ str() for converting numeric or tem= poral values to a - readable string = + readable string cast(... as ...), where the second = argument is the name of - a Hibernate type, and extract(... from ...) if ANSI = - cast() and extract() is supported by = + a Hibernate type, and extract(... from ...) if ANSI + cast() and extract() is supported by the underlying database @@ -611,15 +644,15 @@ - HQL functions that take collection-valued path express= ions: size(), = - minelement(), maxelement(), minindex(), maxindex(), along with the = + HQL functions that take collection-valued path express= ions: size(), + minelement(), maxelement(), minindex(), maxindex(), along with the special elements() and ind= ices functions which may be quantified using some, all, exis= ts, any, in. - Any database-supported SQL scalar function like sign(), = + Any database-supported SQL scalar function like sign(), trunc(), rtrim()= , sin() @@ -663,7 +696,7 @@ = - Likewise, is null and is not null<= /literal> may be used to test = + Likewise, is null and is not null<= /literal> may be used to test for null values. = @@ -692,20 +725,20 @@ = For indexed collections, you may refer to the minimum and maxi= mum indices using - minindex and maxindex fu= nctions. Similarly, = - you may refer to the minimum and maximum elements of a collect= ion of basic type = + minindex and maxindex fu= nctions. Similarly, + you may refer to the minimum and maximum elements of a collect= ion of basic type using the minelement and maxelemen= t functions. - = + current_date]]> - = + 100]]> = 10000]]> - = + - The SQL functions any, some, all, exists, in are supported when passed the element = + The SQL functions any, some, all, exists, in are supported when passed the element or index set of a collection (elements and = indices functions) or the result of a subquery (see below). @@ -728,12 +761,12 @@ minelement, maxelement -= may only be used in the where clause in Hibernate3. - = + Elements of indexed collections (arrays, lists, maps) may be r= eferred to by index (in a where clause only): - = + = The expression inside [] may even be an ari= thmetic expression. - = + - = + - HQL also provides the built-in index() func= tion, for elements = + HQL also provides the built-in index() func= tion, for elements of a one-to-many association or collection of values. = - = @@ -769,7 +802,7 @@ = - If you are not yet convinced by all this, think how much longe= r and less readable the = + If you are not yet convinced by all this, think how much longe= r and less readable the following query would be in SQL: = @@ -816,7 +849,7 @@ order by cat.name asc, cat.weight desc, cat.birthdate]]> = - The optional asc or desc= indicate ascending or descending order = + The optional asc or desc= indicate ascending or descending order respectively. @@ -828,11 +861,11 @@ A query that returns aggregate values may be grouped by any pr= operty of a returned class or components: = - = - = @@ -840,14 +873,14 @@ A having clause is also allowed. = - = SQL functions and aggregate functions are allowed in the having - and order by clauses, if supported by the u= nderlying database = + and order by clauses, if supported by the u= nderlying database (eg. not in MySQL). = @@ -868,37 +901,37 @@ = - = - + + Subqueries - = + For databases that support subselects, Hibernate supports subq= ueries within queries. A subquery must be surrounded by parentheses (often by an SQL aggregate functi= on call). Even correlated subqueries (subqueries that refer to an alias in the outer query) are all= owed. = - ( = - select avg(cat.weight) from DomesticCat cat = + ( + select avg(cat.weight) from DomesticCat cat )]]> = - - = - = - = - = @@ -906,53 +939,30 @@ = - For subqueries with more than one expression in the select lis= t, you can use a tuple constructor: + Note that subqueries can also utilize row value const= ructor syntax. See + for more details. - = - = - - Note that on some databases (but not Oracle or HSQL), you can = use tuple constructors in other - contexts, for example when querying components or composite us= er types: - - - - = - - Which is equivalent to the more verbose: - - = - - - - There are two good reasons you might not want to do this kind = of thing: first, it is not = - completely portable between database platforms; second, the qu= ery is now dependent upon - the ordering of properties in the mapping document. - - = = HQL examples - = + Hibernate queries can be quite powerful and complex. In fact, = the power of the query language is one of Hibernate's main selling points. Here are some examp= le queries very similar to queries that I used on a recent project. Note that most queries you wi= ll write are much simpler than these! - = + - The following query returns the order id, number of items and = total value of the order for all = - unpaid orders for a particular customer and given minimum tota= l value, ordering the results by = - total value. In determining the prices, it uses the current ca= talog. The resulting SQL query, = + The following query returns the order id, number of items and = total value of the order for all + unpaid orders for a particular customer and given minimum tota= l value, ordering the results by + total value. In determining the prices, it uses the current ca= talog. The resulting SQL query, against the ORDER, ORDER_LINE, PRODUCT, CATALOG and PRICE tables= has four inner joins and an (uncorrelated) subselect. - = + =3D all ( - select cat.effectiveDate = + select cat.effectiveDate from Catalog as cat where cat.effectiveDate < sysdate ) group by order having sum(price.amount) > :minAmount order by sum(price.amount) desc]]> - = + - What a monster! Actually, in real life, I'm not very keen on s= ubqueries, so my query was = + What a monster! Actually, in real life, I'm not very keen on s= ubqueries, so my query was really more like this: - = + :minAmount order by sum(price.amount) desc]]> - = + The next query counts the number of payments in each status, e= xcluding all payments in the - AWAITING_APPROVAL status where the most rec= ent status change was made by the = - current user. It translates to an SQL query with two inner joi= ns and a correlated subselect = - against the PAYMENT, PAYMENT_STATU= S and = + AWAITING_APPROVAL status where the most rec= ent status change was made by the + current user. It translates to an SQL query with two inner joi= ns and a correlated subselect + against the PAYMENT, PAYMENT_STATU= S and PAYMENT_STATUS_CHANGE tables. = - PaymentStatus.AWAITING_APPROVAL or ( - statusChange.timeStamp =3D ( = - select max(change.timeStamp) = - from PaymentStatusChange change = + statusChange.timeStamp =3D ( + select max(change.timeStamp) + from PaymentStatusChange change where change.payment =3D payment ) and statusChange.user <> :currentUser @@ -1016,11 +1026,11 @@ order by status.sortOrder]]> = - If I would have mapped the statusChanges co= llection as a list, instead of a set, = + If I would have mapped the statusChanges co= llection as a list, instead of a set, the query would have been much simpler to write. - = - PaymentStatus.AWAITING_APPROVAL @@ -1031,9 +1041,9 @@ The next query uses the MS SQL Server isNull() function to return all the accounts and unpaid payments for the organization to which= the current user belongs. - It translates to an SQL query with three inner joins, an outer= join and a subselect against = + It translates to an SQL query with three inner joins, an outer= join and a subselect against the ACCOUNT, PAYMENT, PAYMENT_STATUS, - ACCOUNT_TYPE, ORGANIZATION and = + ACCOUNT_TYPE, ORGANIZATION and ORG_USER tables. = @@ -1082,7 +1092,7 @@ = @@ -1135,7 +1145,7 @@ Collection elements may be ordered or grouped using a query fi= lter: - = + = @@ -1147,5 +1157,78 @@ = = + + Components + + + Components might be used in just about every way that simple v= alue types can be used in HQL + queries. They can appear in the select cla= use: + + + + = + + + where the Person's name property is a component. Components c= an also be used + in the where clause: + + + + + + + Components can also be used in the order by= clause: + + + + + + + Another common use of components is in row value constructors. + + + + + Row value constructor syntax + + + HQL supports the use of ANSI SQL row value constructo= r syntax (sometimes + called tuple syntax), even though the under= lying database may not support + that notion. Here we are generally referring to multi-valued = comparisons, typically associated + with components. Consider an entity Person which defines a na= me component: + + + + + + That's valid syntax, although a little verbose. It be nice to= make this a bit more concise and use + row value constructor syntax: + + + + + + It can also be useful to specify this in the select clause: + + + + + + Another time using row value constructor sy= ntax can be beneficial + is when using subqueries needing to compare against multiple v= alues: + + + + + + One thing to consider when deciding if you want to use this sy= ntax is that the query will + be dependent upon the ordering of the component sub-properties= in the metadata. + + + + = Modified: trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java 2006-11-21= 17:38:43 UTC (rev 10851) +++ trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java 2006-11-21= 17:39:14 UTC (rev 10852) @@ -81,9 +81,9 @@ private FromElement impliedJoin; = /** - * Sets the join type for the '.' node (JoinFragment.XXX). + * Sets the join type for this '.' node structure. * - * @param joinType + * @param joinType The type of join to use. * @see JoinFragment */ public void setJoinType(int joinType) { @@ -220,8 +220,7 @@ private Type prepareLhs() throws SemanticException { FromReferenceNode lhs =3D getLhs(); lhs.prepareForDot( propertyName ); - Type propertyType =3D getDataType(); - return propertyType; + return getDataType(); } = private void dereferenceCollection(CollectionType collectionType, boolean= implicitJoin, boolean indexed, String classAlias, AST parent) @@ -298,7 +297,7 @@ // select clause is part of a scalar query :/ ) DotNode parentAsDotNode =3D null; String property =3D propertyName; - boolean joinIsNeeded =3D false; + final boolean joinIsNeeded; = if ( isDotNode( parent ) ) { parentAsDotNode =3D ( DotNode ) parent; @@ -340,13 +339,11 @@ String joinPath =3D getPath(); = if ( impliedJoin && getWalker().isInFrom() ) { - int impliedJoinType =3D getWalker().getImpliedJoinType(); - joinType =3D impliedJoinType; + joinType =3D getWalker().getImpliedJoinType(); } = FromClause currentFromClause =3D getWalker().getCurrentFromClause(); - FromElement elem =3D null; - elem =3D currentFromClause.findJoinByPath( joinPath ); + FromElement elem =3D currentFromClause.findJoinByPath( joinPath ); = //////////////////////////////////////////////////////////////////////////= ///// // @@ -420,14 +417,42 @@ return impliedJoin; } = - private boolean isReferenceToPrimaryKey(String propertyName, EntityType p= ropertyType) { - if ( EntityPersister.ENTITY_ID.equals( propertyName ) ) { - // the referenced node text is the special 'id' - return propertyType.isReferenceToPrimaryKey(); + /** + * Is the given property name a reference to the primary key of the assoc= iated + * entity construed by the given entity type? + *

+ * For example, consider a fragment like order.customer.id + * (where order is a from-element alias). Here, we'd have: + * propertyName =3D "id" AND + * owningType =3D ManyToOneType(Customer) + * and are being asked to determine whether "customer.id" is a reference + * to customer's PK... + * + * @param propertyName The name of the property to check. + * @param owningType The type represeting the entity "owning" the property + * @return True if propertyName references the entity's (owningType->asso= ciatedEntity) + * primary key; false otherwise. + */ + private boolean isReferenceToPrimaryKey(String propertyName, EntityType o= wningType) { + EntityPersister persister =3D getSessionFactoryHelper() + .getFactory() + .getEntityPersister( owningType.getAssociatedEntityName() ); + if ( persister.getEntityMetamodel().hasNonIdentifierPropertyNamedId() ) { + // only the identifier property field name can be a reference to the as= sociated entity's PK... + return propertyName.equals( persister.getIdentifierPropertyName() ) && = owningType.isReferenceToPrimaryKey(); } else { - String keyPropertyName =3D getSessionFactoryHelper().getIdentifierOrUni= queKeyPropertyName( propertyType ); - return keyPropertyName !=3D null && keyPropertyName.equals( propertyNam= e ) && propertyType.isReferenceToPrimaryKey(); + // here, we have two possibilities: + // 1) the property-name matches the explicitly identifier property na= me + // 2) the property-name matches the implicit 'id' property name + if ( EntityPersister.ENTITY_ID.equals( propertyName ) ) { + // the referenced node text is the special 'id' + return owningType.isReferenceToPrimaryKey(); + } + else { + String keyPropertyName =3D getSessionFactoryHelper().getIdentifierOrUn= iqueKeyPropertyName( owningType ); + return keyPropertyName !=3D null && keyPropertyName.equals( propertyNa= me ) && owningType.isReferenceToPrimaryKey(); + } } } = Modified: trunk/Hibernate3/src/org/hibernate/hql/ast/tree/FromElement.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/src/org/hibernate/hql/ast/tree/FromElement.java 2006-1= 1-21 17:38:43 UTC (rev 10851) +++ trunk/Hibernate3/src/org/hibernate/hql/ast/tree/FromElement.java 2006-1= 1-21 17:39:14 UTC (rev 10852) @@ -5,7 +5,6 @@ import java.util.List; = import org.hibernate.QueryException; -import org.hibernate.MappingException; import org.hibernate.engine.JoinSequence; import org.hibernate.hql.QueryTranslator; import org.hibernate.hql.CollectionProperties; @@ -285,11 +284,19 @@ throw new IllegalStateException( "No table alias for node " + this ); } String[] cols; + String propertyName; + if ( getEntityPersister() !=3D null && getEntityPersister().getEntityMet= amodel() !=3D null + && getEntityPersister().getEntityMetamodel().hasNonIdentifierPropertyN= amedId() ) { + propertyName =3D getEntityPersister().getIdentifierPropertyName(); + } + else { + propertyName =3D EntityPersister.ENTITY_ID; + } if ( getWalker().getStatementType() =3D=3D HqlSqlWalker.SELECT ) { - cols =3D getPropertyMapping( EntityPersister.ENTITY_ID ).toColumns( tab= le, EntityPersister.ENTITY_ID ); + cols =3D getPropertyMapping( propertyName ).toColumns( table, propertyN= ame ); } else { - cols =3D getPropertyMapping( EntityPersister.ENTITY_ID ).toColumns( Ent= ityPersister.ENTITY_ID ); + cols =3D getPropertyMapping( propertyName ).toColumns( propertyName ); } String result =3D StringHelper.join( ", ", cols ); return cols.length =3D=3D 1 ? result : "(" + result + ")"; @@ -375,13 +382,6 @@ return origin; } = - /** - * Returns the type of a property, given it's name (the last part) and th= e full path. - * - * @param propertyName The last part of the full path to the property. - * @return The type. - * @0param propertyPath The full property path. - */ public Type getPropertyType(String propertyName, String propertyPath) { return elementType.getPropertyType( propertyName, propertyPath ); } @@ -422,9 +422,6 @@ return filter; } = - /** - * Returns true if the from fragment should be included in the from claus= e. - */ public boolean useFromFragment() { checkInitialized(); // If it's not implied or it is implied and it's a many to many join whe= re the target wasn't found. @@ -472,10 +469,6 @@ // Do nothing, eplicit from elements are *always* in the projection list. } = - /** - * Returns true if this element should be in the projection list. - * - */ public boolean inProjectionList() { return !isImplied() && isFromOrJoinFragment(); } Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntit= yPersister.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersi= ster.java 2006-11-21 17:38:43 UTC (rev 10851) +++ trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersi= ster.java 2006-11-21 17:39:14 UTC (rev 10852) @@ -1508,9 +1508,11 @@ // ALIASES internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyC= losureIterator() ); = - // aliases for identifier ( alias.id ) - subclassPropertyAliases.put( ENTITY_ID, getIdentifierAliases() ); - subclassPropertyColumnNames.put( ENTITY_ID, getIdentifierColumnNames() ); + // aliases for identifier ( alias.id ); skip if the entity defines a non= -id property named 'id' + if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) { + subclassPropertyAliases.put( ENTITY_ID, getIdentifierAliases() ); + subclassPropertyColumnNames.put( ENTITY_ID, getIdentifierColumnNames() = ); + } = // aliases named identifier ( alias.idname ) if ( hasIdentifierProperty() ) { @@ -1527,23 +1529,26 @@ String[] idColumnNames =3D getIdentifierColumnNames(); = for ( int i =3D 0; i < idPropertyNames.length; i++ ) { - subclassPropertyAliases.put( - ENTITY_ID + "." + idPropertyNames[i], - new String[] { idAliases[i] } + if ( entityMetamodel.hasNonIdentifierPropertyNamedId() ) { + subclassPropertyAliases.put( + ENTITY_ID + "." + idPropertyNames[i], + new String[] { idAliases[i] } ); - subclassPropertyColumnNames.put( - ENTITY_ID + "." + getIdentifierPropertyName() + "." + idPropertyName= s[i], - new String[] { idColumnNames[i] } + subclassPropertyColumnNames.put( + ENTITY_ID + "." + getIdentifierPropertyName() + "." + idPropertyNam= es[i], + new String[] { idColumnNames[i] } ); - if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropert= yName() ) ) { + } +// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPrope= rtyName() ) ) { + if ( hasIdentifierProperty() ) { subclassPropertyAliases.put( getIdentifierPropertyName() + "." + idPropertyNames[i], new String[] { idAliases[i] } - ); + ); subclassPropertyColumnNames.put( getIdentifierPropertyName() + "." + idPropertyNames[i], new String[] { idColumnNames[i] } - ); + ); } else { // embedded composite ids ( alias.idname1, alias.idname2 ) @@ -1554,10 +1559,8 @@ } = if ( entityMetamodel.isPolymorphic() ) { - subclassPropertyAliases.put( ENTITY_CLASS, - new String[]{getDiscriminatorAlias()} ); - subclassPropertyColumnNames.put( ENTITY_CLASS, - new String[]{getDiscriminatorColumnName()} ); + subclassPropertyAliases.put( ENTITY_CLASS, new String[] { getDiscrimina= torAlias() } ); + subclassPropertyColumnNames.put( ENTITY_CLASS, new String[] { getDiscri= minatorColumnName() } ); } = } @@ -1672,7 +1675,9 @@ if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { propertyMapping.initPropertyPaths( null, getIdentifierType(), getIdenti= fierColumnNames(), null, mapping ); } - propertyMapping.initPropertyPaths( ENTITY_ID, getIdentifierType(), getId= entifierColumnNames(), null, mapping ); + if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) { + propertyMapping.initPropertyPaths( ENTITY_ID, getIdentifierType(), getI= dentifierColumnNames(), null, mapping ); + } } = private void initDiscriminatorPropertyPath(Mapping mapping) throws Mappin= gException { @@ -3145,7 +3150,7 @@ return factory; } = - protected EntityMetamodel getEntityMetamodel() { + public EntityMetamodel getEntityMetamodel() { return entityMetamodel; } = Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractPrope= rtyMapping.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractPropertyMap= ping.java 2006-11-21 17:38:43 UTC (rev 10851) +++ trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractPropertyMap= ping.java 2006-11-21 17:39:14 UTC (rev 10852) @@ -34,20 +34,16 @@ = public Type toType(String propertyName) throws QueryException { Type type =3D (Type) typesByPropertyPath.get(propertyName); - if (type=3D=3Dnull) throwPropertyException(propertyName); + if ( type =3D=3D null ) { + throw propertyException( propertyName ); + } return type; } = - protected final void throwPropertyException(String propertyName) = - throws QueryException { - throw new QueryException( - "could not resolve property: " + - propertyName + - " of: " + - getEntityName() - ); + protected final QueryException propertyException(String propertyName) thr= ows QueryException { + return new QueryException( "could not resolve property: " + propertyName= + " of: " + getEntityName() ); } - = + public String[] getColumnNames(String propertyName) { String[] cols =3D (String[]) columnsByPropertyPath.get(propertyName); if (cols=3D=3Dnull) { @@ -56,11 +52,12 @@ return cols; } = - public String[] toColumns(String alias, String propertyName) - throws QueryException { + public String[] toColumns(String alias, String propertyName) throws Query= Exception { //TODO: *two* hashmap lookups here is one too many... String[] columns =3D (String[]) columnsByPropertyPath.get(propertyName); - if (columns=3D=3Dnull) throwPropertyException(propertyName); + if ( columns =3D=3D null ) { + throw propertyException( propertyName ); + } String[] templates =3D (String[]) formulaTemplatesByPropertyPath.get(pro= pertyName); String[] result =3D new String[columns.length]; for ( int i=3D0; i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Added: trunk/Hibernate3/test/org/hibernate/test/idprops/Order.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/test/org/hibernate/test/idprops/Order.java 2006-11-21 = 17:38:43 UTC (rev 10851) +++ trunk/Hibernate3/test/org/hibernate/test/idprops/Order.java 2006-11-21 = 17:39:14 UTC (rev 10852) @@ -0,0 +1,60 @@ +package org.hibernate.test.idprops; + +import java.util.Date; +import java.util.Set; +import java.util.HashSet; + +/** + * {@inheritDoc} + * + * @author Steve Ebersole + */ +public class Order { + private Long number; + private Date placed; + private Person orderee; + + private Set lineItems =3D new HashSet(); + + public Order() { + } + + public Order(Long number, Person orderee) { + this.number =3D number; + this.orderee =3D orderee; + this.placed =3D new Date(); + } + + public Long getNumber() { + return number; + } + + public void setNumber(Long number) { + this.number =3D number; + } + + public Date getPlaced() { + return placed; + } + + public void setPlaced(Date placed) { + this.placed =3D placed; + } + + public Person getOrderee() { + return orderee; + } + + public void setOrderee(Person orderee) { + this.orderee =3D orderee; + } + + + public Set getLineItems() { + return lineItems; + } + + public void setLineItems(Set lineItems) { + this.lineItems =3D lineItems; + } +} Added: trunk/Hibernate3/test/org/hibernate/test/idprops/Person.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/test/org/hibernate/test/idprops/Person.java 2006-11-21= 17:38:43 UTC (rev 10851) +++ trunk/Hibernate3/test/org/hibernate/test/idprops/Person.java 2006-11-21= 17:39:14 UTC (rev 10852) @@ -0,0 +1,45 @@ +package org.hibernate.test.idprops; + +/** + * {@inheritDoc} + * + * @author Steve Ebersole + */ +public class Person { + private Long pk; + private String name; + private int id; + + public Person() { + } + + public Person(Long pk, String name, int id) { + this.pk =3D pk; + this.name =3D name; + this.id =3D id; + } + + public Long getPk() { + return pk; + } + + public void setPk(Long pk) { + this.pk =3D pk; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name =3D name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id =3D id; + } +} Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.j= ava =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java 20= 06-11-21 17:38:43 UTC (rev 10851) +++ trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java 20= 06-11-21 17:39:14 UTC (rev 10852) @@ -11,6 +11,7 @@ import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.MappingException; +import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.cache.CacheConcurrencyStrategy; import org.hibernate.cache.entry.CacheEntryStructure; import org.hibernate.cache.entry.UnstructuredCacheEntry; @@ -76,7 +77,7 @@ public String getEntityName() { return Custom.class.getName(); } - = + public boolean isSubclassEntityName(String entityName) { return Custom.class.getName().equals(entityName); } @@ -616,4 +617,9 @@ public Comparator getVersionComparator() { return null; } + + public EntityMetamodel getEntityMetamodel() { + return null; + } + } --===============8813753014308743992==--