HHH-6911 - Write DiscriminatorValue to DiscriminatorColumn when combined with InheritanceType#JOINED
This commit is contained in:
parent
e64e89b2cc
commit
5329bba1ea
|
@ -40,6 +40,7 @@ import javax.persistence.Basic;
|
||||||
import javax.persistence.Cacheable;
|
import javax.persistence.Cacheable;
|
||||||
import javax.persistence.CollectionTable;
|
import javax.persistence.CollectionTable;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.DiscriminatorColumn;
|
||||||
import javax.persistence.DiscriminatorType;
|
import javax.persistence.DiscriminatorType;
|
||||||
import javax.persistence.DiscriminatorValue;
|
import javax.persistence.DiscriminatorValue;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
|
@ -97,6 +98,7 @@ import org.hibernate.annotations.CascadeType;
|
||||||
import org.hibernate.annotations.Check;
|
import org.hibernate.annotations.Check;
|
||||||
import org.hibernate.annotations.CollectionId;
|
import org.hibernate.annotations.CollectionId;
|
||||||
import org.hibernate.annotations.Columns;
|
import org.hibernate.annotations.Columns;
|
||||||
|
import org.hibernate.annotations.DiscriminatorFormula;
|
||||||
import org.hibernate.annotations.DiscriminatorOptions;
|
import org.hibernate.annotations.DiscriminatorOptions;
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchProfile;
|
import org.hibernate.annotations.FetchProfile;
|
||||||
|
@ -635,12 +637,27 @@ public final class AnnotationBinder {
|
||||||
Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(
|
Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(
|
||||||
clazzToProcess, mappings, inheritanceState, superEntity
|
clazzToProcess, mappings, inheritanceState, superEntity
|
||||||
);
|
);
|
||||||
Ejb3DiscriminatorColumn discriminatorColumn = null;
|
|
||||||
|
final Ejb3DiscriminatorColumn discriminatorColumn;
|
||||||
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
||||||
discriminatorColumn = processDiscriminatorProperties(
|
discriminatorColumn = processSingleTableDiscriminatorProperties(
|
||||||
clazzToProcess, mappings, inheritanceState, entityBinder
|
clazzToProcess,
|
||||||
|
mappings,
|
||||||
|
inheritanceState,
|
||||||
|
entityBinder
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) ) {
|
||||||
|
discriminatorColumn = processJoinedDiscriminatorProperties(
|
||||||
|
clazzToProcess,
|
||||||
|
mappings,
|
||||||
|
inheritanceState,
|
||||||
|
entityBinder
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
discriminatorColumn = null;
|
||||||
|
}
|
||||||
|
|
||||||
entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
|
entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
|
||||||
entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
|
entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
|
||||||
|
@ -685,7 +702,13 @@ public final class AnnotationBinder {
|
||||||
|
|
||||||
OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class );
|
OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class );
|
||||||
boolean onDeleteAppropriate = false;
|
boolean onDeleteAppropriate = false;
|
||||||
if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) && inheritanceState.hasParents() ) {
|
|
||||||
|
// todo : sucks that this is separate from RootClass distinction
|
||||||
|
final boolean isInheritanceRoot = !inheritanceState.hasParents();
|
||||||
|
final boolean hasSubclasses = inheritanceState.hasSiblings();
|
||||||
|
|
||||||
|
if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) ) {
|
||||||
|
if ( inheritanceState.hasParents() ) {
|
||||||
onDeleteAppropriate = true;
|
onDeleteAppropriate = true;
|
||||||
final JoinedSubclass jsc = ( JoinedSubclass ) persistentClass;
|
final JoinedSubclass jsc = ( JoinedSubclass ) persistentClass;
|
||||||
SimpleValue key = new DependantValue( mappings, jsc.getTable(), jsc.getIdentifier() );
|
SimpleValue key = new DependantValue( mappings, jsc.getTable(), jsc.getIdentifier() );
|
||||||
|
@ -704,27 +727,46 @@ public final class AnnotationBinder {
|
||||||
SecondPass sp = new JoinedSubclassFkSecondPass( jsc, inheritanceJoinedColumns, key, mappings );
|
SecondPass sp = new JoinedSubclassFkSecondPass( jsc, inheritanceJoinedColumns, key, mappings );
|
||||||
mappings.addSecondPass( sp );
|
mappings.addSecondPass( sp );
|
||||||
mappings.addSecondPass( new CreateKeySecondPass( jsc ) );
|
mappings.addSecondPass( new CreateKeySecondPass( jsc ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
|
||||||
if ( ! inheritanceState.hasParents() ) {
|
if ( isInheritanceRoot ) {
|
||||||
if ( inheritanceState.hasSiblings() || !discriminatorColumn.isImplicit() ) {
|
// the class we are processing is the root of the hierarchy, see if we had a discriminator column
|
||||||
//need a discriminator column
|
// (it is perfectly valid for joined subclasses to not have discriminators).
|
||||||
bindDiscriminatorToPersistentClass(
|
if ( discriminatorColumn != null ) {
|
||||||
|
// we have a discriminator column
|
||||||
|
if ( hasSubclasses || !discriminatorColumn.isImplicit() ) {
|
||||||
|
bindDiscriminatorColumnToRootPersistentClass(
|
||||||
(RootClass) persistentClass,
|
(RootClass) persistentClass,
|
||||||
discriminatorColumn,
|
discriminatorColumn,
|
||||||
entityBinder.getSecondaryTables(),
|
entityBinder.getSecondaryTables(),
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
mappings
|
mappings
|
||||||
);
|
);
|
||||||
entityBinder.bindDiscriminatorValue();//bind it again since the type might have changed
|
//bind it again since the type might have changed
|
||||||
|
entityBinder.bindDiscriminatorValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {
|
|
||||||
//nothing to do
|
|
||||||
}
|
}
|
||||||
if (onDeleteAnn != null && !onDeleteAppropriate) LOG.invalidOnDeleteAnnotation(propertyHolder.getEntityName());
|
else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
||||||
|
if ( isInheritanceRoot ) {
|
||||||
|
if ( hasSubclasses || !discriminatorColumn.isImplicit() ) {
|
||||||
|
bindDiscriminatorColumnToRootPersistentClass(
|
||||||
|
(RootClass) persistentClass,
|
||||||
|
discriminatorColumn,
|
||||||
|
entityBinder.getSecondaryTables(),
|
||||||
|
propertyHolder,
|
||||||
|
mappings
|
||||||
|
);
|
||||||
|
//bind it again since the type might have changed
|
||||||
|
entityBinder.bindDiscriminatorValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( onDeleteAnn != null && !onDeleteAppropriate ) {
|
||||||
|
LOG.invalidOnDeleteAnnotation(propertyHolder.getEntityName());
|
||||||
|
}
|
||||||
|
|
||||||
// try to find class level generators
|
// try to find class level generators
|
||||||
HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );
|
HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );
|
||||||
|
@ -782,32 +824,43 @@ public final class AnnotationBinder {
|
||||||
entityBinder.processComplementaryTableDefinitions( tabAnn );
|
entityBinder.processComplementaryTableDefinitions( tabAnn );
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse everything discriminator column relevant in case of single table inheritance
|
/**
|
||||||
private static Ejb3DiscriminatorColumn processDiscriminatorProperties(XClass clazzToProcess, Mappings mappings, InheritanceState inheritanceState, EntityBinder entityBinder) {
|
* Process all discriminator-related metadata per rules for "single table" inheritance
|
||||||
|
*/
|
||||||
|
private static Ejb3DiscriminatorColumn processSingleTableDiscriminatorProperties(
|
||||||
|
XClass clazzToProcess,
|
||||||
|
Mappings mappings,
|
||||||
|
InheritanceState inheritanceState,
|
||||||
|
EntityBinder entityBinder) {
|
||||||
|
final boolean isRoot = !inheritanceState.hasParents();
|
||||||
|
|
||||||
Ejb3DiscriminatorColumn discriminatorColumn = null;
|
Ejb3DiscriminatorColumn discriminatorColumn = null;
|
||||||
javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
|
javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
|
||||||
javax.persistence.DiscriminatorColumn.class
|
javax.persistence.DiscriminatorColumn.class
|
||||||
);
|
);
|
||||||
DiscriminatorType discriminatorType = discAnn != null ?
|
DiscriminatorType discriminatorType = discAnn != null
|
||||||
discAnn.discriminatorType() :
|
? discAnn.discriminatorType()
|
||||||
DiscriminatorType.STRING;
|
: DiscriminatorType.STRING;
|
||||||
|
|
||||||
org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
|
org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
|
||||||
org.hibernate.annotations.DiscriminatorFormula.class
|
org.hibernate.annotations.DiscriminatorFormula.class
|
||||||
);
|
);
|
||||||
if ( !inheritanceState.hasParents() ) {
|
if ( isRoot ) {
|
||||||
discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
|
discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
|
||||||
discriminatorType, discAnn, discFormulaAnn, mappings
|
discriminatorType,
|
||||||
|
discAnn,
|
||||||
|
discFormulaAnn,
|
||||||
|
mappings
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( discAnn != null && inheritanceState.hasParents() ) {
|
if ( discAnn != null && !isRoot ) {
|
||||||
LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() );
|
LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
String discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?
|
final String discriminatorValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class )
|
||||||
clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :
|
? clazzToProcess.getAnnotation( DiscriminatorValue.class ).value()
|
||||||
null;
|
: null;
|
||||||
entityBinder.setDiscriminatorValue( discrimValue );
|
entityBinder.setDiscriminatorValue( discriminatorValue );
|
||||||
|
|
||||||
DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );
|
DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );
|
||||||
if ( discriminatorOptions != null) {
|
if ( discriminatorOptions != null) {
|
||||||
|
@ -818,6 +871,53 @@ public final class AnnotationBinder {
|
||||||
return discriminatorColumn;
|
return discriminatorColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process all discriminator-related metadata per rules for "joined" inheritance
|
||||||
|
*/
|
||||||
|
private static Ejb3DiscriminatorColumn processJoinedDiscriminatorProperties(
|
||||||
|
XClass clazzToProcess,
|
||||||
|
Mappings mappings,
|
||||||
|
InheritanceState inheritanceState,
|
||||||
|
EntityBinder entityBinder) {
|
||||||
|
if ( clazzToProcess.isAnnotationPresent( DiscriminatorFormula.class ) ) {
|
||||||
|
throw new MappingException( "@DiscriminatorFormula on joined inheritance not supported at this time" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// DiscriminatorValue handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
final DiscriminatorValue discriminatorValueAnnotation = clazzToProcess.getAnnotation( DiscriminatorValue.class );
|
||||||
|
final String discriminatorValue = discriminatorValueAnnotation != null
|
||||||
|
? clazzToProcess.getAnnotation( DiscriminatorValue.class ).value()
|
||||||
|
: null;
|
||||||
|
entityBinder.setDiscriminatorValue( discriminatorValue );
|
||||||
|
|
||||||
|
|
||||||
|
// DiscriminatorColumn handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
final DiscriminatorColumn discriminatorColumnAnnotation = clazzToProcess.getAnnotation( DiscriminatorColumn.class );
|
||||||
|
if ( !inheritanceState.hasParents() ) {
|
||||||
|
if ( discriminatorColumnAnnotation != null || mappings.useImplicitDiscriminatorColumnForJoinedInheritance() ) {
|
||||||
|
final DiscriminatorType discriminatorType = discriminatorColumnAnnotation != null
|
||||||
|
? discriminatorColumnAnnotation.discriminatorType()
|
||||||
|
: DiscriminatorType.STRING;
|
||||||
|
return Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
|
||||||
|
discriminatorType,
|
||||||
|
discriminatorColumnAnnotation,
|
||||||
|
null,
|
||||||
|
mappings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( discriminatorColumnAnnotation != null ) {
|
||||||
|
LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static void processIdPropertiesIfNotAlready(
|
private static void processIdPropertiesIfNotAlready(
|
||||||
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
||||||
Mappings mappings,
|
Mappings mappings,
|
||||||
|
@ -1375,7 +1475,7 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void bindDiscriminatorToPersistentClass(
|
private static void bindDiscriminatorColumnToRootPersistentClass(
|
||||||
RootClass rootClass,
|
RootClass rootClass,
|
||||||
Ejb3DiscriminatorColumn discriminatorColumn,
|
Ejb3DiscriminatorColumn discriminatorColumn,
|
||||||
Map<String, Join> secondaryTables,
|
Map<String, Join> secondaryTables,
|
||||||
|
@ -1387,10 +1487,10 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
discriminatorColumn.setJoins( secondaryTables );
|
discriminatorColumn.setJoins( secondaryTables );
|
||||||
discriminatorColumn.setPropertyHolder( propertyHolder );
|
discriminatorColumn.setPropertyHolder( propertyHolder );
|
||||||
SimpleValue discrim = new SimpleValue( mappings, rootClass.getTable() );
|
SimpleValue discriminatorColumnBinding = new SimpleValue( mappings, rootClass.getTable() );
|
||||||
rootClass.setDiscriminator( discrim );
|
rootClass.setDiscriminator( discriminatorColumnBinding );
|
||||||
discriminatorColumn.linkWithValue( discrim );
|
discriminatorColumn.linkWithValue( discriminatorColumnBinding );
|
||||||
discrim.setTypeName( discriminatorColumn.getDiscriminatorTypeName() );
|
discriminatorColumnBinding.setTypeName( discriminatorColumn.getDiscriminatorTypeName() );
|
||||||
rootClass.setPolymorphic( true );
|
rootClass.setPolymorphic( true );
|
||||||
if ( LOG.isTraceEnabled() ) {
|
if ( LOG.isTraceEnabled() ) {
|
||||||
LOG.tracev( "Setting discriminator for entity {0}", rootClass.getEntityName() );
|
LOG.tracev( "Setting discriminator for entity {0}", rootClass.getEntityName() );
|
||||||
|
|
|
@ -604,6 +604,21 @@ public interface AvailableSettings {
|
||||||
|
|
||||||
String FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT = "hibernate.discriminator.force_in_select";
|
String FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT = "hibernate.discriminator.force_in_select";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The legacy behavior of Hibernate is to not use discriminators for joined inheritance (Hibernate does not need
|
||||||
|
* the discriminator...). However, some JPA providers do need the discriminator for handling joined inheritance.
|
||||||
|
* In the interest of portability this capability has been added to Hibernate too.
|
||||||
|
* <p/>
|
||||||
|
* However, we want to make sure that legacy applications continue to work as well. Which puts us in a bind in
|
||||||
|
* terms of how to handle "implicit" discriminator mappings. The solution is to assume that the absence of
|
||||||
|
* discriminator metadata means to follow the legacy behavior *unless* this setting is enabled. With this setting
|
||||||
|
* enabled, Hibernate will interpret the absence of discriminator metadata as an indication to use the JPA
|
||||||
|
* defined defaults for these absent annotations.
|
||||||
|
*
|
||||||
|
* See Hibernate Jira issue HHH-6911 for additional background info,
|
||||||
|
*/
|
||||||
|
String IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.implicit_for_joined";
|
||||||
|
|
||||||
String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
|
String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
|
||||||
|
|
||||||
String HQL_BULK_ID_STRATEGY = "hibernate.hql.bulk_id_strategy";
|
String HQL_BULK_ID_STRATEGY = "hibernate.hql.bulk_id_strategy";
|
||||||
|
@ -678,4 +693,5 @@ public interface AvailableSettings {
|
||||||
String LOG_SESSION_METRICS = "hibernate.session.events.log";
|
String LOG_SESSION_METRICS = "hibernate.session.events.log";
|
||||||
|
|
||||||
String AUTO_SESSION_EVENTS_LISTENER = "hibernate.session.events.auto";
|
String AUTO_SESSION_EVENTS_LISTENER = "hibernate.session.events.auto";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3375,6 +3375,7 @@ public class Configuration implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Boolean useNewGeneratorMappings;
|
private Boolean useNewGeneratorMappings;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean useNewGeneratorMappings() {
|
public boolean useNewGeneratorMappings() {
|
||||||
if ( useNewGeneratorMappings == null ) {
|
if ( useNewGeneratorMappings == null ) {
|
||||||
|
@ -3385,6 +3386,20 @@ public class Configuration implements Serializable {
|
||||||
return useNewGeneratorMappings;
|
return useNewGeneratorMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Boolean implicitDiscriminatorColumnForJoinedInheritance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useImplicitDiscriminatorColumnForJoinedInheritance() {
|
||||||
|
if ( implicitDiscriminatorColumnForJoinedInheritance == null ) {
|
||||||
|
final String booleanName = getConfigurationProperties()
|
||||||
|
.getProperty( AvailableSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS );
|
||||||
|
implicitDiscriminatorColumnForJoinedInheritance = Boolean.valueOf( booleanName );
|
||||||
|
}
|
||||||
|
return implicitDiscriminatorColumnForJoinedInheritance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Boolean useNationalizedCharacterData;
|
private Boolean useNationalizedCharacterData;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,8 +34,8 @@ import org.hibernate.annotations.DiscriminatorFormula;
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
public class Ejb3DiscriminatorColumn extends Ejb3Column {
|
public class Ejb3DiscriminatorColumn extends Ejb3Column {
|
||||||
private static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "DTYPE";
|
public static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "DTYPE";
|
||||||
private static final String DEFAULT_DISCRIMINATOR_TYPE = "string";
|
public static final String DEFAULT_DISCRIMINATOR_TYPE = "string";
|
||||||
private static final int DEFAULT_DISCRIMINATOR_LENGTH = 31;
|
private static final int DEFAULT_DISCRIMINATOR_LENGTH = 31;
|
||||||
|
|
||||||
private String discriminatorTypeName;
|
private String discriminatorTypeName;
|
||||||
|
|
|
@ -797,6 +797,17 @@ public interface Mappings {
|
||||||
*/
|
*/
|
||||||
public boolean useNewGeneratorMappings();
|
public boolean useNewGeneratorMappings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we handle discriminators for joined inheritance per legacy Hibernate rules, or
|
||||||
|
* Should we use the new generator strategy mappings. This is controlled by the
|
||||||
|
* {@link AvailableSettings#USE_NEW_ID_GENERATOR_MAPPINGS} setting.
|
||||||
|
*
|
||||||
|
* @return True if the new generators should be used, false otherwise.
|
||||||
|
*
|
||||||
|
* @see AvailableSettings#IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS
|
||||||
|
*/
|
||||||
|
public boolean useImplicitDiscriminatorColumnForJoinedInheritance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should we use nationalized variants of character data by default? This is controlled by the
|
* Should we use nationalized variants of character data by default? This is controlled by the
|
||||||
* {@link AvailableSettings#USE_NATIONALIZED_CHARACTER_DATA} setting.
|
* {@link AvailableSettings#USE_NATIONALIZED_CHARACTER_DATA} setting.
|
||||||
|
|
|
@ -43,8 +43,10 @@ import org.hibernate.engine.spi.Mapping;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.DynamicFilterAliasGenerator;
|
import org.hibernate.internal.DynamicFilterAliasGenerator;
|
||||||
import org.hibernate.internal.FilterAliasGenerator;
|
import org.hibernate.internal.FilterAliasGenerator;
|
||||||
|
import org.hibernate.internal.util.MarkerObject;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.Formula;
|
||||||
import org.hibernate.mapping.Join;
|
import org.hibernate.mapping.Join;
|
||||||
import org.hibernate.mapping.KeyValue;
|
import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.MappedSuperclass;
|
import org.hibernate.mapping.MappedSuperclass;
|
||||||
|
@ -53,11 +55,16 @@ import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Selectable;
|
import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.mapping.Subclass;
|
import org.hibernate.mapping.Subclass;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.hibernate.mapping.Value;
|
||||||
import org.hibernate.metamodel.binding.EntityBinding;
|
import org.hibernate.metamodel.binding.EntityBinding;
|
||||||
import org.hibernate.sql.CaseFragment;
|
import org.hibernate.sql.CaseFragment;
|
||||||
|
import org.hibernate.sql.InFragment;
|
||||||
|
import org.hibernate.sql.Insert;
|
||||||
import org.hibernate.sql.SelectFragment;
|
import org.hibernate.sql.SelectFragment;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.*;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.DiscriminatorType;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An <tt>EntityPersister</tt> implementing the normalized "table-per-subclass"
|
* An <tt>EntityPersister</tt> implementing the normalized "table-per-subclass"
|
||||||
|
@ -66,6 +73,13 @@ import org.hibernate.type.Type;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
|
private static final Logger log = Logger.getLogger( JoinedSubclassEntityPersister.class );
|
||||||
|
|
||||||
|
private static final String IMPLICIT_DISCRIMINATOR_ALIAS = "clazz_";
|
||||||
|
private static final Object NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>");
|
||||||
|
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject("<not null discriminator>");
|
||||||
|
private static final String NULL_STRING = "null";
|
||||||
|
private static final String NOT_NULL_STRING = "not null";
|
||||||
|
|
||||||
// the class hierarchy structure
|
// the class hierarchy structure
|
||||||
private final int tableSpan;
|
private final int tableSpan;
|
||||||
|
@ -116,6 +130,9 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
|
|
||||||
private final Object discriminatorValue;
|
private final Object discriminatorValue;
|
||||||
private final String discriminatorSQLString;
|
private final String discriminatorSQLString;
|
||||||
|
private final DiscriminatorType discriminatorType;
|
||||||
|
private final String explicitDiscriminatorColumnName;
|
||||||
|
private final String discriminatorAlias;
|
||||||
|
|
||||||
// Span of the tables directly mapped by this entity and super-classes, if any
|
// Span of the tables directly mapped by this entity and super-classes, if any
|
||||||
private final int coreTableSpan;
|
private final int coreTableSpan;
|
||||||
|
@ -136,6 +153,45 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
// DISCRIMINATOR
|
// DISCRIMINATOR
|
||||||
|
|
||||||
if ( persistentClass.isPolymorphic() ) {
|
if ( persistentClass.isPolymorphic() ) {
|
||||||
|
final Value discriminatorMapping = persistentClass.getDiscriminator();
|
||||||
|
if ( discriminatorMapping != null ) {
|
||||||
|
log.debug( "Encountered explicit discriminator mapping for joined inheritance" );
|
||||||
|
|
||||||
|
final Selectable selectable = discriminatorMapping.getColumnIterator().next();
|
||||||
|
if ( Formula.class.isInstance( selectable ) ) {
|
||||||
|
throw new MappingException( "Discriminator formulas on joined inheritance hierarchies not supported at this time" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Column column = (Column) selectable;
|
||||||
|
explicitDiscriminatorColumnName = column.getQuotedName( factory.getDialect() );
|
||||||
|
discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() );
|
||||||
|
}
|
||||||
|
discriminatorType = (DiscriminatorType) persistentClass.getDiscriminator().getType();
|
||||||
|
if ( persistentClass.isDiscriminatorValueNull() ) {
|
||||||
|
discriminatorValue = NULL_DISCRIMINATOR;
|
||||||
|
discriminatorSQLString = InFragment.NULL;
|
||||||
|
}
|
||||||
|
else if ( persistentClass.isDiscriminatorValueNotNull() ) {
|
||||||
|
discriminatorValue = NOT_NULL_DISCRIMINATOR;
|
||||||
|
discriminatorSQLString = InFragment.NOT_NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
discriminatorValue = discriminatorType.stringToObject( persistentClass.getDiscriminatorValue() );
|
||||||
|
discriminatorSQLString = discriminatorType.objectToSQLString( discriminatorValue, factory.getDialect() );
|
||||||
|
}
|
||||||
|
catch (ClassCastException cce) {
|
||||||
|
throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new MappingException("Could not format discriminator value to SQL string", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
explicitDiscriminatorColumnName = null;
|
||||||
|
discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS;
|
||||||
|
discriminatorType = StandardBasicTypes.INTEGER;
|
||||||
try {
|
try {
|
||||||
discriminatorValue = persistentClass.getSubclassId();
|
discriminatorValue = persistentClass.getSubclassId();
|
||||||
discriminatorSQLString = discriminatorValue.toString();
|
discriminatorSQLString = discriminatorValue.toString();
|
||||||
|
@ -144,7 +200,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
throw new MappingException( "Could not format discriminator value to SQL string", e );
|
throw new MappingException( "Could not format discriminator value to SQL string", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
|
explicitDiscriminatorColumnName = null;
|
||||||
|
discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS;
|
||||||
|
discriminatorType = StandardBasicTypes.INTEGER;
|
||||||
discriminatorValue = null;
|
discriminatorValue = null;
|
||||||
discriminatorSQLString = null;
|
discriminatorSQLString = null;
|
||||||
}
|
}
|
||||||
|
@ -477,12 +537,35 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
subclassClosure[k] = sc.getEntityName();
|
subclassClosure[k] = sc.getEntityName();
|
||||||
try {
|
try {
|
||||||
if ( persistentClass.isPolymorphic() ) {
|
if ( persistentClass.isPolymorphic() ) {
|
||||||
|
final Object discriminatorValue;
|
||||||
|
if ( explicitDiscriminatorColumnName != null ) {
|
||||||
|
if ( sc.isDiscriminatorValueNull() ) {
|
||||||
|
discriminatorValue = NULL_DISCRIMINATOR;
|
||||||
|
}
|
||||||
|
else if ( sc.isDiscriminatorValueNotNull() ) {
|
||||||
|
discriminatorValue = NOT_NULL_DISCRIMINATOR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
discriminatorValue = discriminatorType.stringToObject( sc.getDiscriminatorValue() );
|
||||||
|
}
|
||||||
|
catch (ClassCastException cce) {
|
||||||
|
throw new MappingException( "Illegal discriminator type: " + discriminatorType.getName() );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new MappingException( "Could not format discriminator value to SQL string", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
// we now use subclass ids that are consistent across all
|
// we now use subclass ids that are consistent across all
|
||||||
// persisters for a class hierarchy, so that the use of
|
// persisters for a class hierarchy, so that the use of
|
||||||
// "foo.class = Bar" works in HQL
|
// "foo.class = Bar" works in HQL
|
||||||
Integer subclassId = sc.getSubclassId();
|
discriminatorValue = sc.getSubclassId();
|
||||||
subclassesByDiscriminatorValue.put( subclassId, sc.getEntityName() );
|
}
|
||||||
discriminatorValues[k] = subclassId.toString();
|
|
||||||
|
subclassesByDiscriminatorValue.put( discriminatorValue, sc.getEntityName() );
|
||||||
|
discriminatorValues[k] = discriminatorValue.toString();
|
||||||
int id = getTableId(
|
int id = getTableId(
|
||||||
sc.getTable().getQualifiedName(
|
sc.getTable().getQualifiedName(
|
||||||
factory.getDialect(),
|
factory.getDialect(),
|
||||||
|
@ -702,6 +785,9 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
constraintOrderedKeyColumnNames = null;
|
constraintOrderedKeyColumnNames = null;
|
||||||
discriminatorValue = null;
|
discriminatorValue = null;
|
||||||
discriminatorSQLString = null;
|
discriminatorSQLString = null;
|
||||||
|
discriminatorType = StandardBasicTypes.INTEGER;
|
||||||
|
explicitDiscriminatorColumnName = null;
|
||||||
|
discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS;
|
||||||
coreTableSpan = -1;
|
coreTableSpan = -1;
|
||||||
isNullableTable = null;
|
isNullableTable = null;
|
||||||
subclassNamesBySubclassTable = null;
|
subclassNamesBySubclassTable = null;
|
||||||
|
@ -729,21 +815,50 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getDiscriminatorType() {
|
public Type getDiscriminatorType() {
|
||||||
return StandardBasicTypes.INTEGER;
|
return discriminatorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getDiscriminatorValue() {
|
public Object getDiscriminatorValue() {
|
||||||
return discriminatorValue;
|
return discriminatorValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getDiscriminatorSQLValue() {
|
public String getDiscriminatorSQLValue() {
|
||||||
return discriminatorSQLString;
|
return discriminatorSQLString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDiscriminatorColumnName() {
|
||||||
|
return explicitDiscriminatorColumnName == null
|
||||||
|
? super.getDiscriminatorColumnName()
|
||||||
|
: explicitDiscriminatorColumnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDiscriminatorColumnReaders() {
|
||||||
|
return getDiscriminatorColumnName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDiscriminatorColumnReaderTemplate() {
|
||||||
|
return getDiscriminatorColumnName();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDiscriminatorAlias() {
|
||||||
|
return discriminatorAlias;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSubclassForDiscriminatorValue(Object value) {
|
public String getSubclassForDiscriminatorValue(Object value) {
|
||||||
return (String) subclassesByDiscriminatorValue.get( value );
|
return (String) subclassesByDiscriminatorValue.get( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addDiscriminatorToInsert(Insert insert) {
|
||||||
|
if ( explicitDiscriminatorColumnName != null ) {
|
||||||
|
insert.addColumn( explicitDiscriminatorColumnName, getDiscriminatorSQLValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Serializable[] getPropertySpaces() {
|
public Serializable[] getPropertySpaces() {
|
||||||
return spaces; // don't need subclass tables, because they can't appear in conditions
|
return spaces; // don't need subclass tables, because they can't appear in conditions
|
||||||
}
|
}
|
||||||
|
@ -858,8 +973,13 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
|
|
||||||
public void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
|
public void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
|
||||||
if ( hasSubclasses() ) {
|
if ( hasSubclasses() ) {
|
||||||
|
if ( explicitDiscriminatorColumnName == null ) {
|
||||||
select.setExtraSelectList( discriminatorFragment( name ), getDiscriminatorAlias() );
|
select.setExtraSelectList( discriminatorFragment( name ), getDiscriminatorAlias() );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
select.addColumn( name, explicitDiscriminatorColumnName, discriminatorAlias );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CaseFragment discriminatorFragment(String alias) {
|
private CaseFragment discriminatorFragment(String alias) {
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package org.hibernate.test.joinedsubclass;
|
||||||
|
|
||||||
|
import javax.persistence.DiscriminatorColumn;
|
||||||
|
import javax.persistence.DiscriminatorType;
|
||||||
|
import javax.persistence.DiscriminatorValue;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
|
||||||
|
import org.hibernate.persister.entity.Loadable;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@TestForIssue( jiraKey = "HHH-6911" )
|
||||||
|
public class JoinedSubclassWithExplicitDiscriminatorTest extends BaseCoreFunctionalTestCase {
|
||||||
|
@Entity( name = "Animal" )
|
||||||
|
@Table( name = "animal" )
|
||||||
|
@Inheritance( strategy = InheritanceType.JOINED )
|
||||||
|
@DiscriminatorColumn( name = "type", discriminatorType = DiscriminatorType.STRING )
|
||||||
|
@DiscriminatorValue( value = "???animal???" )
|
||||||
|
public static abstract class Animal {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
|
||||||
|
protected Animal() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Animal(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Cat" )
|
||||||
|
@DiscriminatorValue( value = "cat" )
|
||||||
|
public static class Cat extends Animal {
|
||||||
|
public Cat() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cat(Integer id) {
|
||||||
|
super( id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Dog" )
|
||||||
|
@DiscriminatorValue( value = "dog" )
|
||||||
|
public static class Dog extends Animal {
|
||||||
|
public Dog() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dog(Integer id) {
|
||||||
|
super( id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Animal.class, Cat.class, Dog.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metadataAssertions() {
|
||||||
|
EntityPersister p = sessionFactory().getEntityPersister( Dog.class.getName() );
|
||||||
|
assertNotNull( p );
|
||||||
|
final JoinedSubclassEntityPersister dogPersister = assertTyping( JoinedSubclassEntityPersister.class, p );
|
||||||
|
assertEquals( "string", dogPersister.getDiscriminatorType().getName() );
|
||||||
|
assertEquals( "type", dogPersister.getDiscriminatorColumnName() );
|
||||||
|
assertEquals( "dog", dogPersister.getDiscriminatorValue() );
|
||||||
|
|
||||||
|
p = sessionFactory().getEntityPersister( Cat.class.getName() );
|
||||||
|
assertNotNull( p );
|
||||||
|
final JoinedSubclassEntityPersister catPersister = assertTyping( JoinedSubclassEntityPersister.class, p );
|
||||||
|
assertEquals( "string", catPersister.getDiscriminatorType().getName() );
|
||||||
|
assertEquals( "type", catPersister.getDiscriminatorColumnName() );
|
||||||
|
assertEquals( "cat", catPersister.getDiscriminatorValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void basicUsageTest() {
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.save( new Cat( 1 ) );
|
||||||
|
session.save( new Dog( 2 ) );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.createQuery( "from Animal" ).list();
|
||||||
|
Cat cat = (Cat) session.get( Cat.class, 1 );
|
||||||
|
assertNotNull( cat );
|
||||||
|
session.delete( cat );
|
||||||
|
Dog dog = (Dog) session.get( Dog.class, 2 );
|
||||||
|
assertNotNull( dog );
|
||||||
|
session.delete( dog );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package org.hibernate.test.joinedsubclass;
|
||||||
|
|
||||||
|
import javax.persistence.DiscriminatorColumn;
|
||||||
|
import javax.persistence.DiscriminatorType;
|
||||||
|
import javax.persistence.DiscriminatorValue;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.cfg.Ejb3DiscriminatorColumn;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@TestForIssue( jiraKey = "HHH-6911" )
|
||||||
|
public class JoinedSubclassWithImplicitDiscriminatorTest extends BaseCoreFunctionalTestCase {
|
||||||
|
@Entity( name = "Animal" )
|
||||||
|
@Table( name = "animal" )
|
||||||
|
@Inheritance( strategy = InheritanceType.JOINED )
|
||||||
|
public static abstract class Animal {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
|
||||||
|
protected Animal() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Animal(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Cat" )
|
||||||
|
public static class Cat extends Animal {
|
||||||
|
public Cat() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cat(Integer id) {
|
||||||
|
super( id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Dog" )
|
||||||
|
public static class Dog extends Animal {
|
||||||
|
public Dog() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dog(Integer id) {
|
||||||
|
super( id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Animal.class, Cat.class, Dog.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(Configuration configuration) {
|
||||||
|
super.configure( configuration );
|
||||||
|
configuration.setProperty( AvailableSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, "true" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metadataAssertions() {
|
||||||
|
EntityPersister p = sessionFactory().getEntityPersister( Dog.class.getName() );
|
||||||
|
assertNotNull( p );
|
||||||
|
final JoinedSubclassEntityPersister dogPersister = assertTyping( JoinedSubclassEntityPersister.class, p );
|
||||||
|
assertEquals( Ejb3DiscriminatorColumn.DEFAULT_DISCRIMINATOR_TYPE, dogPersister.getDiscriminatorType().getName() );
|
||||||
|
assertEquals( Ejb3DiscriminatorColumn.DEFAULT_DISCRIMINATOR_COLUMN_NAME, dogPersister.getDiscriminatorColumnName() );
|
||||||
|
assertEquals( "Dog", dogPersister.getDiscriminatorValue() );
|
||||||
|
|
||||||
|
p = sessionFactory().getEntityPersister( Cat.class.getName() );
|
||||||
|
assertNotNull( p );
|
||||||
|
final JoinedSubclassEntityPersister catPersister = assertTyping( JoinedSubclassEntityPersister.class, p );
|
||||||
|
assertEquals( Ejb3DiscriminatorColumn.DEFAULT_DISCRIMINATOR_TYPE, catPersister.getDiscriminatorType().getName() );
|
||||||
|
assertEquals( Ejb3DiscriminatorColumn.DEFAULT_DISCRIMINATOR_COLUMN_NAME, catPersister.getDiscriminatorColumnName() );
|
||||||
|
assertEquals( "Cat", catPersister.getDiscriminatorValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void basicUsageTest() {
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.save( new Cat( 1 ) );
|
||||||
|
session.save( new Dog( 2 ) );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.createQuery( "from Animal" ).list();
|
||||||
|
Cat cat = (Cat) session.get( Cat.class, 1 );
|
||||||
|
assertNotNull( cat );
|
||||||
|
session.delete( cat );
|
||||||
|
Dog dog = (Dog) session.get( Dog.class, 2 );
|
||||||
|
assertNotNull( dog );
|
||||||
|
session.delete( dog );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue