diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java index e0860db60d..724d194d8f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java @@ -23,6 +23,8 @@ */ package org.hibernate.metamodel.binding; +import org.hibernate.metamodel.relational.SimpleValue; + /** * Binding of the discriminator in a entity hierarchy * @@ -30,19 +32,25 @@ package org.hibernate.metamodel.binding; * @author Hardy Ferentschik */ public class EntityDiscriminator { - private SimpleSingularAttributeBinding valueBinding; + private final HibernateTypeDescriptor explicitHibernateTypeDescriptor = new HibernateTypeDescriptor(); + + private SimpleValue boundValue; private boolean forced; private boolean inserted = true; public EntityDiscriminator() { } - public SimpleSingularAttributeBinding getValueBinding() { - return valueBinding; + public SimpleValue getBoundValue() { + return boundValue; } - public void setValueBinding(SimpleSingularAttributeBinding valueBinding) { - this.valueBinding = valueBinding; + public void setBoundValue(SimpleValue boundValue) { + this.boundValue = boundValue; + } + + public HibernateTypeDescriptor getExplicitHibernateTypeDescriptor() { + return explicitHibernateTypeDescriptor; } public boolean isForced() { @@ -65,7 +73,7 @@ public class EntityDiscriminator { public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "EntityDiscriminator" ); - sb.append( "{valueBinding=" ).append( valueBinding ); + sb.append( "{boundValue=" ).append( boundValue ); sb.append( ", forced=" ).append( forced ); sb.append( ", inserted=" ).append( inserted ); sb.append( '}' ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java index 37e6f730a6..dc3307e4bc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java @@ -23,58 +23,20 @@ */ package org.hibernate.metamodel.source.annotations.attribute; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.source.binder.ColumnSource; - /** * @author Hardy Ferentschik */ -public class ColumnSourceImpl implements ColumnSource { +public class ColumnSourceImpl extends ColumnValuesSourceImpl { private final SimpleAttribute attribute; - private final ColumnValues columnValues; ColumnSourceImpl(SimpleAttribute attribute) { + super( attribute.getColumnValues() ); this.attribute = attribute; - this.columnValues = attribute.getColumnValues(); } @Override public String getName() { - return columnValues.getName().isEmpty() ? attribute.getName() : columnValues.getName(); - } - - @Override - public boolean isNullable() { - return columnValues.isNullable(); - } - - @Override - public String getDefaultValue() { - // todo - return null; - } - - @Override - public String getSqlType() { - // todo - return null; - } - - @Override - public Datatype getDatatype() { - // todo - return null; - } - - @Override - public Size getSize() { - return new Size( - columnValues.getPrecision(), - columnValues.getScale(), - columnValues.getLength(), - Size.LobMultiplier.NONE - ); + return super.getName().isEmpty() ? attribute.getName() : super.getName(); } @Override @@ -87,36 +49,10 @@ public class ColumnSourceImpl implements ColumnSource { return attribute.getCustomWriteFragment(); } - @Override - public boolean isUnique() { - return columnValues.isUnique(); - } - @Override public String getCheckCondition() { return attribute.getCheckCondition(); } - - @Override - public String getComment() { - // todo - return null; - } - - @Override - public boolean isIncludedInInsert() { - return columnValues.isInsertable(); - } - - @Override - public boolean isIncludedInUpdate() { - return columnValues.isUpdatable(); - } - - @Override - public String getContainingTableName() { - return columnValues.getTable(); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java new file mode 100644 index 0000000000..4cda56b3be --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program 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 distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.annotations.attribute; + +import org.hibernate.metamodel.relational.Datatype; +import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.source.binder.ColumnSource; + +/** + * @author Steve Ebersole + */ +public class ColumnValuesSourceImpl implements ColumnSource { + private final ColumnValues columnValues; + + public ColumnValuesSourceImpl(ColumnValues columnValues) { + this.columnValues = columnValues; + } + + protected ColumnValues columnValues() { + return columnValues; + } + + @Override + public String getName() { + return columnValues.getName(); + } + + @Override + public boolean isNullable() { + return columnValues.isNullable(); + } + + @Override + public String getDefaultValue() { + // todo + return null; + } + + @Override + public String getSqlType() { + // todo + return null; + } + + @Override + public Datatype getDatatype() { + // todo + return null; + } + + @Override + public Size getSize() { + return new Size( + columnValues.getPrecision(), + columnValues.getScale(), + columnValues.getLength(), + Size.LobMultiplier.NONE + ); + } + + @Override + public boolean isUnique() { + return columnValues.isUnique(); + } + + @Override + public String getComment() { + // todo + return null; + } + + @Override + public boolean isIncludedInInsert() { + return columnValues.isInsertable(); + } + + @Override + public boolean isIncludedInUpdate() { + return columnValues.isUpdatable(); + } + + @Override + public String getContainingTableName() { + return columnValues.getTable(); + } + + + // these come from attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public String getReadFragment() { + return null; + } + + @Override + public String getWriteFragment() { + return null; + } + + @Override + public String getCheckCondition() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java index b7de45094c..275ac378cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java @@ -23,17 +23,20 @@ */ package org.hibernate.metamodel.source.annotations.attribute; +import org.hibernate.metamodel.source.annotations.entity.EntityClass; import org.hibernate.metamodel.source.binder.DiscriminatorSource; +import org.hibernate.metamodel.source.binder.RelationalValueSource; /** * @author Hardy Ferentschik */ -public class DiscriminatorSourceImpl extends SingularAttributeSourceImpl implements DiscriminatorSource { +public class DiscriminatorSourceImpl implements DiscriminatorSource { private final DiscriminatorColumnValues discriminatorColumnValues; + private final Class discriminatorType; - public DiscriminatorSourceImpl(SimpleAttribute attribute) { - super( attribute ); - discriminatorColumnValues = (DiscriminatorColumnValues)attribute.getColumnValues(); + public DiscriminatorSourceImpl(EntityClass entityClass) { + this.discriminatorColumnValues = entityClass.getDiscriminatorColumnValues(); + this.discriminatorType = entityClass.getDiscriminatorType(); } @Override @@ -45,6 +48,16 @@ public class DiscriminatorSourceImpl extends SingularAttributeSourceImpl impleme public boolean isInserted() { return discriminatorColumnValues.isIncludedInSql(); } + + @Override + public RelationalValueSource getDiscriminatorRelationalValueSource() { + return new ColumnValuesSourceImpl( discriminatorColumnValues ); + } + + @Override + public String getExplicitHibernateTypeName() { + return discriminatorType.getName(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java index 4054dba553..831fe5321a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java @@ -27,7 +27,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; -import javax.persistence.DiscriminatorType; import javax.persistence.FetchType; import org.jboss.jandex.AnnotationInstance; @@ -58,11 +57,6 @@ public class SimpleAttribute extends MappedAttribute { */ private final boolean isVersioned; - /** - * Is this property a discriminator property. - */ - private final boolean isDiscriminator; - /** * Whether a change of the property's value triggers a version increment of the entity (in case of optimistic * locking). @@ -107,44 +101,9 @@ public class SimpleAttribute extends MappedAttribute { return attribute; } - public static SimpleAttribute createDiscriminatorAttribute(Map> annotations) { - AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation( - annotations, JPADotNames.DISCRIMINATOR_COLUMN - ); - String name = DiscriminatorColumnValues.DEFAULT_DISCRIMINATOR_COLUMN_NAME; - Class type = String.class; // string is the discriminator default - if ( discriminatorOptionsAnnotation != null ) { - name = discriminatorOptionsAnnotation.value( "name" ).asString(); - - DiscriminatorType discriminatorType = Enum.valueOf( - DiscriminatorType.class, discriminatorOptionsAnnotation.value( "discriminatorType" ).asEnum() - ); - switch ( discriminatorType ) { - case STRING: { - type = String.class; - break; - } - case CHAR: { - type = Character.class; - break; - } - case INTEGER: { - type = Integer.class; - break; - } - default: { - throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType ); - } - } - } - return new SimpleAttribute( name, type, annotations, true ); - } - SimpleAttribute(String name, Class type, Map> annotations, boolean isDiscriminator) { super( name, type, annotations ); - this.isDiscriminator = isDiscriminator; - AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID ); AnnotationInstance embeddedIdAnnotation = JandexHelper.getSingleAnnotation( annotations, @@ -194,10 +153,6 @@ public class SimpleAttribute extends MappedAttribute { return isVersioned; } - public boolean isDiscriminator() { - return isDiscriminator; - } - public boolean isLazy() { return isLazy; } @@ -240,7 +195,6 @@ public class SimpleAttribute extends MappedAttribute { sb.append( "SimpleAttribute" ); sb.append( "{isId=" ).append( isId ); sb.append( ", isVersioned=" ).append( isVersioned ); - sb.append( ", isDiscriminator=" ).append( isDiscriminator ); sb.append( ", isOptimisticLockable=" ).append( isOptimisticLockable ); sb.append( ", isLazy=" ).append( isLazy ); sb.append( ", isOptional=" ).append( isOptional ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java index 04c63091a7..33ad9572ed 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.persistence.AccessType; +import javax.persistence.DiscriminatorType; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; @@ -51,7 +52,7 @@ import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; import org.hibernate.metamodel.source.annotations.HibernateDotNames; import org.hibernate.metamodel.source.annotations.JPADotNames; import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.SimpleAttribute; +import org.hibernate.metamodel.source.annotations.attribute.DiscriminatorColumnValues; import org.hibernate.metamodel.source.binder.TableSource; /** @@ -88,10 +89,9 @@ public class EntityClass extends ConfiguredClass { private boolean isLazy; private String proxy; - /** - * The discriminator attribute or {@code null} in case none exists. - */ - private SimpleAttribute discriminatorAttribute; + private DiscriminatorColumnValues discriminatorColumnValues; + private Class discriminatorType; + private String discriminatorMatchValue; public EntityClass( ClassInfo classInfo, @@ -114,13 +114,15 @@ public class EntityClass extends ConfiguredClass { processCustomSqlAnnotations(); processProxyGeneration(); - if ( InheritanceType.SINGLE_TABLE.equals( inheritanceType ) ) { - discriminatorAttribute = SimpleAttribute.createDiscriminatorAttribute( classInfo.annotations() ); - } + processDiscriminator(); } - public SimpleAttribute getDiscriminatorAttribute() { - return discriminatorAttribute; + public DiscriminatorColumnValues getDiscriminatorColumnValues() { + return discriminatorColumnValues; + } + + public Class getDiscriminatorType() { + return discriminatorType; } public IdType getIdType() { @@ -303,6 +305,49 @@ public class EntityClass extends ConfiguredClass { return idAnnotationList; } + private void processDiscriminator() { + if ( !InheritanceType.SINGLE_TABLE.equals( inheritanceType ) ) { + return; + } + + final AnnotationInstance discriminatorValueAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), JPADotNames.DISCRIMINATOR_VALUE + ); + if ( discriminatorValueAnnotation != null ) { + this.discriminatorMatchValue = discriminatorValueAnnotation.value().asString(); + } + + final AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation( + getClassInfo(), JPADotNames.DISCRIMINATOR_COLUMN + ); + Class type = String.class; // string is the discriminator default + if ( discriminatorOptionsAnnotation != null ) { + DiscriminatorType discriminatorType = Enum.valueOf( + DiscriminatorType.class, discriminatorOptionsAnnotation.value( "discriminatorType" ).asEnum() + ); + switch ( discriminatorType ) { + case STRING: { + type = String.class; + break; + } + case CHAR: { + type = Character.class; + break; + } + case INTEGER: { + type = Integer.class; + break; + } + default: { + throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType ); + } + } + } + + discriminatorColumnValues = new DiscriminatorColumnValues( getClassInfo().annotations() ); + discriminatorType = type; + } + private void processHibernateEntitySpecificAnnotations() { final AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.ENTITY @@ -618,6 +663,10 @@ public class EntityClass extends ConfiguredClass { return batchSizeAnnotation == null ? -1 : batchSizeAnnotation.value( "size" ).asInt(); } + public String getDiscriminatorMatchValue() { + return discriminatorMatchValue; + } + class TableSourceImpl implements TableSource { private final String schema; private final String catalog; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java index 9c331d8de3..342bfefda6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java @@ -198,9 +198,8 @@ public class EntitySourceImpl implements EntitySource { } @Override - public String getDiscriminatorValue() { - return ( (DiscriminatorColumnValues) entityClass.getDiscriminatorAttribute() - .getColumnValues() ).getDiscriminatorValue(); + public String getDiscriminatorMatchValue() { + return entityClass.getDiscriminatorMatchValue(); } class LocalBindingContextImpl implements LocalBindingContext { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java index 97fc4642f9..559223334a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java @@ -77,11 +77,11 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity @Override public DiscriminatorSource getDiscriminatorSource() { - DiscriminatorSource attributeSource = null; - if ( getEntityClass().getDiscriminatorAttribute() != null ) { - attributeSource = new DiscriminatorSourceImpl( getEntityClass().getDiscriminatorAttribute() ); + DiscriminatorSource discriminatorSource = null; + if ( getEntityClass().getDiscriminatorColumnValues() != null ) { + discriminatorSource = new DiscriminatorSourceImpl( getEntityClass() ); } - return attributeSource; + return discriminatorSource; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java index 8842b516e4..f8d88478b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java @@ -51,6 +51,7 @@ import org.hibernate.metamodel.domain.Entity; import org.hibernate.metamodel.domain.PluralAttribute; import org.hibernate.metamodel.domain.SingularAttribute; import org.hibernate.metamodel.relational.Column; +import org.hibernate.metamodel.relational.DerivedValue; import org.hibernate.metamodel.relational.Identifier; import org.hibernate.metamodel.relational.Schema; import org.hibernate.metamodel.relational.SimpleValue; @@ -355,18 +356,27 @@ public class Binder { return; } - SimpleSingularAttributeBinding attributeBinding = doBasicSingularAttributeBindingCreation( - discriminatorSource, entityBinding - ); EntityDiscriminator discriminator = new EntityDiscriminator(); - discriminator.setValueBinding( attributeBinding ); + SimpleValue relationalValue = makeSimpleValue( + entityBinding, + discriminatorSource.getDiscriminatorRelationalValueSource() + ); + discriminator.setBoundValue( relationalValue ); + + discriminator.getExplicitHibernateTypeDescriptor().setExplicitTypeName( + discriminatorSource.getExplicitHibernateTypeName() != null + ? discriminatorSource.getExplicitHibernateTypeName() + : "string" + ); + discriminator.setInserted( discriminatorSource.isInserted() ); discriminator.setForced( discriminatorSource.isForced() ); + entityBinding.getHierarchyDetails().setEntityDiscriminator( discriminator ); } private void bindDiscriminatorValue(SubclassEntitySource entitySource, EntityBinding entityBinding) { - final String discriminatorValue = entitySource.getDiscriminatorValue(); + final String discriminatorValue = entitySource.getDiscriminatorMatchValue(); if ( discriminatorValue == null ) { return; } @@ -637,17 +647,7 @@ public class Binder { if ( ColumnSource.class.isInstance( valueSource ) ) { final ColumnSource columnSource = ColumnSource.class.cast( valueSource ); - final Column column = table.locateOrCreateColumn( columnSource.getName() ); - column.setNullable( columnSource.isNullable() ); - column.setDefaultValue( columnSource.getDefaultValue() ); - column.setSqlType( columnSource.getSqlType() ); - column.setSize( columnSource.getSize() ); - column.setDatatype( columnSource.getDatatype() ); - column.setReadFragment( columnSource.getReadFragment() ); - column.setWriteFragment( columnSource.getWriteFragment() ); - column.setUnique( columnSource.isUnique() ); - column.setCheckCondition( columnSource.getCheckCondition() ); - column.setComment( columnSource.getComment() ); + final Column column = makeColumn( (ColumnSource) valueSource, table ); valueBindings.add( new SimpleValueBinding( column, @@ -659,7 +659,7 @@ public class Binder { else { valueBindings.add( new SimpleValueBinding( - table.locateOrCreateDerivedValue( ( (DerivedValueSource) valueSource ).getExpression() ) + makeDerivedValue( ((DerivedValueSource) valueSource), table ) ) ); } @@ -669,7 +669,6 @@ public class Binder { final String name = metadata.getOptions() .getNamingStrategy() .propertyToColumnName( attributeBinding.getAttribute().getName() ); - final SimpleValueBinding valueBinding = new SimpleValueBinding(); valueBindings.add( new SimpleValueBinding( attributeBinding.getEntityBinding().getBaseTable().locateOrCreateColumn( name ) @@ -679,6 +678,38 @@ public class Binder { attributeBinding.setSimpleValueBindings( valueBindings ); } + private SimpleValue makeSimpleValue( + EntityBinding entityBinding, + RelationalValueSource valueSource) { + final TableSpecification table = entityBinding.getTable( valueSource.getContainingTableName() ); + + if ( ColumnSource.class.isInstance( valueSource ) ) { + return makeColumn( (ColumnSource) valueSource, table ); + } + else { + return makeDerivedValue( (DerivedValueSource) valueSource, table ); + } + } + + private Column makeColumn(ColumnSource columnSource, TableSpecification table) { + final Column column = table.locateOrCreateColumn( columnSource.getName() ); + column.setNullable( columnSource.isNullable() ); + column.setDefaultValue( columnSource.getDefaultValue() ); + column.setSqlType( columnSource.getSqlType() ); + column.setSize( columnSource.getSize() ); + column.setDatatype( columnSource.getDatatype() ); + column.setReadFragment( columnSource.getReadFragment() ); + column.setWriteFragment( columnSource.getWriteFragment() ); + column.setUnique( columnSource.isUnique() ); + column.setCheckCondition( columnSource.getCheckCondition() ); + column.setComment( columnSource.getComment() ); + return column; + } + + private DerivedValue makeDerivedValue(DerivedValueSource derivedValueSource, TableSpecification table) { + return table.locateOrCreateDerivedValue( derivedValueSource.getExpression() ); + } + private void processFetchProfiles(EntitySource entitySource, EntityBinding entityBinding) { // todo : process the entity-local fetch-profile declaration } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java index 1d43661600..1689bf79a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java @@ -24,9 +24,19 @@ package org.hibernate.metamodel.source.binder; /** + * Source for discriminator metadata. + *

+ * NOTE : extends the notion of {@link SingularAttributeSource} only for convenience in that both share many of + * the same source options. However, a discriminator is NEVER a physical attribute on the domain model. + * * @author Hardy Ferentschik + * @author Steve Ebersole */ -public interface DiscriminatorSource extends SingularAttributeSource { +public interface DiscriminatorSource { + public RelationalValueSource getDiscriminatorRelationalValueSource(); + + public String getExplicitHibernateTypeName(); + /** * "Forces" Hibernate to specify the allowed discriminator values, even when retrieving all instances of the root class. * diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java index a37a87a754..c8cf698a55 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java @@ -190,5 +190,5 @@ public interface EntitySource extends SubclassEntityContainer, AttributeSourceCo * @return the actual discriminator value in case of a single table inheritance or {@code null} in case there is no * explicit value or a different inheritance scheme */ - public String getDiscriminatorValue(); + public String getDiscriminatorMatchValue(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java index a5e2dcf6c5..e35bb07874 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java @@ -244,7 +244,7 @@ public abstract class AbstractEntitySourceImpl implements EntitySource { } @Override - public String getDiscriminatorValue() { + public String getDiscriminatorMatchValue() { return null; //To change body of implemented methods use File | Settings | File Templates. } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java index b3a139b2e5..b29a2ae9fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java @@ -26,11 +26,13 @@ package org.hibernate.metamodel.source.hbm; import org.hibernate.EntityMode; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.binding.Caching; import org.hibernate.metamodel.binding.IdGenerator; import org.hibernate.metamodel.source.MappingException; import org.hibernate.metamodel.source.binder.DiscriminatorSource; import org.hibernate.metamodel.source.binder.IdentifierSource; +import org.hibernate.metamodel.source.binder.RelationalValueSource; import org.hibernate.metamodel.source.binder.RootEntitySource; import org.hibernate.metamodel.source.binder.SimpleIdentifierSource; import org.hibernate.metamodel.source.binder.SingularAttributeSource; @@ -188,7 +190,55 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro @Override public DiscriminatorSource getDiscriminatorSource() { - // todo : implement - return null; + final XMLHibernateMapping.XMLClass.XMLDiscriminator discriminatorElement = entityElement().getDiscriminator(); + if ( discriminatorElement == null ) { + return null; + } + + return new DiscriminatorSource() { + @Override + public RelationalValueSource getDiscriminatorRelationalValueSource() { + if ( StringHelper.isNotEmpty( discriminatorElement.getColumnAttribute() ) ) { + return new ColumnAttributeSourceImpl( + null, // root table + discriminatorElement.getColumnAttribute(), + discriminatorElement.isInsert(), + discriminatorElement.isInsert() + ); + } + else if ( StringHelper.isNotEmpty( discriminatorElement.getFormulaAttribute() ) ) { + return new FormulaImpl( null, discriminatorElement.getFormulaAttribute() ); + } + else if ( discriminatorElement.getColumn() != null ) { + return new ColumnSourceImpl( + null, // root table + discriminatorElement.getColumn(), + discriminatorElement.isInsert(), + discriminatorElement.isInsert() + ); + } + else if ( StringHelper.isNotEmpty( discriminatorElement.getFormula() ) ) { + return new FormulaImpl( null, discriminatorElement.getFormula() ); + } + else { + throw new MappingException( "could not determine source of discriminator mapping", getOrigin() ); + } + } + + @Override + public String getExplicitHibernateTypeName() { + return discriminatorElement.getType(); + } + + @Override + public boolean isForced() { + return discriminatorElement.isForce(); + } + + @Override + public boolean isInserted() { + return discriminatorElement.isInsert(); + } + }; } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 6c7e33d7cc..7935f32e5b 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -547,17 +547,13 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { boolean isPolymorphic = ! entityBinding.isRoot() || hasSubclasses; final Object discriminatorValue; if ( isPolymorphic ) { - org.hibernate.metamodel.relational.Value discrimValue = - entityBinding.getHierarchyDetails().getEntityDiscriminator().getValueBinding().getValue(); - if (discrimValue==null) { + SimpleValue discriminatorRelationalValue = entityBinding.getHierarchyDetails().getEntityDiscriminator().getBoundValue(); + if ( discriminatorRelationalValue == null ) { throw new MappingException("discriminator mapping required for single table polymorphic persistence"); } forceDiscriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator().isForced(); - if ( ! SimpleValue.class.isInstance( discrimValue ) ) { - throw new MappingException( "discriminator must be mapped to a single column or formula." ); - } - if ( DerivedValue.class.isInstance( discrimValue ) ) { - DerivedValue formula = ( DerivedValue ) discrimValue; + if ( DerivedValue.class.isInstance( discriminatorRelationalValue ) ) { + DerivedValue formula = ( DerivedValue ) discriminatorRelationalValue; discriminatorFormula = formula.getExpression(); discriminatorFormulaTemplate = getTemplateFromString( formula.getExpression(), factory ); discriminatorColumnName = null; @@ -565,8 +561,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { discriminatorColumnReaderTemplate = null; discriminatorAlias = "clazz_"; } - else if ( org.hibernate.metamodel.relational.Column.class.isInstance( discrimValue ) ) { - org.hibernate.metamodel.relational.Column column = ( org.hibernate.metamodel.relational.Column ) discrimValue; + else { + org.hibernate.metamodel.relational.Column column = ( org.hibernate.metamodel.relational.Column ) discriminatorRelationalValue; discriminatorColumnName = column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); discriminatorColumnReaders = column.getReadFragment() == null ? @@ -580,16 +576,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { discriminatorFormula = null; discriminatorFormulaTemplate = null; } - else { - throw new MappingException( "Unknown discriminator value type:" + discrimValue.toLoggableString() ); - } - discriminatorType = - entityBinding - .getHierarchyDetails() - .getEntityDiscriminator() - .getValueBinding() - .getHibernateTypeDescriptor() - .getResolvedTypeMapping(); + + discriminatorType = entityBinding.getHierarchyDetails() + .getEntityDiscriminator() + .getExplicitHibernateTypeDescriptor() + .getResolvedTypeMapping(); if ( entityBinding.getDiscriminatorMatchValue() == null ) { discriminatorValue = NULL_DISCRIMINATOR; discriminatorSQLValue = InFragment.NULL; @@ -606,9 +597,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { discriminatorInsertable = false; } else { - discriminatorInsertable = - entityBinding.getHierarchyDetails().getEntityDiscriminator().isInserted() && - ! DerivedValue.class.isInstance( discrimValue ); + discriminatorInsertable = entityBinding.getHierarchyDetails().getEntityDiscriminator().isInserted() + && ! DerivedValue.class.isInstance( discriminatorRelationalValue ); try { DiscriminatorType dtype = ( DiscriminatorType ) discriminatorType; discriminatorValue = dtype.stringToObject( entityBinding.getDiscriminatorMatchValue() );