HHH-6174 extracting table name from hierarchy
This commit is contained in:
parent
627b4ea6a1
commit
1ae1d4b699
|
@ -35,17 +35,18 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.AccessType;
|
import javax.persistence.AccessType;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
|
||||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||||
import com.fasterxml.classmate.members.HierarchicType;
|
import com.fasterxml.classmate.members.HierarchicType;
|
||||||
import com.fasterxml.classmate.members.ResolvedMember;
|
import com.fasterxml.classmate.members.ResolvedMember;
|
||||||
import org.jboss.jandex.AnnotationInstance;
|
import org.jboss.jandex.AnnotationInstance;
|
||||||
import org.jboss.jandex.AnnotationTarget;
|
import org.jboss.jandex.AnnotationTarget;
|
||||||
|
import org.jboss.jandex.AnnotationValue;
|
||||||
import org.jboss.jandex.ClassInfo;
|
import org.jboss.jandex.ClassInfo;
|
||||||
import org.jboss.jandex.FieldInfo;
|
import org.jboss.jandex.FieldInfo;
|
||||||
import org.jboss.jandex.MethodInfo;
|
import org.jboss.jandex.MethodInfo;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
|
@ -59,27 +60,61 @@ import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public class ConfiguredClass {
|
public class ConfiguredClass {
|
||||||
|
/**
|
||||||
|
* The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy.
|
||||||
|
*/
|
||||||
private final ConfiguredClass parent;
|
private final ConfiguredClass parent;
|
||||||
private final ClassInfo classInfo;
|
private final ClassInfo classInfo;
|
||||||
private final Class<?> clazz;
|
private final Class<?> clazz;
|
||||||
|
|
||||||
private final boolean isRoot;
|
private final boolean isRoot;
|
||||||
private final AccessType classAccessType;
|
private final AccessType classAccessType;
|
||||||
private final AccessType hierarchyAccessType;
|
private final AccessType hierarchyAccessType;
|
||||||
|
|
||||||
|
private final InheritanceType inheritanceType;
|
||||||
|
private final boolean hasOwnTable;
|
||||||
|
private final String primaryTableName;
|
||||||
|
private final AnnotationInstance tableAnnotation;
|
||||||
|
|
||||||
private final boolean isMappedSuperClass;
|
private final boolean isMappedSuperClass;
|
||||||
|
private final boolean isEmbeddable;
|
||||||
|
|
||||||
private final Map<String, MappedProperty> mappedProperties;
|
private final Map<String, MappedProperty> mappedProperties;
|
||||||
|
|
||||||
public ConfiguredClass(ClassInfo info, ConfiguredClass parent, AccessType hierarchyAccessType, ServiceRegistry serviceRegistry, ResolvedTypeWithMembers resolvedType) {
|
public ConfiguredClass(ClassInfo info,
|
||||||
|
ConfiguredClass parent,
|
||||||
|
AccessType hierarchyAccessType,
|
||||||
|
InheritanceType inheritanceType,
|
||||||
|
ServiceRegistry serviceRegistry,
|
||||||
|
ResolvedTypeWithMembers resolvedType) {
|
||||||
this.classInfo = info;
|
this.classInfo = info;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.isRoot = parent == null;
|
this.isRoot = parent == null;
|
||||||
this.hierarchyAccessType = hierarchyAccessType;
|
this.hierarchyAccessType = hierarchyAccessType;
|
||||||
|
this.inheritanceType = inheritanceType;
|
||||||
AnnotationInstance mappedSuperClassAnnotation = assertNotEntityAndMappedSuperClass();
|
|
||||||
|
|
||||||
this.clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( info.toString() );
|
this.clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( info.toString() );
|
||||||
|
|
||||||
|
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
|
||||||
|
classInfo, JPADotNames.MAPPED_SUPER_CLASS
|
||||||
|
);
|
||||||
isMappedSuperClass = mappedSuperClassAnnotation != null;
|
isMappedSuperClass = mappedSuperClassAnnotation != null;
|
||||||
|
|
||||||
|
AnnotationInstance embeddableAnnotation = JandexHelper.getSingleAnnotation(
|
||||||
|
classInfo, JPADotNames.MAPPED_SUPER_CLASS
|
||||||
|
);
|
||||||
|
isEmbeddable = embeddableAnnotation != null;
|
||||||
|
|
||||||
|
tableAnnotation = JandexHelper.getSingleAnnotation(
|
||||||
|
classInfo, JPADotNames.TABLE
|
||||||
|
);
|
||||||
|
|
||||||
|
// todo think about how exactly to handle embeddables regarding access type etc
|
||||||
|
|
||||||
classAccessType = determineClassAccessType();
|
classAccessType = determineClassAccessType();
|
||||||
|
|
||||||
|
hasOwnTable = definesItsOwnTable();
|
||||||
|
primaryTableName = determinePrimaryTableName();
|
||||||
|
|
||||||
List<MappedProperty> properties = collectMappedProperties( resolvedType );
|
List<MappedProperty> properties = collectMappedProperties( resolvedType );
|
||||||
// make sure the properties are ordered by property name
|
// make sure the properties are ordered by property name
|
||||||
Collections.sort( properties );
|
Collections.sort( properties );
|
||||||
|
@ -110,6 +145,22 @@ public class ConfiguredClass {
|
||||||
return isMappedSuperClass;
|
return isMappedSuperClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEmbeddable() {
|
||||||
|
return isEmbeddable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InheritanceType getInheritanceType() {
|
||||||
|
return inheritanceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasOwnTable() {
|
||||||
|
return hasOwnTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrimaryTableName() {
|
||||||
|
return primaryTableName;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterable<MappedProperty> getMappedProperties() {
|
public Iterable<MappedProperty> getMappedProperties() {
|
||||||
return mappedProperties.values();
|
return mappedProperties.values();
|
||||||
}
|
}
|
||||||
|
@ -126,6 +177,7 @@ public class ConfiguredClass {
|
||||||
sb.append( ", mappedProperties=" ).append( mappedProperties );
|
sb.append( ", mappedProperties=" ).append( mappedProperties );
|
||||||
sb.append( ", classAccessType=" ).append( classAccessType );
|
sb.append( ", classAccessType=" ).append( classAccessType );
|
||||||
sb.append( ", isRoot=" ).append( isRoot );
|
sb.append( ", isRoot=" ).append( isRoot );
|
||||||
|
sb.append( ", inheritanceType=" ).append( inheritanceType );
|
||||||
sb.append( '}' );
|
sb.append( '}' );
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
@ -344,20 +396,39 @@ public class ConfiguredClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnnotationInstance assertNotEntityAndMappedSuperClass() {
|
private boolean definesItsOwnTable() {
|
||||||
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
|
// mapped super classes and embeddables don't have their own tables
|
||||||
AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.ENTITY );
|
if ( isMappedSuperClass() || isEmbeddable() ) {
|
||||||
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
|
return false;
|
||||||
classInfo, JPADotNames.MAPPED_SUPER_CLASS
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) {
|
|
||||||
throw new AnnotationException(
|
|
||||||
"An entity cannot be annotated with both @Entity and @MappedSuperclass: "
|
|
||||||
+ classInfo.name().toString()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return mappedSuperClassAnnotation;
|
|
||||||
|
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceType ) ) {
|
||||||
|
if ( isRoot() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String determinePrimaryTableName() {
|
||||||
|
String tableName = null;
|
||||||
|
if ( hasOwnTable() ) {
|
||||||
|
tableName = clazz.getSimpleName();
|
||||||
|
if ( tableAnnotation != null ) {
|
||||||
|
AnnotationValue value = tableAnnotation.value( "name" );
|
||||||
|
String tmp = value == null ? null : value.asString();
|
||||||
|
if ( tmp != null && !tmp.isEmpty() ) {
|
||||||
|
tableName = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( parent != null && !parent.isMappedSuperClass && !parent.isEmbeddable ) {
|
||||||
|
tableName = parent.getPrimaryTableName();
|
||||||
|
}
|
||||||
|
return tableName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,9 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
||||||
configuredClasses = new ArrayList<ConfiguredClass>();
|
configuredClasses = new ArrayList<ConfiguredClass>();
|
||||||
ConfiguredClass parent = null;
|
ConfiguredClass parent = null;
|
||||||
for ( ClassInfo info : classes ) {
|
for ( ClassInfo info : classes ) {
|
||||||
ConfiguredClass configuredClass = new ConfiguredClass( info, parent, defaultAccessType, serviceRegistry, resolvedMembers );
|
ConfiguredClass configuredClass = new ConfiguredClass(
|
||||||
|
info, parent, defaultAccessType, inheritanceType, serviceRegistry, resolvedMembers
|
||||||
|
);
|
||||||
configuredClasses.add( configuredClass );
|
configuredClasses.add( configuredClass );
|
||||||
parent = configuredClass;
|
parent = configuredClass;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,17 @@ public class EntityBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindTable(EntityBinding entityBinding) {
|
private void bindTable(EntityBinding entityBinding) {
|
||||||
|
|
||||||
|
// this.schemaName = new Schema.Name(
|
||||||
|
// ( entityClazz.getSchema() == null ?
|
||||||
|
// hibernateMappingBinder.getDefaultSchemaName() :
|
||||||
|
// entityClazz.getSchema() ),
|
||||||
|
// ( entityClazz.getCatalog() == null ?
|
||||||
|
// hibernateMappingBinder.getDefaultCatalogName() :
|
||||||
|
// entityClazz.getCatalog() )
|
||||||
|
// );
|
||||||
|
|
||||||
|
|
||||||
final Schema schema = meta.getDatabase().getSchema( null );
|
final Schema schema = meta.getDatabase().getSchema( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.annotations.Check;
|
||||||
import org.hibernate.annotations.Entity;
|
import org.hibernate.annotations.Entity;
|
||||||
import org.hibernate.annotations.FetchProfile;
|
import org.hibernate.annotations.FetchProfile;
|
||||||
import org.hibernate.annotations.FetchProfiles;
|
import org.hibernate.annotations.FetchProfiles;
|
||||||
|
import org.hibernate.annotations.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the dot names for the Hibernate specific annotations.
|
* Defines the dot names for the Hibernate specific annotations.
|
||||||
|
@ -37,6 +38,8 @@ import org.hibernate.annotations.FetchProfiles;
|
||||||
*/
|
*/
|
||||||
public interface HibernateDotNames {
|
public interface HibernateDotNames {
|
||||||
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
|
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
|
||||||
|
public static final DotName TABLE = DotName.createSimple( Table.class.getName() );
|
||||||
|
|
||||||
public static final DotName FETCH_PROFILES = DotName.createSimple( FetchProfiles.class.getName() );
|
public static final DotName FETCH_PROFILES = DotName.createSimple( FetchProfiles.class.getName() );
|
||||||
public static final DotName FETCH_PROFILE = DotName.createSimple( FetchProfile.class.getName() );
|
public static final DotName FETCH_PROFILE = DotName.createSimple( FetchProfile.class.getName() );
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
package org.hibernate.metamodel.source.annotations;
|
package org.hibernate.metamodel.source.annotations;
|
||||||
|
|
||||||
import javax.persistence.Access;
|
import javax.persistence.Access;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.EmbeddedId;
|
import javax.persistence.EmbeddedId;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
@ -42,6 +43,8 @@ import org.jboss.jandex.DotName;
|
||||||
public interface JPADotNames {
|
public interface JPADotNames {
|
||||||
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
|
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
|
||||||
public static final DotName MAPPED_SUPER_CLASS = DotName.createSimple( MappedSuperclass.class.getName() );
|
public static final DotName MAPPED_SUPER_CLASS = DotName.createSimple( MappedSuperclass.class.getName() );
|
||||||
|
public static final DotName EMBEDDABLE = DotName.createSimple( Embeddable.class.getName() );
|
||||||
|
|
||||||
public static final DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() );
|
public static final DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() );
|
||||||
|
|
||||||
public static final DotName ID = DotName.createSimple( Id.class.getName() );
|
public static final DotName ID = DotName.createSimple( Id.class.getName() );
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, 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
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.source.annotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This package contains the core binding code for binding annotation based configuration to the Hibernate metadata model.
|
||||||
|
*/
|
|
@ -35,6 +35,7 @@ import org.jboss.jandex.ClassInfo;
|
||||||
import org.jboss.jandex.DotName;
|
import org.jboss.jandex.DotName;
|
||||||
import org.jboss.jandex.Index;
|
import org.jboss.jandex.Index;
|
||||||
|
|
||||||
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.metamodel.source.annotations.ConfiguredClassHierarchy;
|
import org.hibernate.metamodel.source.annotations.ConfiguredClassHierarchy;
|
||||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
@ -54,19 +55,14 @@ public class ConfiguredClassHierarchyBuilder {
|
||||||
* @param index The annotation index
|
* @param index The annotation index
|
||||||
* @param serviceRegistry The service registry
|
* @param serviceRegistry The service registry
|
||||||
*
|
*
|
||||||
* @return a set of {@code ConfiguredClassHierarchy}s. One for each configured "leaf" entity.
|
* @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity.
|
||||||
*/
|
*/
|
||||||
public static Set<ConfiguredClassHierarchy> createEntityHierarchies(Index index, ServiceRegistry serviceRegistry) {
|
public static Set<ConfiguredClassHierarchy> createEntityHierarchies(Index index, ServiceRegistry serviceRegistry) {
|
||||||
ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||||
Map<ClassInfo, List<ClassInfo>> processedClassInfos = new HashMap<ClassInfo, List<ClassInfo>>();
|
Map<ClassInfo, List<ClassInfo>> processedClassInfos = new HashMap<ClassInfo, List<ClassInfo>>();
|
||||||
|
|
||||||
for ( ClassInfo info : index.getKnownClasses() ) {
|
for ( ClassInfo info : index.getKnownClasses() ) {
|
||||||
AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( info, JPADotNames.ENTITY );
|
if ( !isConfiguredClass( info ) ) {
|
||||||
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
|
|
||||||
info, JPADotNames.MAPPED_SUPER_CLASS
|
|
||||||
);
|
|
||||||
// we are only interested in building the class hierarchies for @Entity or @MappedSuperclass w
|
|
||||||
if ( jpaEntityAnnotation == null && mappedSuperClassAnnotation == null ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +106,29 @@ public class ConfiguredClassHierarchyBuilder {
|
||||||
return hierarchies;
|
return hierarchies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isConfiguredClass(ClassInfo info) {
|
||||||
|
boolean isConfiguredClass = true;
|
||||||
|
AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( info, JPADotNames.ENTITY );
|
||||||
|
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
|
||||||
|
info, JPADotNames.MAPPED_SUPER_CLASS
|
||||||
|
);
|
||||||
|
AnnotationInstance embeddableAnnotation = JandexHelper.getSingleAnnotation(
|
||||||
|
info, JPADotNames.EMBEDDABLE
|
||||||
|
);
|
||||||
|
|
||||||
|
// we are only interested in building the class hierarchies for @Entity or @MappedSuperclass w
|
||||||
|
if ( jpaEntityAnnotation == null && mappedSuperClassAnnotation == null && embeddableAnnotation == null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// some sanity checks
|
||||||
|
String className = info.toString();
|
||||||
|
assertNotEntityAndMappedSuperClass( jpaEntityAnnotation, mappedSuperClassAnnotation, className );
|
||||||
|
assertNotEntityAndEmbeddable( jpaEntityAnnotation, embeddableAnnotation, className );
|
||||||
|
|
||||||
|
return isConfiguredClass;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean existsHierarchyWithClassInfoAsLeaf(Map<ClassInfo, List<ClassInfo>> processedClassInfos, ClassInfo tmpClassInfo) {
|
private static boolean existsHierarchyWithClassInfoAsLeaf(Map<ClassInfo, List<ClassInfo>> processedClassInfos, ClassInfo tmpClassInfo) {
|
||||||
if ( !processedClassInfos.containsKey( tmpClassInfo ) ) {
|
if ( !processedClassInfos.containsKey( tmpClassInfo ) ) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -118,6 +137,22 @@ public class ConfiguredClassHierarchyBuilder {
|
||||||
List<ClassInfo> classInfoList = processedClassInfos.get( tmpClassInfo );
|
List<ClassInfo> classInfoList = processedClassInfos.get( tmpClassInfo );
|
||||||
return classInfoList.get( classInfoList.size() - 1 ).equals( tmpClassInfo );
|
return classInfoList.get( classInfoList.size() - 1 ).equals( tmpClassInfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void assertNotEntityAndMappedSuperClass(AnnotationInstance jpaEntityAnnotation, AnnotationInstance mappedSuperClassAnnotation, String className) {
|
||||||
|
if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) {
|
||||||
|
throw new AnnotationException(
|
||||||
|
"An entity cannot be annotated with both @Entity and @MappedSuperclass. " + className + " has both annotations."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertNotEntityAndEmbeddable(AnnotationInstance jpaEntityAnnotation, AnnotationInstance embeddableAnnotation, String className) {
|
||||||
|
if ( jpaEntityAnnotation != null && embeddableAnnotation != null ) {
|
||||||
|
throw new AnnotationException(
|
||||||
|
"An entity cannot be annotated with both @Entity and @Embeddable. " + className + " has both annotations."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, 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
|
||||||
|
*/
|
||||||
|
package org.hibernate.metamodel.source.annotations;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.jboss.jandex.ClassInfo;
|
||||||
|
import org.jboss.jandex.DotName;
|
||||||
|
import org.jboss.jandex.Index;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder;
|
||||||
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
|
import org.hibernate.service.ServiceRegistryBuilder;
|
||||||
|
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Hardy Ferentschik
|
||||||
|
*/
|
||||||
|
public class TableNameTest extends BaseUnitTestCase {
|
||||||
|
|
||||||
|
private BasicServiceRegistryImpl serviceRegistry;
|
||||||
|
private ClassLoaderService service;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
serviceRegistry = (BasicServiceRegistryImpl) new ServiceRegistryBuilder().buildServiceRegistry();
|
||||||
|
service = serviceRegistry.getService( ClassLoaderService.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
serviceRegistry.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleInheritanceDefaultTableName() {
|
||||||
|
@Entity
|
||||||
|
class A {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private int id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class B extends A {
|
||||||
|
}
|
||||||
|
|
||||||
|
Index index = JandexHelper.indexForClass( service, A.class, B.class );
|
||||||
|
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||||
|
index, serviceRegistry
|
||||||
|
);
|
||||||
|
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||||
|
|
||||||
|
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
|
||||||
|
ConfiguredClass configuredClass = iter.next();
|
||||||
|
ClassInfo info = configuredClass.getClassInfo();
|
||||||
|
assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() );
|
||||||
|
assertTrue( configuredClass.hasOwnTable() );
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong inheritance type", InheritanceType.SINGLE_TABLE, configuredClass.getInheritanceType()
|
||||||
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong table name", "A", configuredClass.getPrimaryTableName()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue( iter.hasNext() );
|
||||||
|
configuredClass = iter.next();
|
||||||
|
info = configuredClass.getClassInfo();
|
||||||
|
assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() );
|
||||||
|
assertFalse( configuredClass.hasOwnTable() );
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong inheritance type", InheritanceType.SINGLE_TABLE, configuredClass.getInheritanceType()
|
||||||
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong table name", "A", configuredClass.getPrimaryTableName()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertFalse( iter.hasNext() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTablePerClassDefaultTableName() {
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||||
|
class A {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private int id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class B extends A {
|
||||||
|
}
|
||||||
|
|
||||||
|
Index index = JandexHelper.indexForClass( service, A.class, B.class );
|
||||||
|
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||||
|
index, serviceRegistry
|
||||||
|
);
|
||||||
|
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||||
|
|
||||||
|
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
|
||||||
|
ConfiguredClass configuredClass = iter.next();
|
||||||
|
ClassInfo info = configuredClass.getClassInfo();
|
||||||
|
assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() );
|
||||||
|
assertTrue( configuredClass.hasOwnTable() );
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong inheritance type", InheritanceType.TABLE_PER_CLASS, configuredClass.getInheritanceType()
|
||||||
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong table name", "A", configuredClass.getPrimaryTableName()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue( iter.hasNext() );
|
||||||
|
configuredClass = iter.next();
|
||||||
|
info = configuredClass.getClassInfo();
|
||||||
|
assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() );
|
||||||
|
assertTrue( configuredClass.hasOwnTable() );
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong inheritance type", InheritanceType.TABLE_PER_CLASS, configuredClass.getInheritanceType()
|
||||||
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong table name", "B", configuredClass.getPrimaryTableName()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertFalse( iter.hasNext() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinedSubclassDefaultTableName() {
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
@Table(name = "FOO")
|
||||||
|
class A {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private int id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class B extends A {
|
||||||
|
}
|
||||||
|
|
||||||
|
Index index = JandexHelper.indexForClass( service, B.class, A.class );
|
||||||
|
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||||
|
index, serviceRegistry
|
||||||
|
);
|
||||||
|
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||||
|
|
||||||
|
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
|
||||||
|
ConfiguredClass configuredClass = iter.next();
|
||||||
|
ClassInfo info = configuredClass.getClassInfo();
|
||||||
|
assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() );
|
||||||
|
assertTrue( configuredClass.hasOwnTable() );
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong inheritance type", InheritanceType.JOINED, configuredClass.getInheritanceType()
|
||||||
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong table name", "FOO", configuredClass.getPrimaryTableName()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue( iter.hasNext() );
|
||||||
|
configuredClass = iter.next();
|
||||||
|
info = configuredClass.getClassInfo();
|
||||||
|
assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() );
|
||||||
|
assertTrue( configuredClass.hasOwnTable() );
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong inheritance type", InheritanceType.JOINED, configuredClass.getInheritanceType()
|
||||||
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"wrong table name", "B", configuredClass.getPrimaryTableName()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertFalse( iter.hasNext() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.metamodel.source.annotations.util;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.AccessType;
|
import javax.persistence.AccessType;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
@ -157,6 +158,17 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
||||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = AnnotationException.class)
|
||||||
|
public void testEntityAndEmbeddableAnnotations() {
|
||||||
|
@Entity
|
||||||
|
@Embeddable
|
||||||
|
class EntityAndEmbeddable {
|
||||||
|
}
|
||||||
|
|
||||||
|
Index index = JandexHelper.indexForClass( service, EntityAndEmbeddable.class );
|
||||||
|
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = AnnotationException.class)
|
@Test(expected = AnnotationException.class)
|
||||||
public void testNoIdAnnotation() {
|
public void testNoIdAnnotation() {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue