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$
package org.hibernate.annotations;
import org.hibernate.binder.internal.DiscriminatorOptionsBinder;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@ -19,6 +21,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
*
* @author Hardy Ferentschik
*/
@TypeBinderType(binder = DiscriminatorOptionsBinder.class)
@Target(TYPE)
@Retention(RUNTIME)
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.JavaType;
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.JdbcTypeIndicators;
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.Checks;
import org.hibernate.annotations.DiscriminatorFormula;
import org.hibernate.annotations.DiscriminatorOptions;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Filter;
@ -178,8 +177,6 @@ public class EntityBinder {
private String name;
private XClass annotatedClass;
private PersistentClass persistentClass;
private Boolean forceDiscriminator;
private Boolean insertableDiscriminator;
private PolymorphismType polymorphismType;
private boolean lazy;
private XClass proxyClass;
@ -769,8 +766,11 @@ public class EntityBinder {
singleTableInheritance( inheritanceState, propertyHolder );
isJoinedSubclass = false;
break;
default:
case TABLE_PER_CLASS:
isJoinedSubclass = false;
break;
default:
throw new AssertionFailure( "Unrecognized InheritanceType" );
}
bindDiscriminatorValue();
@ -785,21 +785,21 @@ public class EntityBinder {
}
private void singleTableInheritance(InheritanceState inheritanceState, PropertyHolder holder) {
processDiscriminatorOptions();
final AnnotatedDiscriminatorColumn discriminatorColumn = processSingleTableDiscriminatorProperties( inheritanceState );
final AnnotatedDiscriminatorColumn discriminatorColumn =
processSingleTableDiscriminatorProperties( inheritanceState );
if ( !inheritanceState.hasParents() ) { // todo : sucks that this is separate from RootClass distinction
final RootClass rootClass = (RootClass) persistentClass;
if ( inheritanceState.hasSiblings()
|| discriminatorColumn != null && !discriminatorColumn.isImplicit() ) {
bindDiscriminatorColumnToRootPersistentClass( rootClass, discriminatorColumn, holder );
rootClass.setForceDiscriminator( isForceDiscriminatorInSelects() );
if ( context.getBuildingOptions().shouldImplicitlyForceDiscriminatorInSelect() ) {
rootClass.setForceDiscriminator( true );
}
}
}
}
private void joinedInheritance(InheritanceState state, PersistentClass superEntity, PropertyHolder holder) {
processDiscriminatorOptions();
if ( state.hasParents() ) {
final AnnotatedJoinColumns joinColumns = subclassJoinColumns( annotatedClass, superEntity, context );
final JoinedSubclass jsc = (JoinedSubclass) persistentClass;
@ -821,17 +821,13 @@ public class EntityBinder {
// the class we're processing is the root of the hierarchy, so
// let's see if we had a discriminator column (it's perfectly
// valid for joined inheritance to not have a discriminator)
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 {
if ( discriminatorColumn != null ) {
// we do have a discriminator column
if ( state.hasSiblings() || !discriminatorColumn.isImplicit() ) {
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() )
);
}
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 );
}
private boolean isForceDiscriminatorInSelects() {
return forceDiscriminator == null
? context.getBuildingOptions().shouldImplicitlyForceDiscriminatorInSelect()
: forceDiscriminator;
}
private void bindCustomSql() {
//TODO: tolerate non-empty table() member here if it explicitly names the main table

View File

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