/** * Determine the inheritance type and discriminator properties. */ private void buildInheritance() { // Check, if we've got an explicit inheritance type final Inheritance inheritance = this.entityClass.getAnnotation(Inheritance.class); if (inheritance != null) { this.inheritanceType = inheritance.strategy(); } // Find the root of our hierarchy this.hierarchyRoot = this; findHierarchyRoot(this.entityClass.getSuperclass()); // We scan only classes that we are about to write // So we don't know, that there is a subclass entity - until we find one // This could be to late for InheritanceType.SINGLE_TABLE - the defaault type // That's why we build a discriminator, if one of the inheritance annotations exists if (this.inheritanceType == null && this.entityClass.isAnnotationPresent(DiscriminatorColumn.class) || this.entityClass.isAnnotationPresent(DiscriminatorValue.class)) { this.inheritanceType = InheritanceType.SINGLE_TABLE; } buildDiscriminator(); }
private DiscriminatorValue getDiscriminatorValue(Element tree, XMLContext.Default defaults) { Element element = tree != null ? tree.element( "discriminator-value" ) : null; if ( element != null ) { AnnotationDescriptor ad = new AnnotationDescriptor( DiscriminatorValue.class ); copyStringElement( element, ad, "value" ); return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { return getPhysicalAnnotation( DiscriminatorValue.class ); } else { return null; } }
@Test public void testGetEntityClassFromNodeLabelsHavingTheLabelDeclaredByTheClassNameWithSingleTableInheritance() throws Exception { final String simpleClassNameBase = "EntityClass"; final String simpleClassNameA = "SubEntityClassA"; final String simpleClassNameB = "SubEntityClassB"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.SINGLE_TABLE); jBaseClass.annotate(DiscriminatorColumn.class).param("name", "TYPE"); final JDefinedClass jSubclassA = jp._class(JMod.PUBLIC, simpleClassNameA)._extends(jBaseClass); jSubclassA.annotate(Entity.class); jSubclassA.annotate(DiscriminatorValue.class).param("value", "A"); final JDefinedClass jSubclassB = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclassB.annotate(Entity.class); jSubclassB.annotate(DiscriminatorValue.class).param("value", "B"); buildModel(testFolder.getRoot(), jCodeModel); compileModel(testFolder.getRoot()); final Class<?> baseClass = loadClass(testFolder.getRoot(), jBaseClass.name()); final Class<?> subClassA = loadClass(testFolder.getRoot(), jSubclassA.name()); final Class<?> subClassB = loadClass(testFolder.getRoot(), jSubclassB.name()); final Class<?> clazz = EntityUtils.getEntityClassFromNodeLabels(Arrays.asList(simpleClassNameBase), Arrays.asList(baseClass, subClassA, subClassB)); assertThat(clazz, equalTo(baseClass)); }
@Test public void testGetEntityClassFromNodeLabelsHavingTheLabelDeclaredByTheTableAnnotationWithSingleTableInheritance() throws Exception { final String simpleClassNameBase = "EntityClass"; final String simpleClassNameA = "SubEntityClassA"; final String simpleClassNameB = "SubEntityClassB"; final String nodeLabel = "ENTITY_CLASS"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Table.class).param("name", nodeLabel); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.SINGLE_TABLE); jBaseClass.annotate(DiscriminatorColumn.class).param("name", "TYPE"); final JDefinedClass jSubclassA = jp._class(JMod.PUBLIC, simpleClassNameA)._extends(jBaseClass); jSubclassA.annotate(Entity.class); jSubclassA.annotate(DiscriminatorValue.class).param("value", "A"); final JDefinedClass jSubclassB = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclassB.annotate(Entity.class); jSubclassB.annotate(DiscriminatorValue.class).param("value", "B"); buildModel(testFolder.getRoot(), jCodeModel); compileModel(testFolder.getRoot()); final Class<?> baseClass = loadClass(testFolder.getRoot(), jBaseClass.name()); final Class<?> subClassA = loadClass(testFolder.getRoot(), jSubclassA.name()); final Class<?> subClassB = loadClass(testFolder.getRoot(), jSubclassB.name()); final Class<?> clazz = EntityUtils.getEntityClassFromNodeLabels(Arrays.asList(nodeLabel), Arrays.asList(baseClass, subClassA, subClassB)); assertThat(clazz, equalTo(baseClass)); }
private ColumnExpression buildDiscriminator(final EntityClass<?> c, final DiscriminatorColumn column) { final DiscriminatorType type; final int maxLength; if (column == null) { type = DiscriminatorType.STRING; final int defaultMaxLength = 31; maxLength = defaultMaxLength; } else { type = column.discriminatorType(); maxLength = column.length(); } final DiscriminatorValue value = this.entityClass.getAnnotation(DiscriminatorValue.class); if (type == DiscriminatorType.INTEGER) { return PrimitiveColumnExpression.create( value == null ? c.getEntityName().hashCode() : Integer.parseInt(value.value()), getContext().getDialect()); } final String v = value == null ? c.getEntityName() : value.value(); if (StringUtils.isEmpty(v)) { throw new IllegalArgumentException("Missing discriminator value for: " + c.getEntityClass()); } if (type == DiscriminatorType.STRING) { return PrimitiveColumnExpression.create(v.length() <= maxLength ? v : v.substring(0, maxLength), getContext().getDialect()); } else if (type == DiscriminatorType.CHAR) { return PrimitiveColumnExpression.create(v.substring(0, 1), getContext().getDialect()); } throw new IllegalArgumentException("Unknown discriminator type: " + type); }
public String getDiscriminatorValue() { final DiscriminatorValue annotation = clazz.getAnnotation(DiscriminatorValue.class); if (annotation != null) return annotation.value(); else return clazz.getName(); }
/** * 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; 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 ( isRoot ) { discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn( discriminatorType, discAnn, discFormulaAnn, mappings ); } if ( discAnn != null && !isRoot ) { LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() ); } final String discriminatorValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ? clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() : null; entityBinder.setDiscriminatorValue( discriminatorValue ); DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class ); if ( discriminatorOptions != null) { entityBinder.setForceDiscriminator( discriminatorOptions.force() ); entityBinder.setInsertableDiscriminator( discriminatorOptions.insert() ); } 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() ) { // we want to process the discriminator column if either: // 1) There is an explicit DiscriminatorColumn annotation && we are not told to ignore them // 2) There is not an explicit DiscriminatorColumn annotation && we are told to create them implicitly final boolean generateDiscriminatorColumn; if ( discriminatorColumnAnnotation != null ) { if ( mappings.ignoreExplicitDiscriminatorColumnForJoinedInheritance() ) { LOG.debugf( "Ignoring explicit DiscriminatorColumn annotation on ", clazzToProcess.getName() ); generateDiscriminatorColumn = false; } else { LOG.applyingExplicitDiscriminatorColumnForJoined( clazzToProcess.getName(), AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS ); generateDiscriminatorColumn = true; } } else { if ( mappings.useImplicitDiscriminatorColumnForJoinedInheritance() ) { LOG.debug( "Applying implicit DiscriminatorColumn using DiscriminatorColumn defaults" ); generateDiscriminatorColumn = true; } else { LOG.debug( "Ignoring implicit (absent) DiscriminatorColumn" ); generateDiscriminatorColumn = false; } } if ( generateDiscriminatorColumn ) { 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; }