introduce DiscriminatorOptionsBinder

This commit is contained in:
Gavin King 2024-03-10 16:11:26 +01:00
parent 76d7d4c3a8
commit 688bb8a222
5 changed files with 67 additions and 37 deletions

View File

@ -6,6 +6,8 @@
*/ */
// $Id$ // $Id$
package org.hibernate.annotations; package org.hibernate.annotations;
import org.hibernate.binder.internal.DiscriminatorOptionsBinder;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@ -19,6 +21,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* *
* @author Hardy Ferentschik * @author Hardy Ferentschik
*/ */
@TypeBinderType(binder = DiscriminatorOptionsBinder.class)
@Target(TYPE) @Target(TYPE)
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface DiscriminatorOptions { public @interface DiscriminatorOptions {

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.binder.internal;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.DiscriminatorOptions;
import org.hibernate.binder.TypeBinder;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
/**
* Handles {@link DiscriminatorOptions} annotations.
*
* @author Gavin King
*
* @since 6.5
*/
public class DiscriminatorOptionsBinder implements TypeBinder<DiscriminatorOptions> {
@Override
public void bind(DiscriminatorOptions options, MetadataBuildingContext context, PersistentClass persistentClass) {
if ( persistentClass instanceof RootClass ) {
final RootClass rootClass = (RootClass) persistentClass;
if ( !rootClass.hasDiscriminator() ) {
throw new AnnotationException( "Root entity '" + rootClass.getEntityName()
+ "' is annotated '@DiscriminatorOptions' but has no discriminator column" );
}
rootClass.setForceDiscriminator( options.force() );
rootClass.setDiscriminatorInsertable( options.insert() );
}
else {
throw new AnnotationException("Class '" + persistentClass.getClassName()
+ "' is not the root class of an entity inheritance hierarchy and may not be annotated '@DiscriminatorOptions'");
}
}
@Override
public void bind(DiscriminatorOptions options, MetadataBuildingContext context, Component embeddableClass) {
throw new AnnotationException("Class '" + embeddableClass.getComponentClassName()
+ "' is an '@Embeddable' type and may not be annotated '@DiscriminatorOptions'");
}
}

View File

@ -72,8 +72,6 @@ import org.hibernate.type.descriptor.java.Immutability;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.java.spi.JsonJavaType;
import org.hibernate.type.descriptor.java.spi.XmlJavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;

View File

@ -26,7 +26,6 @@ import org.hibernate.annotations.CacheLayout;
import org.hibernate.annotations.Check; import org.hibernate.annotations.Check;
import org.hibernate.annotations.Checks; import org.hibernate.annotations.Checks;
import org.hibernate.annotations.DiscriminatorFormula; import org.hibernate.annotations.DiscriminatorFormula;
import org.hibernate.annotations.DiscriminatorOptions;
import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Filter; import org.hibernate.annotations.Filter;
@ -178,8 +177,6 @@ public class EntityBinder {
private String name; private String name;
private XClass annotatedClass; private XClass annotatedClass;
private PersistentClass persistentClass; private PersistentClass persistentClass;
private Boolean forceDiscriminator;
private Boolean insertableDiscriminator;
private PolymorphismType polymorphismType; private PolymorphismType polymorphismType;
private boolean lazy; private boolean lazy;
private XClass proxyClass; private XClass proxyClass;
@ -769,8 +766,11 @@ public class EntityBinder {
singleTableInheritance( inheritanceState, propertyHolder ); singleTableInheritance( inheritanceState, propertyHolder );
isJoinedSubclass = false; isJoinedSubclass = false;
break; break;
default: case TABLE_PER_CLASS:
isJoinedSubclass = false; isJoinedSubclass = false;
break;
default:
throw new AssertionFailure( "Unrecognized InheritanceType" );
} }
bindDiscriminatorValue(); bindDiscriminatorValue();
@ -785,21 +785,21 @@ public class EntityBinder {
} }
private void singleTableInheritance(InheritanceState inheritanceState, PropertyHolder holder) { private void singleTableInheritance(InheritanceState inheritanceState, PropertyHolder holder) {
processDiscriminatorOptions(); final AnnotatedDiscriminatorColumn discriminatorColumn =
final AnnotatedDiscriminatorColumn discriminatorColumn = processSingleTableDiscriminatorProperties( inheritanceState ); processSingleTableDiscriminatorProperties( inheritanceState );
if ( !inheritanceState.hasParents() ) { // todo : sucks that this is separate from RootClass distinction if ( !inheritanceState.hasParents() ) { // todo : sucks that this is separate from RootClass distinction
final RootClass rootClass = (RootClass) persistentClass; final RootClass rootClass = (RootClass) persistentClass;
if ( inheritanceState.hasSiblings() if ( inheritanceState.hasSiblings()
|| discriminatorColumn != null && !discriminatorColumn.isImplicit() ) { || discriminatorColumn != null && !discriminatorColumn.isImplicit() ) {
bindDiscriminatorColumnToRootPersistentClass( rootClass, discriminatorColumn, holder ); bindDiscriminatorColumnToRootPersistentClass( rootClass, discriminatorColumn, holder );
rootClass.setForceDiscriminator( isForceDiscriminatorInSelects() ); if ( context.getBuildingOptions().shouldImplicitlyForceDiscriminatorInSelect() ) {
rootClass.setForceDiscriminator( true );
}
} }
} }
} }
private void joinedInheritance(InheritanceState state, PersistentClass superEntity, PropertyHolder holder) { private void joinedInheritance(InheritanceState state, PersistentClass superEntity, PropertyHolder holder) {
processDiscriminatorOptions();
if ( state.hasParents() ) { if ( state.hasParents() ) {
final AnnotatedJoinColumns joinColumns = subclassJoinColumns( annotatedClass, superEntity, context ); final AnnotatedJoinColumns joinColumns = subclassJoinColumns( annotatedClass, superEntity, context );
final JoinedSubclass jsc = (JoinedSubclass) persistentClass; final JoinedSubclass jsc = (JoinedSubclass) persistentClass;
@ -821,17 +821,13 @@ public class EntityBinder {
// the class we're processing is the root of the hierarchy, so // the class we're processing is the root of the hierarchy, so
// let's see if we had a discriminator column (it's perfectly // let's see if we had a discriminator column (it's perfectly
// valid for joined inheritance to not have a discriminator) // valid for joined inheritance to not have a discriminator)
if ( discriminatorColumn == null ) { if ( discriminatorColumn != null ) {
if ( isForceDiscriminatorInSelects() ) {
throw new AnnotationException( "Entity '" + rootClass.getEntityName()
+ "' with 'JOINED' inheritance is annotated '@DiscriminatorOptions(force=true)' but has no discriminator column" );
}
}
else {
// we do have a discriminator column // we do have a discriminator column
if ( state.hasSiblings() || !discriminatorColumn.isImplicit() ) { if ( state.hasSiblings() || !discriminatorColumn.isImplicit() ) {
bindDiscriminatorColumnToRootPersistentClass( rootClass, discriminatorColumn, holder ); bindDiscriminatorColumnToRootPersistentClass( rootClass, discriminatorColumn, holder );
rootClass.setForceDiscriminator( isForceDiscriminatorInSelects() ); if ( context.getBuildingOptions().shouldImplicitlyForceDiscriminatorInSelect() ) {
rootClass.setForceDiscriminator( true );
}
} }
} }
} }
@ -911,17 +907,6 @@ public class EntityBinder {
new NullableDiscriminatorColumnSecondPass( rootClass.getEntityName() ) new NullableDiscriminatorColumnSecondPass( rootClass.getEntityName() )
); );
} }
if ( insertableDiscriminator != null ) {
rootClass.setDiscriminatorInsertable( insertableDiscriminator );
}
}
private void processDiscriminatorOptions() {
final DiscriminatorOptions discriminatorOptions = annotatedClass.getAnnotation( DiscriminatorOptions.class );
if ( discriminatorOptions != null ) {
forceDiscriminator = discriminatorOptions.force();
insertableDiscriminator = discriminatorOptions.insert();
}
} }
/** /**
@ -1343,12 +1328,6 @@ public class EntityBinder {
rootClass.setNaturalIdCacheRegionName( naturalIdCacheRegion ); rootClass.setNaturalIdCacheRegionName( naturalIdCacheRegion );
} }
private boolean isForceDiscriminatorInSelects() {
return forceDiscriminator == null
? context.getBuildingOptions().shouldImplicitlyForceDiscriminatorInSelect()
: forceDiscriminator;
}
private void bindCustomSql() { private void bindCustomSql() {
//TODO: tolerate non-empty table() member here if it explicitly names the main table //TODO: tolerate non-empty table() member here if it explicitly names the main table

View File

@ -7,7 +7,6 @@
package org.hibernate.mapping; package org.hibernate.mapping;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -107,6 +106,10 @@ public class RootClass extends PersistentClass implements TableOwner, SoftDeleta
return identifierProperty != null; return identifierProperty != null;
} }
public boolean hasDiscriminator() {
return discriminator != null;
}
@Override @Override
public Value getDiscriminator() { public Value getDiscriminator() {
return discriminator; return discriminator;