/** * 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 void extractInheritanceType() { XAnnotatedElement element = getClazz(); Inheritance inhAnn = element.getAnnotation( Inheritance.class ); MappedSuperclass mappedSuperClass = element.getAnnotation( MappedSuperclass.class ); if ( mappedSuperClass != null ) { setEmbeddableSuperclass( true ); setType( inhAnn == null ? null : inhAnn.strategy() ); } else { setType( inhAnn == null ? InheritanceType.SINGLE_TABLE : inhAnn.strategy() ); } }
private Inheritance getInheritance(Element tree, XMLContext.Default defaults) { Element element = tree != null ? tree.element( "inheritance" ) : null; if ( element != null ) { AnnotationDescriptor ad = new AnnotationDescriptor( Inheritance.class ); Attribute attr = element.attribute( "strategy" ); InheritanceType strategy = InheritanceType.SINGLE_TABLE; if ( attr != null ) { String value = attr.getValue(); if ( "SINGLE_TABLE".equals( value ) ) { strategy = InheritanceType.SINGLE_TABLE; } else if ( "JOINED".equals( value ) ) { strategy = InheritanceType.JOINED; } else if ( "TABLE_PER_CLASS".equals( value ) ) { strategy = InheritanceType.TABLE_PER_CLASS; } else { throw new AnnotationException( "Unknown InheritanceType in XML: " + value + " (" + SCHEMA_VALIDATION + ")" ); } } ad.setValue( "strategy", strategy ); return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { return getPhysicalAnnotation( Inheritance.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)); }
@Test public void testGetEntityClassFromNodeLabelsHavingTheLabelDeclaredByTheClassNameWithTablePerClassInheritance() 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.TABLE_PER_CLASS); final JDefinedClass jSubclassA = jp._class(JMod.PUBLIC, simpleClassNameA)._extends(jBaseClass); jSubclassA.annotate(Entity.class); final JDefinedClass jSubclassB = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclassB.annotate(Entity.class); 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(simpleClassNameB), Arrays.asList(baseClass, subClassA, subClassB)); assertThat(clazz, equalTo(subClassB)); }
@Test public void testGetEntityClassFromNodeLabelsHavingTheLabelDeclaredByTheTableAnnotationWithTablePerClassInheritance() throws Exception { final String simpleClassNameBase = "EntityClass"; final String simpleClassNameA = "SubEntityClassA"; final String simpleClassNameB = "SubEntityClassB"; final String nodeLabelBase = "ENTITY_CLASS"; final String nodeLabelA = "ENTITY_CLASS_A"; final String nodeLabelB = "ENTITY_CLASS_B"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Table.class).param("name", nodeLabelBase); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.TABLE_PER_CLASS); final JDefinedClass jSubclassA = jp._class(JMod.PUBLIC, simpleClassNameA)._extends(jBaseClass); jSubclassA.annotate(Entity.class); jSubclassA.annotate(Table.class).param("name", nodeLabelA); final JDefinedClass jSubclassB = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclassB.annotate(Entity.class); jSubclassB.annotate(Table.class).param("name", nodeLabelB); 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(nodeLabelA), Arrays.asList(baseClass, subClassA, subClassB)); assertThat(clazz, equalTo(subClassA)); }
@Test public void testGetEntityClassFromNodeLabelsHavingTheLabelDeclaredByTheClassNameWithJoinedInheritance() 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.JOINED); final JDefinedClass jSubclassA = jp._class(JMod.PUBLIC, simpleClassNameA)._extends(jBaseClass); jSubclassA.annotate(Entity.class); final JDefinedClass jSubclassB = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclassB.annotate(Entity.class); 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(simpleClassNameB), Arrays.asList(baseClass, subClassA, subClassB)); assertThat(clazz, equalTo(subClassB)); }
@Test public void testGetEntityClassFromNodeLabelsHavingTheLabelDeclaredByTheTableAnnotationWithJoinedInheritance() throws Exception { final String simpleClassNameBase = "EntityClass"; final String simpleClassNameA = "SubEntityClassA"; final String simpleClassNameB = "SubEntityClassB"; final String nodeLabelBase = "ENTITY_CLASS"; final String nodeLabelA = "ENTITY_CLASS_A"; final String nodeLabelB = "ENTITY_CLASS_B"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Table.class).param("name", nodeLabelBase); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.JOINED); final JDefinedClass jSubclassA = jp._class(JMod.PUBLIC, simpleClassNameA)._extends(jBaseClass); jSubclassA.annotate(Entity.class); jSubclassA.annotate(Table.class).param("name", nodeLabelA); final JDefinedClass jSubclassB = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclassB.annotate(Entity.class); jSubclassB.annotate(Table.class).param("name", nodeLabelB); 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(nodeLabelA), Arrays.asList(baseClass, subClassA, subClassB)); assertThat(clazz, equalTo(subClassA)); }
@Test public void testGetNamesOfIdPropertiesFromAClassHierarchyHavingAFieldAnnotatedWithId() throws Exception { // GIVEN final String simpleClassNameBase = "EntityClass"; final String simpleClassNameB = "SubEntityClass"; final String idPropertyName = "key"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.TABLE_PER_CLASS); jBaseClass.field(JMod.PRIVATE, String.class, idPropertyName).annotate(Id.class); final JDefinedClass jSubclass = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclass.annotate(Entity.class); buildModel(testFolder.getRoot(), jCodeModel); compileModel(testFolder.getRoot()); final Class<?> subClass = loadClass(testFolder.getRoot(), jSubclass.name()); // WHEN final List<String> namesOfIdProperties = EntityUtils.getNamesOfIdProperties(subClass); // THEN assertThat(namesOfIdProperties.size(), equalTo(1)); assertThat(namesOfIdProperties, hasItem(idPropertyName)); }
@Test public void testGetNamesOfIdPropertiesFromAClassHierarchyHavingAMethodAnnotatedWithId() throws Exception { // GIVEN final String simpleClassNameBase = "EntityClass"; final String simpleClassNameB = "SubEntityClass"; final String idPropertyName = "key"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.TABLE_PER_CLASS); jBaseClass.method(JMod.PUBLIC, jCodeModel.VOID, "getKey").annotate(Id.class); final JDefinedClass jSubclass = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclass.annotate(Entity.class); buildModel(testFolder.getRoot(), jCodeModel); compileModel(testFolder.getRoot()); final Class<?> subClass = loadClass(testFolder.getRoot(), jSubclass.name()); // WHEN final List<String> namesOfIdProperties = EntityUtils.getNamesOfIdProperties(subClass); // THEN assertThat(namesOfIdProperties.size(), equalTo(1)); assertThat(namesOfIdProperties, hasItem(idPropertyName)); }
@Test public void testGetNamesOfIdPropertiesFromAClassHierarchyHavingAFieldAnnotatedWithEmbeddedId() throws Exception { // GIVEN final String simpleClassNameBase = "EntityClass"; final String simpleClassNameB = "SubEntityClass"; final String compositeIdPropertyName = "compositeKey"; final String id1PropertyName = "key1"; final String id2PropertyName = "key2"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jIdTypeClass = jp._class(JMod.PUBLIC, "IdType"); jIdTypeClass.annotate(Embeddable.class); jIdTypeClass.field(JMod.PRIVATE, Integer.class, id1PropertyName); jIdTypeClass.field(JMod.PRIVATE, String.class, id2PropertyName); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.TABLE_PER_CLASS); jBaseClass.field(JMod.PRIVATE, jIdTypeClass, compositeIdPropertyName).annotate(EmbeddedId.class); final JDefinedClass jSubclass = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclass.annotate(Entity.class); buildModel(testFolder.getRoot(), jCodeModel); compileModel(testFolder.getRoot()); final Class<?> entityClass = loadClass(testFolder.getRoot(), jSubclass.name()); // WHEN final List<String> namesOfIdProperties = EntityUtils.getNamesOfIdProperties(entityClass); // THEN assertThat(namesOfIdProperties.size(), equalTo(2)); assertThat(namesOfIdProperties, hasItems(compositeIdPropertyName + "." + id1PropertyName, compositeIdPropertyName + "." + id2PropertyName)); }
@Test public void testGetNamesOfIdPropertiesFromAClassHierarchyHavingAMethodAnnotatedWithEmbeddedId() throws Exception { // GIVEN final String simpleClassNameBase = "EntityClass"; final String simpleClassNameB = "SubEntityClass"; final String compositeIdPropertyName = "compositeKey"; final String id1PropertyName = "key1"; final String id2PropertyName = "key2"; final JPackage jp = jCodeModel.rootPackage(); final JDefinedClass jIdTypeClass = jp._class(JMod.PUBLIC, "IdType"); jIdTypeClass.annotate(Embeddable.class); jIdTypeClass.field(JMod.PRIVATE, Integer.class, id1PropertyName); jIdTypeClass.field(JMod.PRIVATE, String.class, id2PropertyName); final JDefinedClass jBaseClass = jp._class(JMod.PUBLIC, simpleClassNameBase); jBaseClass.annotate(Entity.class); jBaseClass.annotate(Inheritance.class).param("strategy", InheritanceType.TABLE_PER_CLASS); final JMethod method = jBaseClass.method(JMod.PUBLIC, jIdTypeClass, "getCompositeKey"); method.annotate(EmbeddedId.class); method.body()._return(JExpr._null()); final JDefinedClass jSubclass = jp._class(JMod.PUBLIC, simpleClassNameB)._extends(jBaseClass); jSubclass.annotate(Entity.class); buildModel(testFolder.getRoot(), jCodeModel); compileModel(testFolder.getRoot()); final Class<?> entityClass = loadClass(testFolder.getRoot(), jSubclass.name()); // WHEN final List<String> namesOfIdProperties = EntityUtils.getNamesOfIdProperties(entityClass); // THEN assertThat(namesOfIdProperties.size(), equalTo(2)); assertThat(namesOfIdProperties, hasItems(compositeIdPropertyName + "." + id1PropertyName, compositeIdPropertyName + "." + id2PropertyName)); }
protected String getEntityNameForIdGeneration(MetaClass metaClass) { MetaClass result = metaClass.getAncestors().stream() .filter(mc -> { // use root of inheritance tree if the strategy is JOINED because ID is stored in the root table Class<?> javaClass = mc.getJavaClass(); Inheritance inheritance = javaClass.getAnnotation(Inheritance.class); return inheritance != null && inheritance.strategy() == InheritanceType.JOINED; }) .findFirst() .orElse(metaClass); return result.getName(); }