/** * 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 DiscriminatorColumn getDiscriminatorColumn(Element tree, XMLContext.Default defaults) { Element element = tree != null ? tree.element( "discriminator-column" ) : null; if ( element != null ) { AnnotationDescriptor ad = new AnnotationDescriptor( DiscriminatorColumn.class ); copyStringAttribute( ad, element, "name", false ); copyStringAttribute( ad, element, "column-definition", false ); String value = element.attributeValue( "discriminator-type" ); DiscriminatorType type = DiscriminatorType.STRING; if ( value != null ) { if ( "STRING".equals( value ) ) { type = DiscriminatorType.STRING; } else if ( "CHAR".equals( value ) ) { type = DiscriminatorType.CHAR; } else if ( "INTEGER".equals( value ) ) { type = DiscriminatorType.INTEGER; } else { throw new AnnotationException( "Unknown DiscrimiatorType in XML: " + value + " (" + SCHEMA_VALIDATION + ")" ); } } ad.setValue( "discriminatorType", type ); copyIntegerAttribute( ad, element, "length" ); return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { return getPhysicalAnnotation( DiscriminatorColumn.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 void buildDiscriminator() { if (this.inheritanceType == InheritanceType.SINGLE_TABLE || this.inheritanceType == InheritanceType.JOINED) { final DiscriminatorColumn column = this.hierarchyRoot.entityClass.getAnnotation(DiscriminatorColumn.class); if (column != null || this.inheritanceType != InheritanceType.JOINED || this.context.getProvider().isJoinedDiscriminatorNeeded()) { this.discriminatorColumn = this.table.resolveColumn(column == null ? "DTYPE" : column.name()); this.discriminator = buildDiscriminator(this, column); } } }
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 static Ejb3DiscriminatorColumn buildDiscriminatorColumn( DiscriminatorType type, DiscriminatorColumn discAnn, DiscriminatorFormula discFormulaAnn, Mappings mappings) { Ejb3DiscriminatorColumn discriminatorColumn = new Ejb3DiscriminatorColumn(); discriminatorColumn.setMappings( mappings ); discriminatorColumn.setImplicit( true ); if ( discFormulaAnn != null ) { discriminatorColumn.setImplicit( false ); discriminatorColumn.setFormula( discFormulaAnn.value() ); } else if ( discAnn != null ) { discriminatorColumn.setImplicit( false ); if ( !BinderHelper.isEmptyAnnotationValue( discAnn.columnDefinition() ) ) { discriminatorColumn.setSqlType( discAnn.columnDefinition() ); } if ( !BinderHelper.isEmptyAnnotationValue( discAnn.name() ) ) { discriminatorColumn.setLogicalColumnName( discAnn.name() ); } discriminatorColumn.setNullable( false ); } if ( DiscriminatorType.CHAR.equals( type ) ) { discriminatorColumn.setDiscriminatorTypeName( "character" ); discriminatorColumn.setImplicit( false ); } else if ( DiscriminatorType.INTEGER.equals( type ) ) { discriminatorColumn.setDiscriminatorTypeName( "integer" ); discriminatorColumn.setImplicit( false ); } else if ( DiscriminatorType.STRING.equals( type ) || type == null ) { if ( discAnn != null ) discriminatorColumn.setLength( discAnn.length() ); discriminatorColumn.setDiscriminatorTypeName( "string" ); } else { throw new AssertionFailure( "Unknown discriminator type: " + type ); } discriminatorColumn.bind(); return discriminatorColumn; }
/** * 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; }