HHH-5190 - Introduced new annotation @DiscriminatorOptions and deprecated @ForceDiscriminator

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@20749 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Hardy Ferentschik 2010-09-29 10:45:08 +00:00
parent 4e2887c0c0
commit bf7607e244
7 changed files with 285 additions and 51 deletions

View File

@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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
*/
// $Id:$
package org.hibernate.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Optional annotation to express Hibernate specific discrimintor properties.
*
* @author Hardy Ferentschik
*/
@Target({ TYPE })
@Retention(RUNTIME)
public @interface DiscriminatorOptions {
/**
* "Forces" Hibernate to specify the allowed discriminator values, even when retrieving all instances of the root class.
*
* @return {@code true} in case the discriminator value should be forces, {@code false} otherwise. Default is {@code false}.
*/
boolean force() default false;
/**
* Set this to {@code false}, if your discriminator column is also part of a mapped composite identifier.
* It tells Hibernate not to include the column in SQL INSERTs.
*
* @return {@code true} in case the discriminator value should be included in inserts, {@code false} otherwise.
* Default is {@code true}.
*/
boolean insert() default true;
}

View File

@ -23,16 +23,19 @@
*/
package org.hibernate.annotations;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* ForceDiscriminator flag
* To be placed at the root entity near @DiscriminatorColumn or @DiscriminatorFormula
*
* @author Serg Prasolov
* @deprecated use {@link org.hibernate.annotations.DiscriminatorOptions} instead
*/
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME)
public @interface ForceDiscriminator {}
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface ForceDiscriminator {
}

View File

@ -97,6 +97,7 @@ import org.hibernate.annotations.Check;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.DiscriminatorOptions;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchProfile;
import org.hibernate.annotations.FetchProfiles;
@ -104,6 +105,7 @@ import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.FilterDefs;
import org.hibernate.annotations.Filters;
import org.hibernate.annotations.ForceDiscriminator;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.GenericGenerator;
@ -533,6 +535,16 @@ public final class AnnotationBinder {
clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState
);
PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
Entity entityAnn = clazzToProcess.getAnnotation( Entity.class );
org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(
org.hibernate.annotations.Entity.class
);
EntityBinder entityBinder = new EntityBinder(
entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings
);
entityBinder.setInheritanceState( inheritanceState );
bindQueries( clazzToProcess, mappings );
bindFilterDefs( clazzToProcess, mappings );
bindTypeDefs( clazzToProcess, mappings );
@ -555,56 +567,16 @@ public final class AnnotationBinder {
clazzToProcess, mappings, inheritanceState, superEntity
);
Ejb3DiscriminatorColumn discriminatorColumn = null;
String discrimValue = null;
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
javax.persistence.DiscriminatorColumn.class
discriminatorColumn = processDiscriminatorProperties(
clazzToProcess, mappings, inheritanceState, entityBinder
);
DiscriminatorType discriminatorType = discAnn != null ?
discAnn.discriminatorType() :
DiscriminatorType.STRING;
org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
org.hibernate.annotations.DiscriminatorFormula.class
);
if ( !inheritanceState.hasParents() ) {
discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
discriminatorType, discAnn, discFormulaAnn, mappings
);
}
if ( discAnn != null && inheritanceState.hasParents() ) {
log.warn(
"Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
clazzToProcess.getName()
);
}
discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?
clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :
null;
}
PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
Proxy proxyAnn = clazzToProcess.getAnnotation( Proxy.class );
BatchSize sizeAnn = clazzToProcess.getAnnotation( BatchSize.class );
Where whereAnn = clazzToProcess.getAnnotation( Where.class );
Entity entityAnn = clazzToProcess.getAnnotation( Entity.class );
org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(
org.hibernate.annotations.Entity.class
);
Cache cacheAnn = determineCacheSettings( clazzToProcess, mappings );
EntityBinder entityBinder = new EntityBinder(
entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings
);
entityBinder.setDiscriminatorValue( discrimValue );
entityBinder.setBatchSize( sizeAnn );
entityBinder.setProxy( proxyAnn );
entityBinder.setWhere( whereAnn );
entityBinder.setCache( cacheAnn );
entityBinder.setInheritanceState( inheritanceState );
entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
entityBinder.setCache( determineCacheSettings( clazzToProcess, mappings ) );
//Filters are not allowed on subclasses
if ( !inheritanceState.hasParents() ) {
@ -763,6 +735,50 @@ public final class AnnotationBinder {
}
// parse everything discriminator column relevant in case of single table inheritance
private static Ejb3DiscriminatorColumn processDiscriminatorProperties(XClass clazzToProcess, Mappings mappings, InheritanceState inheritanceState, EntityBinder entityBinder) {
Ejb3DiscriminatorColumn discriminatorColumn = null;
javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
javax.persistence.DiscriminatorColumn.class
);
DiscriminatorType discriminatorType = discAnn != null ?
discAnn.discriminatorType() :
DiscriminatorType.STRING;
org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
org.hibernate.annotations.DiscriminatorFormula.class
);
if ( !inheritanceState.hasParents() ) {
discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
discriminatorType, discAnn, discFormulaAnn, mappings
);
}
if ( discAnn != null && inheritanceState.hasParents() ) {
log.warn(
"Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
clazzToProcess.getName()
);
}
String discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?
clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :
null;
entityBinder.setDiscriminatorValue( discrimValue );
if ( clazzToProcess.isAnnotationPresent( ForceDiscriminator.class ) ) {
log.warn( "@ForceDiscriminator is deprecated use @DiscriminatorOptions instead." );
entityBinder.setForceDiscriminator( true );
}
DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );
if ( discriminatorOptions != null) {
entityBinder.setForceDiscriminator( discriminatorOptions.force() );
entityBinder.setInsertableDiscriminator( discriminatorOptions.insert() );
}
return discriminatorColumn;
}
private static void processIdPropertiesIfNotAlready(
Map<XClass, InheritanceState> inheritanceStatePerClass,
Mappings mappings,

View File

@ -43,7 +43,6 @@ import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.ForceDiscriminator;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.Loader;
import org.hibernate.annotations.OptimisticLockType;
@ -102,6 +101,8 @@ public class EntityBinder {
private Mappings mappings;
private Logger log = LoggerFactory.getLogger( EntityBinder.class );
private String discriminatorValue = "";
private Boolean forceDiscriminator;
private Boolean insertableDiscriminator;
private boolean dynamicInsert;
private boolean dynamicUpdate;
private boolean explicitHibernateEntityAnnotation;
@ -182,6 +183,14 @@ public class EntityBinder {
this.discriminatorValue = discriminatorValue;
}
public void setForceDiscriminator(boolean forceDiscriminator) {
this.forceDiscriminator = forceDiscriminator;
}
public void setInsertableDiscriminator(boolean insertableDiscriminator) {
this.insertableDiscriminator = insertableDiscriminator;
}
public void bindEntity() {
persistentClass.setAbstract( annotatedClass.isAbstract() );
persistentClass.setClassName( annotatedClass.getName() );
@ -219,7 +228,12 @@ public class EntityBinder {
rootClass.setCacheRegionName( cacheRegion );
rootClass.setLazyPropertiesCacheable( cacheLazyProperty );
}
rootClass.setForceDiscriminator( annotatedClass.isAnnotationPresent( ForceDiscriminator.class ) );
if(forceDiscriminator != null) {
rootClass.setForceDiscriminator( forceDiscriminator );
}
if( insertableDiscriminator != null) {
rootClass.setDiscriminatorInsertable( insertableDiscriminator );
}
}
else {
if ( explicitHibernateEntityAnnotation ) {

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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
*/
// $Id:$
package org.hibernate.test.annotations.inheritance.discriminatoroptions;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.DiscriminatorOptions;
/**
* @author Hardy Ferentschik
*/
@Entity
@DiscriminatorValue("B")
@DiscriminatorOptions(force = true, insert = false)
public class BaseClass {
@Id
@GeneratedValue
private long id;
}

View File

@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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
*/
//$Id$
package org.hibernate.test.annotations.inheritance.discriminatoroptions;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
import org.hibernate.test.annotations.TestCase;
/**
* Test for the @DiscriminatorOptions annotations.
*
* @author Hardy Ferentschik
*/
public class DiscriminatorOptionsTest extends TestCase {
public void testNonDefaultOptions() throws Exception {
buildConfiguration();
PersistentClass persistentClass = cfg.getClassMapping( BaseClass.class.getName() );
assertNotNull( persistentClass );
assertTrue( persistentClass instanceof RootClass );
RootClass root = ( RootClass ) persistentClass;
assertTrue( "Discriminator should be forced", root.isForceDiscriminator() );
assertFalse( "Discriminator should not be insertable", root.isDiscriminatorInsertable() );
}
protected Class[] getAnnotatedClasses() {
return new Class[] {
BaseClass.class, SubClass.class
};
}
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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
*/
// $Id:$
package org.hibernate.test.annotations.inheritance.discriminatoroptions;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
@DiscriminatorValue("B")
public class SubClass extends BaseClass {
}