diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java index 34fc6a6fb8..455b50305f 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java @@ -36,6 +36,7 @@ import org.hibernate.metamodel.model.domain.internal.MapMember; import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; import org.hibernate.metamodel.model.domain.internal.PluralAttributeBuilder; import org.hibernate.metamodel.model.domain.internal.SingularAttributeImpl; +import org.hibernate.metamodel.model.domain.spi.ManagedTypeDescriptor.InFlightAccess; import org.hibernate.metamodel.model.domain.spi.PersistentAttributeDescriptor; import org.hibernate.metamodel.model.domain.spi.EmbeddedTypeDescriptor; import org.hibernate.metamodel.model.domain.spi.IdentifiableTypeDescriptor; @@ -46,6 +47,7 @@ import org.hibernate.property.access.internal.PropertyAccessMapImpl; import org.hibernate.property.access.spi.Getter; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.type.ComponentType; +import org.hibernate.type.CompositeType; import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.EntityType; @@ -95,11 +97,45 @@ public class AttributeFactory { return buildPluralAttribute( (PluralAttributeMetadata) attributeMetadata ); } final SingularAttributeMetadata singularAttributeMetadata = (SingularAttributeMetadata) attributeMetadata; - final SimpleTypeDescriptor metaModelType = determineSimpleType( singularAttributeMetadata.getValueContext() ); + SimpleTypeDescriptor metaModelType = determineSimpleType( singularAttributeMetadata.getValueContext() ); + Attribute.PersistentAttributeType jpaAttributeNature = attributeMetadata.getJpaAttributeNature(); + + if ( attributeContext.getPropertyMapping().getType().isComponentType() && jpaAttributeNature.equals( Attribute.PersistentAttributeType.BASIC ) ) { + CompositeType compositeType = (CompositeType) attributeContext.getPropertyMapping().getType(); + EmbeddableTypeImpl embeddableType = new EmbeddableTypeImpl<>( + attributeMetadata.getJavaType(), + ownerType, + compositeType, + context.getSessionFactory() + ); + context.registerEmbeddedableType(embeddableType); + + String[] propertyNames = compositeType.getPropertyNames(); + org.hibernate.type.Type[] subtypes = compositeType.getSubtypes(); + InFlightAccess inFlightAccess = embeddableType.getInFlightAccess(); + + for ( int i = 0; i < propertyNames.length; i++ ) { + SingularAttributeImpl nestedAttribute = new SingularAttributeImpl( + embeddableType, + propertyNames[i], + Attribute.PersistentAttributeType.BASIC, + new BasicTypeImpl(subtypes[i].getReturnedClass(), Type.PersistenceType.BASIC), + null, + false, + false, + property.isOptional() + ); + inFlightAccess.addAttribute(nestedAttribute); + } + + metaModelType = embeddableType; + jpaAttributeNature = Attribute.PersistentAttributeType.EMBEDDED; + } + return new SingularAttributeImpl( ownerType, attributeMetadata.getName(), - attributeMetadata.getJpaAttributeNature(), + jpaAttributeNature, metaModelType, attributeMetadata.getMember(), false, @@ -230,7 +266,7 @@ public class AttributeFactory { ); context.registerEmbeddedableType( embeddableType ); - final ManagedTypeDescriptor.InFlightAccess inFlightAccess = embeddableType.getInFlightAccess(); + final InFlightAccess inFlightAccess = embeddableType.getInFlightAccess(); final Iterator subProperties = component.getPropertyIterator(); while ( subProperties.hasNext() ) { final Property property = subProperties.next(); @@ -954,7 +990,7 @@ public class AttributeFactory { final EmbeddedTypeDescriptor embeddableType = (EmbeddedTypeDescriptor) attributeContext.getOwnerType(); final String attributeName = attributeContext.getPropertyMapping().getName(); - final Getter getter = embeddableType.getHibernateType() + final Getter getter = ( ( ComponentType ) embeddableType.getHibernateType() ) .getComponentTuplizer() .getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) ); return PropertyAccessMapImpl.GetterImpl.class.isInstance( getter ) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java index 100be7a13e..95efae1fbd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java @@ -13,7 +13,7 @@ import org.hibernate.graph.internal.SubGraphImpl; import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.metamodel.model.domain.spi.EmbeddedTypeDescriptor; import org.hibernate.metamodel.model.domain.spi.ManagedTypeDescriptor; -import org.hibernate.type.ComponentType; +import org.hibernate.type.CompositeType; /** * Standard Hibernate implementation of JPA's {@link javax.persistence.metamodel.EmbeddableType} @@ -27,12 +27,12 @@ public class EmbeddableTypeImpl implements EmbeddedTypeDescriptor, Serializable { private final ManagedTypeDescriptor parent; - private final ComponentType hibernateType; + private final CompositeType hibernateType; public EmbeddableTypeImpl( Class javaType, ManagedTypeDescriptor parent, - ComponentType hibernateType, + CompositeType hibernateType, SessionFactoryImplementor sessionFactory) { super( javaType, null, null, sessionFactory ); this.parent = parent; @@ -48,7 +48,7 @@ public class EmbeddableTypeImpl return parent; } - public ComponentType getHibernateType() { + public CompositeType getHibernateType() { return hibernateType; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/EmbeddedTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/EmbeddedTypeDescriptor.java index 3190d74358..de7af0c106 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/EmbeddedTypeDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/EmbeddedTypeDescriptor.java @@ -9,7 +9,7 @@ package org.hibernate.metamodel.model.domain.spi; import javax.persistence.metamodel.EmbeddableType; import org.hibernate.metamodel.model.domain.EmbeddedDomainType; -import org.hibernate.type.ComponentType; +import org.hibernate.type.CompositeType; /** * Hibernate extension to the JPA {@link EmbeddableType} descriptor @@ -17,7 +17,7 @@ import org.hibernate.type.ComponentType; * @author Steve Ebersole */ public interface EmbeddedTypeDescriptor extends EmbeddedDomainType, ManagedTypeDescriptor { - ComponentType getHibernateType(); + CompositeType getHibernateType(); ManagedTypeDescriptor getParent(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/cut/CompositeUserTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/cut/CompositeUserTypeTest.java index 1f02f107b7..7d8d3678d1 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/cut/CompositeUserTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cut/CompositeUserTypeTest.java @@ -6,18 +6,24 @@ */ package org.hibernate.test.cut; +import java.lang.reflect.Member; import java.math.BigDecimal; import java.util.Currency; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Restrictions; import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.SybaseASE15Dialect; import org.hibernate.hql.internal.ast.QuerySyntaxException; +import org.hibernate.metamodel.model.domain.spi.PersistentAttributeDescriptor; +import org.hibernate.metamodel.model.domain.spi.SingularPersistentAttribute; +import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; @@ -25,13 +31,20 @@ import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.SingularAttribute; + import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; /** * @author Gavin King */ public class CompositeUserTypeTest extends BaseCoreFunctionalTestCase { + @Override public String[] getMappings() { return new String[] { "cut/types.hbm.xml", "cut/Transaction.hbm.xml" }; @@ -67,6 +80,21 @@ public class CompositeUserTypeTest extends BaseCoreFunctionalTestCase { t.commit(); s.close(); } + + @Test + public void testMetamodel() { + MetamodelImplementor metamodel = sessionFactory().getMetamodel(); + PersistentAttributeDescriptor value = metamodel.managedType(Transaction.class).getAttribute("value"); + assertEquals(Attribute.PersistentAttributeType.EMBEDDED, value.getPersistentAttributeType()); + + SingularPersistentAttribute singularPersistentAttribute = (SingularPersistentAttribute) value; + ManagedType attribute = (ManagedType) singularPersistentAttribute.getType(); + SingularAttribute amount = attribute.getSingularAttribute("amount"); + assertNotNull(amount); + + Member javaMember = amount.getJavaMember(); + assertNull(javaMember); + } @Test @SkipForDialect ( value = { SybaseASE15Dialect.class }, jiraKey = "HHH-6788" )