HHH-15813 add @Imported annotation
This commit is contained in:
parent
c29f2eaf60
commit
9526eb89b7
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* Marks an arbitrary class as available for use in HQL queries by its unqualified name.
|
||||
* <p>
|
||||
* By default, non-entity class names must be fully-qualified in the query language.
|
||||
*
|
||||
* @author Gavin King
|
||||
*
|
||||
* @since 6.2
|
||||
*/
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Imported {
|
||||
/**
|
||||
* Provide an alias for the class, to avoid collisions.
|
||||
*/
|
||||
String rename() default "";
|
||||
}
|
|
@ -27,6 +27,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.annotations.CollectionTypeRegistration;
|
||||
import org.hibernate.annotations.Imported;
|
||||
import org.hibernate.annotations.Parameter;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.boot.CacheRegionDefinition;
|
||||
|
@ -808,12 +809,12 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addImport(String importName, String entityName) {
|
||||
if ( importName == null || entityName == null ) {
|
||||
public void addImport(String importName, String className) {
|
||||
if ( importName == null || className == null ) {
|
||||
throw new IllegalArgumentException( "Import name or entity name is null" );
|
||||
}
|
||||
log.tracev( "Import: {0} -> {1}", importName, entityName );
|
||||
String old = imports.put( importName, entityName );
|
||||
log.tracev( "Import: {0} -> {1}", importName, className);
|
||||
String old = imports.put( importName, className);
|
||||
if ( old != null ) {
|
||||
log.debugf( "import name [%s] overrode previous [{%s}]", importName, old );
|
||||
}
|
||||
|
@ -1185,23 +1186,29 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|||
|
||||
@Override
|
||||
public AnnotatedClassType addClassType(XClass clazz) {
|
||||
AnnotatedClassType type;
|
||||
if ( clazz.isAnnotationPresent( Entity.class ) ) {
|
||||
type = AnnotatedClassType.ENTITY;
|
||||
}
|
||||
else if ( clazz.isAnnotationPresent( Embeddable.class ) ) {
|
||||
type = AnnotatedClassType.EMBEDDABLE;
|
||||
}
|
||||
else if ( clazz.isAnnotationPresent( jakarta.persistence.MappedSuperclass.class ) ) {
|
||||
type = AnnotatedClassType.MAPPED_SUPERCLASS;
|
||||
}
|
||||
else {
|
||||
type = AnnotatedClassType.NONE;
|
||||
}
|
||||
final AnnotatedClassType type = getAnnotatedClassType(clazz);
|
||||
annotatedClassTypeMap.put( clazz.getName(), type );
|
||||
return type;
|
||||
}
|
||||
|
||||
private static AnnotatedClassType getAnnotatedClassType(XClass clazz) {
|
||||
if ( clazz.isAnnotationPresent( Entity.class ) ) {
|
||||
return AnnotatedClassType.ENTITY;
|
||||
}
|
||||
else if ( clazz.isAnnotationPresent( Embeddable.class ) ) {
|
||||
return AnnotatedClassType.EMBEDDABLE;
|
||||
}
|
||||
else if ( clazz.isAnnotationPresent( jakarta.persistence.MappedSuperclass.class ) ) {
|
||||
return AnnotatedClassType.MAPPED_SUPERCLASS;
|
||||
}
|
||||
else if ( clazz.isAnnotationPresent( Imported.class ) ) {
|
||||
return AnnotatedClassType.IMPORTED;
|
||||
}
|
||||
else {
|
||||
return AnnotatedClassType.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addMappedSuperclass(Class type, MappedSuperclass mappedSuperclass) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.annotations.Imported;
|
||||
import org.hibernate.annotations.common.reflection.MetadataProviderInjector;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
|
@ -19,7 +20,6 @@ import org.hibernate.boot.AttributeConverterInfo;
|
|||
import org.hibernate.boot.internal.MetadataBuildingContextRootImpl;
|
||||
import org.hibernate.boot.jaxb.mapping.JaxbEntityMappings;
|
||||
import org.hibernate.boot.jaxb.spi.Binding;
|
||||
import org.hibernate.boot.model.convert.internal.AttributeConverterManager;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.model.process.spi.ManagedResources;
|
||||
import org.hibernate.boot.model.source.spi.MetadataSourceProcessor;
|
||||
|
@ -117,10 +117,9 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
|||
attributeConverterManager.addAttributeConverter( (Class<? extends AttributeConverter<?,?>>) annotatedClass );
|
||||
}
|
||||
else if ( xClass.isAnnotationPresent( Entity.class )
|
||||
|| xClass.isAnnotationPresent( MappedSuperclass.class ) ) {
|
||||
xClasses.add( xClass );
|
||||
}
|
||||
else if ( xClass.isAnnotationPresent( Embeddable.class ) ) {
|
||||
|| xClass.isAnnotationPresent( MappedSuperclass.class )
|
||||
|| xClass.isAnnotationPresent( Embeddable.class )
|
||||
|| xClass.isAnnotationPresent( Imported.class ) ) {
|
||||
xClasses.add( xClass );
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -86,15 +86,15 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
|
|||
void registerComponent(Component component);
|
||||
|
||||
/**
|
||||
* Adds an import (HQL entity rename).
|
||||
* Adds an import (for use in HQL).
|
||||
*
|
||||
* @param entityName The entity name being renamed.
|
||||
* @param rename The rename
|
||||
* @param importName The name to be used in HQL
|
||||
* @param className The fully-qualified name of the class
|
||||
*
|
||||
* @throws DuplicateMappingException If rename already is mapped to another
|
||||
* @throws DuplicateMappingException If className already is mapped to another
|
||||
* entity name in this repository.
|
||||
*/
|
||||
void addImport(String entityName, String rename) throws DuplicateMappingException;
|
||||
void addImport(String importName, String className) throws DuplicateMappingException;
|
||||
|
||||
/**
|
||||
* Add collection mapping metadata to this repository.
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.cfg;
|
||||
|
||||
|
||||
import org.hibernate.annotations.Imported;
|
||||
|
||||
/**
|
||||
* Type of annotation of a class will give its type
|
||||
*
|
||||
|
@ -17,6 +19,10 @@ public enum AnnotatedClassType {
|
|||
* has no relevant top level annotation
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* has an {@link Imported} annotation
|
||||
*/
|
||||
IMPORTED,
|
||||
/**
|
||||
* has an {@link jakarta.persistence.Entity} annotation
|
||||
*/
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.annotations.Formula;
|
|||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.GenericGenerators;
|
||||
import org.hibernate.annotations.IdGeneratorType;
|
||||
import org.hibernate.annotations.Imported;
|
||||
import org.hibernate.annotations.Index;
|
||||
import org.hibernate.annotations.JavaTypeRegistration;
|
||||
import org.hibernate.annotations.JavaTypeRegistrations;
|
||||
|
@ -77,6 +78,7 @@ import org.hibernate.engine.OptimisticLockStyle;
|
|||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.GenericsHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.Any;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Join;
|
||||
|
@ -148,12 +150,12 @@ import static org.hibernate.cfg.BinderHelper.getPath;
|
|||
import static org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId;
|
||||
import static org.hibernate.cfg.BinderHelper.getRelativePath;
|
||||
import static org.hibernate.cfg.BinderHelper.hasToOneAnnotation;
|
||||
import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
|
||||
import static org.hibernate.cfg.BinderHelper.makeIdGenerator;
|
||||
import static org.hibernate.cfg.InheritanceState.getInheritanceStateOfSuperEntity;
|
||||
import static org.hibernate.cfg.InheritanceState.getSuperclassInheritanceState;
|
||||
import static org.hibernate.cfg.PropertyHolderBuilder.buildPropertyHolder;
|
||||
import static org.hibernate.cfg.annotations.HCANNHelper.findContainingAnnotation;
|
||||
import static org.hibernate.cfg.annotations.PropertyBinder.generatorCreator;
|
||||
import static org.hibernate.cfg.annotations.PropertyBinder.identifierGeneratorCreator;
|
||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
||||
import static org.hibernate.mapping.Constraint.hashedName;
|
||||
|
@ -517,6 +519,8 @@ public final class AnnotationBinder {
|
|||
bindQueries( annotatedClass, context );
|
||||
bindFilterDefs( annotatedClass, context );
|
||||
//fall through:
|
||||
case IMPORTED:
|
||||
handleImport( annotatedClass, context );
|
||||
case EMBEDDABLE:
|
||||
case NONE:
|
||||
return;
|
||||
|
@ -535,6 +539,15 @@ public final class AnnotationBinder {
|
|||
EntityBinder.bindEntityClass( annotatedClass, inheritanceStatePerClass, generators, context );
|
||||
}
|
||||
|
||||
private static void handleImport(XClass annotatedClass, MetadataBuildingContext context) {
|
||||
if ( annotatedClass.isAnnotationPresent(Imported.class) ) {
|
||||
String qualifiedName = annotatedClass.getName();
|
||||
String name = StringHelper.unqualify( qualifiedName );
|
||||
String rename = annotatedClass.getAnnotation(Imported.class).rename();
|
||||
context.getMetadataCollector().addImport( isEmptyAnnotationValue( rename ) ? name : rename, qualifiedName );
|
||||
}
|
||||
}
|
||||
|
||||
private static void detectMappedSuperclassProblems(XClass annotatedClass) {
|
||||
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
|
||||
if ( annotatedClass.isAnnotationPresent( Entity.class )
|
||||
|
|
|
@ -375,7 +375,7 @@ public class PropertyBinder {
|
|||
property.setUpdateable( updatable );
|
||||
property.setPropertyAccessStrategy( propertyAccessStrategy );
|
||||
|
||||
inferOptimisticLocking(property);
|
||||
inferOptimisticLocking( property );
|
||||
|
||||
LOG.tracev( "Cascading {0} with {1}", name, cascade );
|
||||
return property;
|
||||
|
|
|
@ -16,6 +16,7 @@ import jakarta.persistence.Id;
|
|||
import jakarta.persistence.ManyToMany;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.annotations.Imported;
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
@ -31,7 +32,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.core.Is.is;
|
||||
|
||||
@TestForIssue( jiraKey = "HHH-13619" )
|
||||
@DomainModel( annotatedClasses = { ManyToManySizeTest.Company.class, ManyToManySizeTest.Customer.class } )
|
||||
@DomainModel( annotatedClasses = { ManyToManySizeTest.Company.class, ManyToManySizeTest.Customer.class, ManyToManySizeTest.CompanyDto.class } )
|
||||
@SessionFactory
|
||||
public class ManyToManySizeTest {
|
||||
|
||||
|
@ -82,7 +83,7 @@ public class ManyToManySizeTest {
|
|||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final List results = session.createQuery(
|
||||
"select new org.hibernate.orm.test.query.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||
"select new ManyToManySizeTest$CompanyDto(" +
|
||||
" c.id, c.name, size( c.customers ) )" +
|
||||
" from Company c" +
|
||||
" group by c.id, c.name" +
|
||||
|
@ -111,7 +112,7 @@ public class ManyToManySizeTest {
|
|||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final List results = session.createQuery(
|
||||
"select new org.hibernate.orm.test.query.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||
"select new ManyToManySizeTest$CompanyDto(" +
|
||||
" c.id, c.name, size( c.customers ) )" +
|
||||
" from Company c left join c.customers cu" +
|
||||
" group by c.id, c.name" +
|
||||
|
@ -140,7 +141,7 @@ public class ManyToManySizeTest {
|
|||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final List results = session.createQuery(
|
||||
"select new org.hibernate.orm.test.query.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||
"select new ManyToManySizeTest$CompanyDto(" +
|
||||
" c.id, c.name, size( c.customers ) )" +
|
||||
" from Company c inner join c.customers cu" +
|
||||
" group by c.id, c.name" +
|
||||
|
@ -165,7 +166,7 @@ public class ManyToManySizeTest {
|
|||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final List results = session.createQuery(
|
||||
"select new org.hibernate.orm.test.query.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||
"select new ManyToManySizeTest$CompanyDto(" +
|
||||
" c.id, c.name, size( cu ) )" +
|
||||
" from Company c inner join c.customers cu" +
|
||||
" group by c.id, c.name" +
|
||||
|
@ -190,7 +191,7 @@ public class ManyToManySizeTest {
|
|||
scope.inTransaction(
|
||||
session -> {
|
||||
final List results = session.createQuery(
|
||||
"select new org.hibernate.orm.test.query.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||
"select new ManyToManySizeTest$CompanyDto(" +
|
||||
" c.id, c.name, size( c.customers ) )" +
|
||||
" from Company c" +
|
||||
" where c.id != 0" +
|
||||
|
@ -335,6 +336,7 @@ public class ManyToManySizeTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Imported
|
||||
public static class CompanyDto {
|
||||
|
||||
public int id;
|
||||
|
|
Loading…
Reference in New Issue