From 2176af11442c702aefa1900cdba4c32e6338b620 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Tue, 27 Oct 2009 15:05:44 +0000 Subject: [PATCH] HHH-4528 - Applied patch (with minor cleanup) git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17849 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../org/hibernate/cfg/AnnotationBinder.java | 95 ++++++++++++++++++- .../test/annotations/idclass/DomainAdmin.java | 84 ++++++++++++++++ .../annotations/idclass/DomainAdminId.java | 73 ++++++++++++++ .../idclass/IdClassCompositePKTest.java | 58 +++++++++++ 4 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdmin.java create mode 100644 annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdminId.java create mode 100644 annotations/src/test/java/org/hibernate/test/annotations/idclass/IdClassCompositePKTest.java diff --git a/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java index f9e89d3122..5ec783386e 100644 --- a/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -127,6 +127,7 @@ import org.hibernate.annotations.GenericGenerators; import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XClass; +import org.hibernate.annotations.common.reflection.XMethod; import org.hibernate.annotations.common.reflection.XPackage; import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.cfg.annotations.CollectionBinder; @@ -714,9 +715,10 @@ public final class AnnotationBinder { //process idclass if any Set idProperties = new HashSet(); IdClass idClass = null; + XClass current = null; if ( !inheritanceState.hasParents ) { //look for idClass - XClass current = inheritanceState.clazz; + current = inheritanceState.clazz; InheritanceState state = inheritanceState; do { current = state.clazz; @@ -740,6 +742,9 @@ public final class AnnotationBinder { PropertyData inferredData = new PropertyPreloadedData( entityBinder.getPropertyAccessor(), "id", compositeClass ); + PropertyData baseInferredData = new PropertyPreloadedData( + entityBinder.getPropertyAccessor(), "id", current + ); HashMap localGenerators = new HashMap(); boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations(); entityBinder.setIgnoreIdAnnotations( true ); @@ -747,6 +752,7 @@ public final class AnnotationBinder { generatorType, generator, inferredData, + baseInferredData, null, propertyHolder, localGenerators, @@ -762,6 +768,7 @@ public final class AnnotationBinder { Component mapper = fillComponent( propertyHolder, inferredData, + baseInferredData, propertyAnnotated, propertyAccessor, false, entityBinder, @@ -1941,6 +1948,17 @@ public final class AnnotationBinder { EntityBinder entityBinder, boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings ) { + + return fillComponent(propertyHolder, inferredData, null, propertyAnnotated, propertyAccessor, isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings); + } + + public static Component fillComponent( + PropertyHolder propertyHolder, PropertyData inferredData, PropertyData baseInferredData, + boolean propertyAnnotated, String propertyAccessor, boolean isNullable, + EntityBinder entityBinder, + boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings + ) { + /** * inSecondPass can only be used to apply right away the second pass of a composite-element * Because it's a value type, there is no bidirectional association, hence second pass @@ -1963,8 +1981,29 @@ public final class AnnotationBinder { comp, subpath, inferredData, propertyHolder, mappings ); + List classElements = new ArrayList(); XClass returnedClassOrElement = inferredData.getClassOrElement(); + + List baseClassElements = null; + XClass baseReturnedClassOrElement; + PropertyHolder baseSubHolder; + if(baseInferredData != null) + { + baseSubHolder = PropertyHolderBuilder.buildPropertyHolder( + comp, subpath, + inferredData, propertyHolder, mappings + ); + baseClassElements = new ArrayList(); + baseReturnedClassOrElement = baseInferredData.getClassOrElement(); + bindTypeDefs(baseReturnedClassOrElement, mappings); + addElementsOfAClass( + baseClassElements, + baseSubHolder, + propertyAnnotated, + propertyAccessor, baseReturnedClassOrElement, mappings + ); + } //embeddable elements can have type defs bindTypeDefs(returnedClassOrElement, mappings); @@ -1986,6 +2025,16 @@ public final class AnnotationBinder { ); superClass = superClass.getSuperclass(); } + if(baseClassElements != null) + { + if(!hasIdClassAnnotations(inferredData.getPropertyClass())) + { + for(int i=0; i < classElements.size(); i++) + { + classElements.set(i, baseClassElements.get(i)); //this works since they are in the same order + } + } + } for (PropertyData propertyAnnotatedElement : classElements) { processElementAnnotations( subHolder, isNullable ? @@ -2008,6 +2057,20 @@ public final class AnnotationBinder { String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded, boolean isIdentifierMapper, ExtendedMappings mappings ) { + + bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder, localGenerators, isComposite, isPropertyAnnotated, propertyAccessor, entityBinder, isEmbedded, isIdentifierMapper, mappings); + } + + private static void bindId( + String generatorType, String generatorName, PropertyData inferredData, + PropertyData baseInferredData, Ejb3Column[] columns, PropertyHolder propertyHolder, + Map localGenerators, + boolean isComposite, + boolean isPropertyAnnotated, + String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded, + boolean isIdentifierMapper, ExtendedMappings mappings + ) { + /* * Fill simple value and property since and Id is a property */ @@ -2025,7 +2088,7 @@ public final class AnnotationBinder { SimpleValue id; if ( isComposite ) { id = fillComponent( - propertyHolder, inferredData, isPropertyAnnotated, propertyAccessor, + propertyHolder, inferredData, baseInferredData, isPropertyAnnotated, propertyAccessor, false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings ); Component componentId = (Component) id; @@ -2474,4 +2537,32 @@ public final class AnnotationBinder { } return inheritanceStatePerClass; } + + private static boolean hasIdClassAnnotations(XClass idClass) + { + if(idClass.getAnnotation(Embeddable.class) != null) + return true; + + List properties = idClass.getDeclaredProperties( XClass.ACCESS_FIELD ); + for ( XProperty property : properties ) { + if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent( OneToMany.class ) || + property.isAnnotationPresent( ManyToOne.class ) || property.isAnnotationPresent( Id.class ) || + property.isAnnotationPresent( GeneratedValue.class ) || property.isAnnotationPresent( OneToOne.class ) || + property.isAnnotationPresent( ManyToMany.class ) + ) { + return true; + } + } + List methods = idClass.getDeclaredMethods(); + for ( XMethod method : methods ) { + if ( method.isAnnotationPresent( Column.class ) || method.isAnnotationPresent( OneToMany.class ) || + method.isAnnotationPresent( ManyToOne.class ) || method.isAnnotationPresent( Id.class ) || + method.isAnnotationPresent( GeneratedValue.class ) || method.isAnnotationPresent( OneToOne.class ) || + method.isAnnotationPresent( ManyToMany.class ) + ) { + return true; + } + } + return false; + } } diff --git a/annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdmin.java b/annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdmin.java new file mode 100644 index 0000000000..3eb7b0d6f7 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdmin.java @@ -0,0 +1,84 @@ +// $Id$ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.hibernate.test.annotations.idclass; + +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.NamedNativeQuery; +import javax.persistence.Table; + + +/** + * A DomainAdmin. + * + * @author Stale W. Pedersen + */ +@Entity +@Table(name = "domainadmin") +@IdClass(DomainAdminId.class) +@NamedNativeQuery(name = "DomainAdmin.testQuery", + query = "select * from domainadmin da where da.domain_name = 'org'", + resultClass = org.hibernate.test.annotations.idclass.DomainAdmin.class) +public class DomainAdmin implements Serializable { + + @Id + @Column(name = "domain_name") + private String domainName; + + @Id + @Column(name = "admin_user") + private String adminUser; + + @Column(name = "nick_name") + private String nickName; + + public DomainAdmin() { + } + + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + public String getAdminUser() { + return adminUser; + } + + public void setAdminUser(String adminUser) { + this.adminUser = adminUser; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } +} \ No newline at end of file diff --git a/annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdminId.java b/annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdminId.java new file mode 100644 index 0000000000..6d19f27a56 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/idclass/DomainAdminId.java @@ -0,0 +1,73 @@ +// $Id$ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.hibernate.test.annotations.idclass; + +import java.io.Serializable; + +/** + * A DomainAdminId. + * + * @author Stale W. Pedersen + */ +@SuppressWarnings("serial") +public class DomainAdminId implements Serializable { + + private String domainName; + + private String adminUser; + + public DomainAdminId() { + } + + public DomainAdminId(String domainName, String adminUser) { + this.domainName = domainName; + this.adminUser = adminUser; + } + + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + public String getAdminUser() { + return adminUser; + } + + public void setAdminUser(String adminUser) { + this.adminUser = adminUser; + } + + @Override + public boolean equals(Object o) { + return ( ( o instanceof DomainAdminId ) && domainName.equals( ( ( DomainAdminId ) o ).getDomainName() ) && + adminUser.equals( ( ( DomainAdminId ) o ).getAdminUser() ) ); + } + + @Override + public int hashCode() { + return ( domainName + adminUser ).hashCode(); + } +} \ No newline at end of file diff --git a/annotations/src/test/java/org/hibernate/test/annotations/idclass/IdClassCompositePKTest.java b/annotations/src/test/java/org/hibernate/test/annotations/idclass/IdClassCompositePKTest.java new file mode 100644 index 0000000000..8fea0dfa90 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/idclass/IdClassCompositePKTest.java @@ -0,0 +1,58 @@ +// $Id$ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.hibernate.test.annotations.idclass; + +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.test.annotations.TestCase; + +/** + * A IdClassTestCase. + * + * @author Stale W. Pedersen + * @version $Revision: 1.1 $ + */ +public class IdClassCompositePKTest extends TestCase { + + public void testEntityMappningPropertiesAreNotIgnored() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + DomainAdmin da = new DomainAdmin(); + da.setAdminUser( "admin" ); + da.setDomainName( "org" ); + + s.persist( da ); + Query q = s.getNamedQuery( "DomainAdmin.testQuery" ); + assertEquals( 1, q.list().size() ); + + tx.rollback(); + s.close(); + } + + protected Class[] getMappings() { + return new Class[] { + DomainAdmin.class + }; + } +}