diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeFactory.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeFactory.java index 6352c9e7d9..daca8213ad 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeFactory.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeFactory.java @@ -73,10 +73,12 @@ public class AttributeFactory { * @param property The Hibernate property descriptor for the attribute * @param The type of the owner * @param The attribute type - * @return The built attribute descriptor + * @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model (eg backrefs) */ @SuppressWarnings({ "unchecked" }) public AttributeImplementor buildAttribute(AbstractManagedType ownerType, Property property) { + //a back ref is a virtual property created by Hibernate, let's hide it from the JPA model. + if ( property.isBackRef() ) return null; final AttributeContext attributeContext = wrap( ownerType, property ); final AttributeMetadata attributeMetadata = determineAttributeMetadata( attributeContext, NORMAL_MEMBER_RESOLVER ); @@ -208,7 +210,10 @@ public class AttributeFactory { final Iterator subProperties = component.getPropertyIterator(); while ( subProperties.hasNext() ) { final Property property = subProperties.next(); - embeddableType.getBuilder().addAttribute( buildAttribute( embeddableType, property) ); + final AttributeImplementor attribute = buildAttribute( embeddableType, property ); + if ( attribute != null ) { + embeddableType.getBuilder().addAttribute( attribute ); + } } embeddableType.lock(); return embeddableType; diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java index 8dc28115dc..798ade530a 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java @@ -175,7 +175,9 @@ class MetadataContext { continue; } final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property ); - jpa2Mapping.getBuilder().addAttribute( attribute ); + if ( attribute != null ) { + jpa2Mapping.getBuilder().addAttribute( attribute ); + } } jpa2Mapping.lock(); populateStaticMetamodel( jpa2Mapping ); @@ -192,7 +194,9 @@ class MetadataContext { while ( properties.hasNext() ) { final Property property = properties.next(); final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property ); - jpa2Mapping.getBuilder().addAttribute( attribute ); + if ( attribute != null ) { + jpa2Mapping.getBuilder().addAttribute( attribute ); + } } jpa2Mapping.lock(); populateStaticMetamodel( jpa2Mapping ); diff --git a/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/Child.java b/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/Child.java new file mode 100644 index 0000000000..245c3878c8 --- /dev/null +++ b/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/Child.java @@ -0,0 +1,34 @@ +package org.hibernate.ejb.test.metadata; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author Emmanuel Bernard + */ +@Entity +@Table(name="ejb_child") +public class Child { + private Integer id; + private String name; + + @Id + @GeneratedValue + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/MetadataTest.java b/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/MetadataTest.java index c0390a5bd9..d07e9d3f22 100644 --- a/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/MetadataTest.java +++ b/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/MetadataTest.java @@ -274,6 +274,18 @@ public class MetadataTest extends TestCase { assertNull( thing.getSupertype() ); } + public void testOneToManyJoinColumnUnidirectional() throws Exception { + final EntityType parent = factory.getMetamodel().entity( Parent.class ); + assertNotNull( parent ); + final SetAttribute children = parent.getSet( "children" ); + assertNotNull( children ); + assertEquals( 1, parent.getPluralAttributes().size() ); + assertEquals( 3, parent.getAttributes().size() ); + final EntityType child = factory.getMetamodel().entity( Child.class ); + assertNotNull( child ); + assertEquals( 2, child.getAttributes().size() ); + } + private void ensureProperMember(Set attributes) { //we do not update the set so we are safe @SuppressWarnings( "unchecked" ) @@ -321,7 +333,9 @@ public class MetadataTest extends TestCase { Feline.class, Garden.class, Flower.class, - JoinedManyToOneOwner.class + JoinedManyToOneOwner.class, + Parent.class, + Child.class }; } diff --git a/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/Parent.java b/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/Parent.java new file mode 100644 index 0000000000..59316f032a --- /dev/null +++ b/entitymanager/src/test/java/org/hibernate/ejb/test/metadata/Parent.java @@ -0,0 +1,49 @@ +package org.hibernate.ejb.test.metadata; + +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.Table; + + +/** + * @author Emmanuel Bernard + */ +@Entity +@Table(name="ejb_parent") +public class Parent { + private Integer id; + private String name; + private Set children; + + @Id + @GeneratedValue + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @OneToMany + @JoinColumn(name="parent_fk", nullable = false) + public Set getChildren() { + return children; + } + + public void setChildren(Set children) { + this.children = children; + } +}