HHH-18649 populate EntityGraph in static metamodel
This commit is contained in:
parent
c863838e72
commit
600288d1bb
|
@ -42,7 +42,8 @@ public class NamedHqlQueryDefinitionImpl<E> extends AbstractNamedQueryDefinition
|
|||
Integer fetchSize,
|
||||
String comment,
|
||||
Map<String,String> parameterTypes,
|
||||
Map<String,Object> hints) {
|
||||
Map<String,Object> hints,
|
||||
String location) {
|
||||
super(
|
||||
name,
|
||||
resultType,
|
||||
|
@ -55,7 +56,8 @@ public class NamedHqlQueryDefinitionImpl<E> extends AbstractNamedQueryDefinition
|
|||
timeout,
|
||||
fetchSize,
|
||||
comment,
|
||||
hints
|
||||
hints,
|
||||
location
|
||||
);
|
||||
this.hqlString = hqlString;
|
||||
this.firstResult = firstResult;
|
||||
|
|
|
@ -44,7 +44,8 @@ public class NamedNativeQueryDefinitionImpl<E> extends AbstractNamedQueryDefinit
|
|||
String comment,
|
||||
Integer firstResult,
|
||||
Integer maxResults,
|
||||
Map<String,Object> hints) {
|
||||
Map<String,Object> hints,
|
||||
String location) {
|
||||
super(
|
||||
name,
|
||||
resultType,
|
||||
|
@ -57,7 +58,8 @@ public class NamedNativeQueryDefinitionImpl<E> extends AbstractNamedQueryDefinit
|
|||
timeout,
|
||||
fetchSize,
|
||||
comment,
|
||||
hints
|
||||
hints,
|
||||
location
|
||||
);
|
||||
this.sqlString = sqlString;
|
||||
this.resultSetMappingName = resultSetMappingName;
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -74,6 +75,12 @@ public class NamedProcedureCallDefinitionImpl implements NamedProcedureCallDefin
|
|||
return registeredName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getLocation() {
|
||||
// not kept for now
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProcedureName() {
|
||||
return procedureName;
|
||||
|
|
|
@ -104,11 +104,11 @@ public final class AnnotationBinder {
|
|||
// queries ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
globalRegistrations.getNamedQueryRegistrations().forEach( (name, queryRegistration) -> {
|
||||
QueryBinder.bindQuery( queryRegistration.configuration(), context, true );
|
||||
QueryBinder.bindQuery( queryRegistration.configuration(), context, true, null );
|
||||
} );
|
||||
|
||||
globalRegistrations.getNamedNativeQueryRegistrations().forEach( (name, queryRegistration) -> {
|
||||
QueryBinder.bindNativeQuery( queryRegistration.configuration(), context, true );
|
||||
QueryBinder.bindNativeQuery( queryRegistration.configuration(), context, null, true );
|
||||
} );
|
||||
|
||||
globalRegistrations.getNamedStoredProcedureQueryRegistrations().forEach( (name, queryRegistration) -> {
|
||||
|
@ -152,13 +152,13 @@ public final class AnnotationBinder {
|
|||
annotationTarget.forEachRepeatedAnnotationUsages(
|
||||
HibernateAnnotations.NAMED_QUERY,
|
||||
sourceModelContext,
|
||||
(usage) -> QueryBinder.bindQuery( usage, context )
|
||||
(usage) -> QueryBinder.bindQuery( usage, context, annotationTarget )
|
||||
);
|
||||
|
||||
annotationTarget.forEachRepeatedAnnotationUsages(
|
||||
HibernateAnnotations.NAMED_NATIVE_QUERY,
|
||||
sourceModelContext,
|
||||
(usage) -> QueryBinder.bindNativeQuery( usage, context )
|
||||
(usage) -> QueryBinder.bindNativeQuery( usage, context, annotationTarget )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -174,13 +174,13 @@ public final class AnnotationBinder {
|
|||
annotationTarget.forEachRepeatedAnnotationUsages(
|
||||
JpaAnnotations.NAMED_QUERY,
|
||||
sourceModelContext,
|
||||
(usage) -> QueryBinder.bindQuery( usage, context, false )
|
||||
(usage) -> QueryBinder.bindQuery( usage, context, false, annotationTarget )
|
||||
);
|
||||
|
||||
annotationTarget.forEachRepeatedAnnotationUsages(
|
||||
JpaAnnotations.NAMED_NATIVE_QUERY,
|
||||
sourceModelContext,
|
||||
(usage) -> QueryBinder.bindNativeQuery( usage, context, false )
|
||||
(usage) -> QueryBinder.bindNativeQuery( usage, context, annotationTarget, false )
|
||||
);
|
||||
|
||||
annotationTarget.forEachRepeatedAnnotationUsages(
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.function.Supplier;
|
|||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.models.spi.AnnotationTarget;
|
||||
import org.hibernate.query.QueryFlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.annotations.FlushModeType;
|
||||
|
@ -74,7 +75,8 @@ public abstract class QueryBinder {
|
|||
public static void bindQuery(
|
||||
NamedQuery namedQuery,
|
||||
MetadataBuildingContext context,
|
||||
boolean isDefault) {
|
||||
boolean isDefault,
|
||||
AnnotationTarget annotationTarget) {
|
||||
if ( namedQuery == null ) {
|
||||
return;
|
||||
}
|
||||
|
@ -94,7 +96,7 @@ public abstract class QueryBinder {
|
|||
final QueryHintDefinition hints = new QueryHintDefinition( queryName, namedQuery.hints() );
|
||||
final NamedHqlQueryDefinition<?> queryMapping =
|
||||
createNamedQueryDefinition( queryName, queryString, resultClass,
|
||||
hints.determineLockOptions( namedQuery ), hints );
|
||||
hints.determineLockOptions( namedQuery ), hints, annotationTarget );
|
||||
if ( isDefault ) {
|
||||
context.getMetadataCollector().addDefaultQuery( queryMapping );
|
||||
}
|
||||
|
@ -105,8 +107,8 @@ public abstract class QueryBinder {
|
|||
|
||||
private static <T> NamedHqlQueryDefinitionImpl<T> createNamedQueryDefinition(
|
||||
String queryName, String queryString, Class<T> resultClass, LockOptions lockOptions,
|
||||
QueryHintDefinition hints) {
|
||||
return new NamedHqlQueryDefinitionImpl.Builder<T>(queryName)
|
||||
QueryHintDefinition hints, AnnotationTarget annotationTarget) {
|
||||
return new NamedHqlQueryDefinitionImpl.Builder<T>(queryName, annotationTarget)
|
||||
.setHqlString(queryString)
|
||||
.setResultClass(resultClass)
|
||||
.setCacheable(hints.getCacheability())
|
||||
|
@ -124,6 +126,7 @@ public abstract class QueryBinder {
|
|||
public static void bindNativeQuery(
|
||||
NamedNativeQuery namedNativeQuery,
|
||||
MetadataBuildingContext context,
|
||||
AnnotationTarget location,
|
||||
boolean isDefault) {
|
||||
if ( namedNativeQuery == null ) {
|
||||
return;
|
||||
|
@ -143,7 +146,7 @@ public abstract class QueryBinder {
|
|||
final Class<?> resultClass = void.class == resultClassDetails ? null : resultClassDetails;
|
||||
|
||||
final NamedNativeQueryDefinition<?> queryDefinition =
|
||||
createNamedQueryDefinition( registrationName, queryString, resultClass, resultSetMappingName, hints );
|
||||
createNamedQueryDefinition( registrationName, queryString, resultClass, resultSetMappingName, hints, location );
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Binding named native query: %s => %s",
|
||||
|
@ -161,8 +164,9 @@ public abstract class QueryBinder {
|
|||
private static <T> NamedNativeQueryDefinition<T> createNamedQueryDefinition(
|
||||
String registrationName, String queryString,
|
||||
Class<T> resultClass, String resultSetMappingName,
|
||||
QueryHintDefinition hints) {
|
||||
return new NamedNativeQueryDefinition.Builder<T>(registrationName)
|
||||
QueryHintDefinition hints,
|
||||
AnnotationTarget location) {
|
||||
return new NamedNativeQueryDefinition.Builder<T>(registrationName, location)
|
||||
.setSqlString(queryString)
|
||||
.setResultClass(resultClass)
|
||||
.setResultSetMappingName(resultSetMappingName)
|
||||
|
@ -184,7 +188,8 @@ public abstract class QueryBinder {
|
|||
SQLSelect sqlSelect,
|
||||
ClassDetails annotatedClass,
|
||||
MetadataBuildingContext context) {
|
||||
final NamedNativeQueryDefinition.Builder<?> builder = new NamedNativeQueryDefinition.Builder<>( name )
|
||||
final NamedNativeQueryDefinition.Builder<?> builder =
|
||||
new NamedNativeQueryDefinition.Builder<>( name )
|
||||
.setFlushMode( FlushMode.MANUAL )
|
||||
.setSqlString( sqlSelect.sql() )
|
||||
.setQuerySpaces( setOf( sqlSelect.querySpaces() ) );
|
||||
|
@ -210,7 +215,8 @@ public abstract class QueryBinder {
|
|||
|
||||
public static void bindNativeQuery(
|
||||
org.hibernate.annotations.NamedNativeQuery namedNativeQuery,
|
||||
MetadataBuildingContext context) {
|
||||
MetadataBuildingContext context,
|
||||
AnnotationTarget location) {
|
||||
if ( namedNativeQuery == null ) {
|
||||
return;
|
||||
}
|
||||
|
@ -231,7 +237,7 @@ public abstract class QueryBinder {
|
|||
|
||||
final NamedNativeQueryDefinition.Builder<?> builder =
|
||||
createQueryDefinition( namedNativeQuery, registrationName, resultSetMappingName, resultClass,
|
||||
namedNativeQuery.timeout(), namedNativeQuery.fetchSize(), querySpaces );
|
||||
namedNativeQuery.timeout(), namedNativeQuery.fetchSize(), querySpaces, location );
|
||||
|
||||
if ( TRUE == namedNativeQuery.callable() ) {
|
||||
final NamedProcedureCallDefinition definition =
|
||||
|
@ -261,8 +267,9 @@ public abstract class QueryBinder {
|
|||
String registrationName, String resultSetMappingName,
|
||||
Class<T> resultClass,
|
||||
int timeout, int fetchSize,
|
||||
HashSet<String> querySpaces) {
|
||||
return new NamedNativeQueryDefinition.Builder<T>(registrationName)
|
||||
HashSet<String> querySpaces,
|
||||
AnnotationTarget location) {
|
||||
return new NamedNativeQueryDefinition.Builder<T>(registrationName, location)
|
||||
.setSqlString(namedNativeQuery.query())
|
||||
.setResultSetMappingName(resultSetMappingName)
|
||||
.setResultClass(resultClass)
|
||||
|
@ -365,17 +372,18 @@ public abstract class QueryBinder {
|
|||
String name,
|
||||
HQLSelect hqlSelect,
|
||||
MetadataBuildingContext context) {
|
||||
final NamedHqlQueryDefinition<?> hqlQueryDefinition = new NamedHqlQueryDefinition.Builder<>( name )
|
||||
final NamedHqlQueryDefinition<?> hqlQueryDefinition =
|
||||
new NamedHqlQueryDefinition.Builder<>( name )
|
||||
.setFlushMode( FlushMode.MANUAL )
|
||||
.setHqlString( hqlSelect.query() )
|
||||
.build();
|
||||
|
||||
context.getMetadataCollector().addNamedQuery( hqlQueryDefinition );
|
||||
}
|
||||
|
||||
public static void bindQuery(
|
||||
org.hibernate.annotations.NamedQuery namedQuery,
|
||||
MetadataBuildingContext context) {
|
||||
MetadataBuildingContext context,
|
||||
AnnotationTarget location) {
|
||||
if ( namedQuery == null ) {
|
||||
return;
|
||||
}
|
||||
|
@ -389,7 +397,7 @@ public abstract class QueryBinder {
|
|||
|
||||
final NamedHqlQueryDefinition.Builder<?> builder =
|
||||
createQueryDefinition( namedQuery, registrationName, resultClass,
|
||||
namedQuery.timeout(), namedQuery.fetchSize() ) ;
|
||||
namedQuery.timeout(), namedQuery.fetchSize(), location ) ;
|
||||
|
||||
final NamedHqlQueryDefinitionImpl<?> hqlQueryDefinition = builder.build();
|
||||
|
||||
|
@ -403,8 +411,9 @@ public abstract class QueryBinder {
|
|||
|
||||
private static <T> NamedHqlQueryDefinition.Builder<T> createQueryDefinition(
|
||||
org.hibernate.annotations.NamedQuery namedQuery,
|
||||
String registrationName, Class<T> resultClass, int timeout, int fetchSize) {
|
||||
return new NamedHqlQueryDefinition.Builder<T>(registrationName)
|
||||
String registrationName, Class<T> resultClass, int timeout, int fetchSize,
|
||||
AnnotationTarget location) {
|
||||
return new NamedHqlQueryDefinition.Builder<T>(registrationName, location)
|
||||
.setHqlString(namedQuery.query())
|
||||
.setResultClass(resultClass)
|
||||
.setCacheable(namedQuery.cacheable())
|
||||
|
|
|
@ -47,7 +47,8 @@ public class NamedQueryBinder {
|
|||
String prefix) {
|
||||
final String registrationName = prefix + namedQueryBinding.getName();
|
||||
|
||||
final NamedHqlQueryDefinition.Builder<?> queryBuilder = new NamedHqlQueryDefinition.Builder<>( registrationName )
|
||||
final NamedHqlQueryDefinition.Builder<?> queryBuilder =
|
||||
new NamedHqlQueryDefinition.Builder<>( registrationName )
|
||||
.setComment( namedQueryBinding.getComment() )
|
||||
.setCacheable( namedQueryBinding.isCacheable() )
|
||||
.setCacheMode( namedQueryBinding.getCacheMode() )
|
||||
|
@ -109,7 +110,8 @@ public class NamedQueryBinder {
|
|||
|
||||
final String registrationName = prefix + namedQueryBinding.getName();
|
||||
|
||||
final NamedNativeQueryDefinition.Builder<?> builder = new NamedNativeQueryDefinition.Builder<>( registrationName )
|
||||
final NamedNativeQueryDefinition.Builder<?> builder =
|
||||
new NamedNativeQueryDefinition.Builder<>( registrationName )
|
||||
.setComment( namedQueryBinding.getComment() )
|
||||
.setCacheable( namedQueryBinding.isCacheable() )
|
||||
.setCacheMode( namedQueryBinding.getCacheMode() )
|
||||
|
@ -222,12 +224,10 @@ public class NamedQueryBinder {
|
|||
);
|
||||
}
|
||||
|
||||
if ( content instanceof JaxbHbmQueryParamType ) {
|
||||
final JaxbHbmQueryParamType paramTypeBinding = (JaxbHbmQueryParamType) content;
|
||||
if ( content instanceof JaxbHbmQueryParamType paramTypeBinding ) {
|
||||
queryBuilder.addParameterTypeHint( paramTypeBinding.getName(), paramTypeBinding.getType() );
|
||||
}
|
||||
else if ( content instanceof JaxbHbmSynchronizeType ) {
|
||||
final JaxbHbmSynchronizeType synchronizedSpace = (JaxbHbmSynchronizeType) content;
|
||||
else if ( content instanceof JaxbHbmSynchronizeType synchronizedSpace ) {
|
||||
queryBuilder.addSynchronizedQuerySpace( synchronizedSpace.getTable() );
|
||||
}
|
||||
else if ( content instanceof JaxbHbmNativeQueryScalarReturnType ) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.FlushMode;
|
|||
import org.hibernate.LockOptions;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.models.spi.AnnotationTarget;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -36,14 +37,21 @@ public abstract class AbstractNamedQueryBuilder<R, T extends AbstractNamedQueryB
|
|||
|
||||
private Map<String, Object> hints;
|
||||
|
||||
public AbstractNamedQueryBuilder(String name) {
|
||||
private final AnnotationTarget location;
|
||||
|
||||
public AbstractNamedQueryBuilder(String name, AnnotationTarget location) {
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
AnnotationTarget getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
protected abstract T getThis();
|
||||
|
||||
public T setResultClass(Class<R> resultClass) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.boot.internal.NamedHqlQueryDefinitionImpl;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.models.spi.AnnotationTarget;
|
||||
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
|
||||
|
||||
/**
|
||||
|
@ -35,8 +36,12 @@ public interface NamedHqlQueryDefinition<E> extends NamedQueryDefinition<E> {
|
|||
|
||||
private Map<String,String> parameterTypes;
|
||||
|
||||
public Builder(String name, AnnotationTarget location) {
|
||||
super( name, location );
|
||||
}
|
||||
|
||||
public Builder(String name) {
|
||||
super( name );
|
||||
super( name, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,7 +85,9 @@ public interface NamedHqlQueryDefinition<E> extends NamedQueryDefinition<E> {
|
|||
getFetchSize(),
|
||||
getComment(),
|
||||
parameterTypes,
|
||||
getHints()
|
||||
getHints(),
|
||||
//TODO: should this be location.asClassDetails().getClassName() ?
|
||||
getLocation() == null ? null : getLocation().getName()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.boot.internal.NamedNativeQueryDefinitionImpl;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.models.spi.AnnotationTarget;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
|
||||
/**
|
||||
|
@ -43,8 +44,12 @@ public interface NamedNativeQueryDefinition<E> extends NamedQueryDefinition<E> {
|
|||
private Integer firstResult;
|
||||
private Integer maxResults;
|
||||
|
||||
public Builder(String name, AnnotationTarget location) {
|
||||
super( name, location );
|
||||
}
|
||||
|
||||
public Builder(String name) {
|
||||
super( name );
|
||||
super( name, null );
|
||||
}
|
||||
|
||||
public Builder<E> setSqlString(String sqlString) {
|
||||
|
@ -79,7 +84,9 @@ public interface NamedNativeQueryDefinition<E> extends NamedQueryDefinition<E> {
|
|||
getComment(),
|
||||
firstResult,
|
||||
maxResults,
|
||||
getHints()
|
||||
getHints(),
|
||||
//TODO: should this be location.asClassDetails().getClassName() ?
|
||||
getLocation() == null ? null : getLocation().getName()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public interface NamedQueryDefinition<E> extends TypedQueryReference<E> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The name under which the query is to be registered
|
||||
* The name under which the query is to be registered.
|
||||
*/
|
||||
String getRegistrationName();
|
||||
|
||||
|
@ -36,7 +36,14 @@ public interface NamedQueryDefinition<E> extends TypedQueryReference<E> {
|
|||
Class<E> getResultType();
|
||||
|
||||
/**
|
||||
* Resolve the mapping definition into its run-time memento form
|
||||
* Resolve the mapping definition into its run-time memento form.
|
||||
*/
|
||||
NamedQueryMemento<E> resolve(SessionFactoryImplementor factory);
|
||||
|
||||
/**
|
||||
* The location at which the defining named query annotation occurs,
|
||||
* usually a class or package name. Null for named queries declared
|
||||
* in XML.
|
||||
*/
|
||||
@Nullable String getLocation();
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ public abstract class AbstractNamedQueryDefinition<R> implements NamedQueryDefin
|
|||
private final String comment;
|
||||
|
||||
private final Map<String,Object> hints;
|
||||
private final String location;
|
||||
|
||||
public AbstractNamedQueryDefinition(
|
||||
String name,
|
||||
|
@ -49,7 +50,8 @@ public abstract class AbstractNamedQueryDefinition<R> implements NamedQueryDefin
|
|||
Integer timeout,
|
||||
Integer fetchSize,
|
||||
String comment,
|
||||
Map<String,Object> hints) {
|
||||
Map<String,Object> hints,
|
||||
String location) {
|
||||
this.name = name;
|
||||
this.resultType = resultType;
|
||||
this.cacheable = cacheable;
|
||||
|
@ -62,6 +64,7 @@ public abstract class AbstractNamedQueryDefinition<R> implements NamedQueryDefin
|
|||
this.fetchSize = fetchSize;
|
||||
this.comment = comment;
|
||||
this.hints = hints == null ? new HashMap<>() : new HashMap<>( hints );
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,6 +72,11 @@ public abstract class AbstractNamedQueryDefinition<R> implements NamedQueryDefin
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Class<R> getResultType() {
|
||||
return resultType;
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
||||
import org.hibernate.boot.query.NamedQueryDefinition;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static java.lang.Character.charCount;
|
||||
|
||||
public class InjectionHelper {
|
||||
private static final CoreMessageLogger log = CoreLogging.messageLogger( MetadataContext.class );
|
||||
|
||||
public static void injectEntityGraph(
|
||||
NamedEntityGraphDefinition definition,
|
||||
Class<?> metamodelClass,
|
||||
JpaMetamodel jpaMetamodel) {
|
||||
if ( metamodelClass != null ) {
|
||||
try {
|
||||
injectField(
|
||||
metamodelClass,
|
||||
'_' + javaIdentifier( definition.getRegisteredName() ),
|
||||
jpaMetamodel.findEntityGraphByName( definition.getRegisteredName() ),
|
||||
false
|
||||
);
|
||||
}
|
||||
catch ( NoSuchFieldException e ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void injectTypedQueryReference(NamedQueryDefinition<?> definition, Class<?> metamodelClass) {
|
||||
if ( metamodelClass != null ) {
|
||||
try {
|
||||
injectField(
|
||||
metamodelClass,
|
||||
'_' + javaIdentifier( definition.getRegistrationName() ) + '_',
|
||||
definition,
|
||||
false
|
||||
);
|
||||
}
|
||||
catch ( NoSuchFieldException e ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String javaIdentifier(String name) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
int position = 0;
|
||||
while ( position < name.length() ) {
|
||||
final int codePoint = name.codePointAt( position );
|
||||
if ( Character.isJavaIdentifierPart(codePoint) ) {
|
||||
result.appendCodePoint( codePoint );
|
||||
}
|
||||
else {
|
||||
result.append('_');
|
||||
}
|
||||
position += charCount( codePoint );
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static void injectField(
|
||||
Class<?> metamodelClass, String name, Object model,
|
||||
boolean allowNonDeclaredFieldReference)
|
||||
throws NoSuchFieldException {
|
||||
final Field field = allowNonDeclaredFieldReference
|
||||
? metamodelClass.getField(name)
|
||||
: metamodelClass.getDeclaredField(name);
|
||||
try {
|
||||
// should be public anyway, but to be sure...
|
||||
ReflectHelper.ensureAccessibility( field );
|
||||
field.set( null, model);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// todo : exception type?
|
||||
throw new AssertionFailure(
|
||||
"Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name,
|
||||
e
|
||||
);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// most likely a mismatch in the type we are injecting and the defined field; this represents a
|
||||
// mismatch in how the annotation processor interpreted the attribute and how our metamodel
|
||||
// and/or annotation binder did.
|
||||
|
||||
// This is particularly the case as arrays are not handled properly by the StaticMetamodel generator
|
||||
|
||||
// throw new AssertionFailure(
|
||||
// "Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name
|
||||
// + "; expected type : " + attribute.getClass().getName()
|
||||
// + "; encountered type : " + field.getType().getName()
|
||||
// );
|
||||
log.illegalArgumentOnStaticMetamodelFieldInjection(
|
||||
metamodelClass.getName(),
|
||||
name,
|
||||
model.getClass().getName(),
|
||||
field.getType().getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -4,25 +4,18 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.internal;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import jakarta.persistence.metamodel.Attribute;
|
||||
import jakarta.persistence.metamodel.IdentifiableType;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import jakarta.persistence.metamodel.Type;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.query.NamedQueryDefinition;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
|
@ -53,13 +46,16 @@ import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
|
|||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.metamodel.Attribute;
|
||||
import jakarta.persistence.metamodel.IdentifiableType;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import jakarta.persistence.metamodel.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static java.lang.Character.charCount;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static org.hibernate.metamodel.internal.InjectionHelper.injectField;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -278,8 +274,9 @@ public class MetadataContext {
|
|||
attribute = factoryFunction.apply( entityType, genericProperty );
|
||||
if ( !property.isGeneric() ) {
|
||||
final PersistentAttribute<X, ?> concreteAttribute = factoryFunction.apply( entityType, property );
|
||||
//noinspection unchecked
|
||||
( (AttributeContainer<X>) entityType ).getInFlightAccess().addConcreteGenericAttribute( concreteAttribute );
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<X> attributeContainer = (AttributeContainer<X>) entityType;
|
||||
attributeContainer.getInFlightAccess().addConcreteGenericAttribute( concreteAttribute );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -324,18 +321,7 @@ public class MetadataContext {
|
|||
// skip the version property, it was already handled previously.
|
||||
continue;
|
||||
}
|
||||
final PersistentAttribute<Object, ?> attribute = buildAttribute(
|
||||
property,
|
||||
jpaMapping,
|
||||
attributeFactory::buildAttribute
|
||||
);
|
||||
if ( attribute != null ) {
|
||||
addAttribute( jpaMapping, attribute );
|
||||
if ( property.isNaturalIdentifier() ) {
|
||||
( ( AttributeContainer<Object>) jpaMapping ).getInFlightAccess()
|
||||
.applyNaturalIdAttribute( attribute );
|
||||
}
|
||||
}
|
||||
buildAttribute( property, jpaMapping );
|
||||
}
|
||||
|
||||
( (AttributeContainer<?>) jpaMapping ).getInFlightAccess().finishUp();
|
||||
|
@ -364,21 +350,10 @@ public class MetadataContext {
|
|||
// applyNaturalIdAttribute( safeMapping, jpaType );
|
||||
|
||||
for ( Property property : safeMapping.getDeclaredProperties() ) {
|
||||
if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) {
|
||||
if ( !safeMapping.isVersioned()
|
||||
// skip the version property, it was already handled previously.
|
||||
continue;
|
||||
}
|
||||
final PersistentAttribute<Object, ?> attribute = buildAttribute(
|
||||
property,
|
||||
jpaType,
|
||||
attributeFactory::buildAttribute
|
||||
);
|
||||
if ( attribute != null ) {
|
||||
addAttribute( jpaType, attribute );
|
||||
if ( property.isNaturalIdentifier() ) {
|
||||
( ( AttributeContainer<Object>) jpaType ).getInFlightAccess()
|
||||
.applyNaturalIdAttribute( attribute );
|
||||
}
|
||||
|| property != safeMapping.getVersion() ) {
|
||||
buildAttribute( property, jpaType );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,22 +386,9 @@ public class MetadataContext {
|
|||
for ( EmbeddableDomainType<?> embeddable : processingEmbeddables ) {
|
||||
final Component component = componentByEmbeddable.get( embeddable );
|
||||
for ( Property property : component.getProperties() ) {
|
||||
if ( component.isPolymorphic() && !embeddable.getTypeName().equals( component.getPropertyDeclaringClass( property ) ) ) {
|
||||
continue;
|
||||
}
|
||||
final PersistentAttribute<Object, ?> attribute =
|
||||
attributeFactory.buildAttribute( (ManagedDomainType<Object>) embeddable, property );
|
||||
if ( attribute != null ) {
|
||||
final Property superclassProperty = getMappedSuperclassProperty(
|
||||
property.getName(),
|
||||
component.getMappedSuperclass()
|
||||
);
|
||||
if ( superclassProperty != null && superclassProperty.isGeneric() ) {
|
||||
( (AttributeContainer<Object>) embeddable ).getInFlightAccess().addConcreteGenericAttribute( attribute );
|
||||
}
|
||||
else {
|
||||
addAttribute( embeddable, attribute );
|
||||
}
|
||||
if ( !component.isPolymorphic()
|
||||
|| embeddable.getTypeName().equals( component.getPropertyDeclaringClass( property ) ) ) {
|
||||
addAttribute( embeddable, property, component );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,20 +406,52 @@ public class MetadataContext {
|
|||
}
|
||||
}
|
||||
|
||||
private void addAttribute(ManagedDomainType<?> type, PersistentAttribute<Object, ?> attribute) {
|
||||
//noinspection unchecked
|
||||
AttributeContainer<Object> container = (AttributeContainer<Object>) type;
|
||||
final AttributeContainer.InFlightAccess<Object> inFlightAccess = container.getInFlightAccess();
|
||||
private <T> void addAttribute(EmbeddableDomainType<T> embeddable, Property property, Component component) {
|
||||
final PersistentAttribute<T, ?> attribute =
|
||||
attributeFactory.buildAttribute( embeddable, property);
|
||||
if ( attribute != null ) {
|
||||
final Property superclassProperty = getMappedSuperclassProperty(
|
||||
property.getName(),
|
||||
component.getMappedSuperclass()
|
||||
);
|
||||
if ( superclassProperty != null && superclassProperty.isGeneric() ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<T> attributeContainer = (AttributeContainer<T>) embeddable;
|
||||
attributeContainer.getInFlightAccess().addConcreteGenericAttribute( attribute );
|
||||
}
|
||||
else {
|
||||
addAttribute(embeddable, attribute );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void buildAttribute(Property property, IdentifiableDomainType<T> jpaType) {
|
||||
final PersistentAttribute<T, ?> attribute =
|
||||
buildAttribute( property, jpaType, attributeFactory::buildAttribute );
|
||||
if ( attribute != null ) {
|
||||
addAttribute(jpaType, attribute );
|
||||
if ( property.isNaturalIdentifier() ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<T> attributeContainer = (AttributeContainer<T>) jpaType;
|
||||
attributeContainer.getInFlightAccess().applyNaturalIdAttribute( attribute );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void addAttribute(ManagedDomainType<T> type, PersistentAttribute<T, ?> attribute) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<T> container = (AttributeContainer<T>) type;
|
||||
final AttributeContainer.InFlightAccess<T> inFlightAccess = container.getInFlightAccess();
|
||||
final boolean virtual = attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED
|
||||
&& attribute.getAttributeJavaType() instanceof EntityJavaType<?>;
|
||||
if ( virtual ) {
|
||||
final EmbeddableDomainType<?> embeddableDomainType = (EmbeddableDomainType<?>) attribute.getValueGraphType();
|
||||
@SuppressWarnings("unchecked")
|
||||
final EmbeddableDomainType<T> embeddableDomainType =
|
||||
(EmbeddableDomainType<T>) attribute.getValueGraphType();
|
||||
final Component component = componentByEmbeddable.get( embeddableDomainType );
|
||||
for ( Property property : component.getProperties() ) {
|
||||
//noinspection unchecked
|
||||
ManagedDomainType<Object> managedDomainType = (ManagedDomainType<Object>) embeddableDomainType;
|
||||
final PersistentAttribute<Object, ?> subAttribute =
|
||||
attributeFactory.buildAttribute( managedDomainType, property );
|
||||
final PersistentAttribute<T, ?> subAttribute =
|
||||
attributeFactory.buildAttribute( embeddableDomainType, property );
|
||||
if ( subAttribute != null ) {
|
||||
inFlightAccess.addAttribute( subAttribute );
|
||||
}
|
||||
|
@ -473,43 +467,41 @@ public class MetadataContext {
|
|||
// 2) register the part (mapping role)
|
||||
// 3) somehow get the mapping role "into" the part (setter, ?)
|
||||
|
||||
private void applyIdMetadata(PersistentClass persistentClass, IdentifiableDomainType<?> identifiableType) {
|
||||
private <T> void applyIdMetadata(PersistentClass persistentClass, IdentifiableDomainType<T> identifiableType) {
|
||||
if ( persistentClass.hasIdentifierProperty() ) {
|
||||
final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
|
||||
//noinspection rawtypes
|
||||
final AttributeContainer attributeContainer = (AttributeContainer) identifiableType;
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<T> attributeContainer = (AttributeContainer<T>) identifiableType;
|
||||
if ( declaredIdentifierProperty != null ) {
|
||||
//noinspection unchecked
|
||||
final SingularPersistentAttribute<?, Object> idAttribute = (SingularPersistentAttribute<?, Object>) buildAttribute(
|
||||
final SingularPersistentAttribute<T, ?> idAttribute =
|
||||
(SingularPersistentAttribute<T, ?>)
|
||||
buildAttribute(
|
||||
declaredIdentifierProperty,
|
||||
identifiableType,
|
||||
attributeFactory::buildIdAttribute
|
||||
);
|
||||
//noinspection unchecked
|
||||
attributeContainer.getInFlightAccess().applyIdAttribute( idAttribute );
|
||||
}
|
||||
else {
|
||||
final Property superclassIdentifier = getMappedSuperclassIdentifier( persistentClass );
|
||||
if ( superclassIdentifier != null && superclassIdentifier.isGeneric() ) {
|
||||
// If the superclass identifier is generic we have to build the attribute to register the concrete type
|
||||
final SingularPersistentAttribute<?, Object> concreteIdentifier = attributeFactory.buildIdAttribute(
|
||||
final SingularPersistentAttribute<T, ?> concreteIdentifier =
|
||||
attributeFactory.buildIdAttribute(
|
||||
identifiableType,
|
||||
persistentClass.getIdentifierProperty()
|
||||
);
|
||||
//noinspection unchecked
|
||||
attributeContainer.getInFlightAccess().addConcreteGenericAttribute( concreteIdentifier );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we have a non-aggregated composite-id
|
||||
|
||||
if ( !(persistentClass.getIdentifier() instanceof Component) ) {
|
||||
if ( !( persistentClass.getIdentifier() instanceof Component compositeId ) ) {
|
||||
throw new MappingException( "Expecting Component for id mapping with no id-attribute" );
|
||||
}
|
||||
|
||||
// Handle the actual id-attributes
|
||||
final Component cidValue = (Component) persistentClass.getIdentifier();
|
||||
final List<Property> cidProperties;
|
||||
final int propertySpan;
|
||||
final EmbeddableTypeImpl<?> idClassType;
|
||||
|
@ -520,33 +512,39 @@ public class MetadataContext {
|
|||
idClassType = applyIdClassMetadata( (Component) persistentClass.getIdentifier() );
|
||||
}
|
||||
else {
|
||||
cidProperties = cidValue.getProperties();
|
||||
propertySpan = cidValue.getPropertySpan();
|
||||
cidProperties = compositeId.getProperties();
|
||||
propertySpan = compositeId.getPropertySpan();
|
||||
idClassType = null;
|
||||
}
|
||||
|
||||
assert cidValue.isEmbedded();
|
||||
assert compositeId.isEmbedded();
|
||||
|
||||
AbstractIdentifiableType<?> idType = (AbstractIdentifiableType<?>)
|
||||
identifiableTypesByName.get( cidValue.getOwner().getEntityName() );
|
||||
//noinspection rawtypes
|
||||
Set idAttributes = idType.getIdClassAttributesSafely();
|
||||
final IdentifiableDomainType<?> idDomainType =
|
||||
identifiableTypesByName.get( compositeId.getOwner().getEntityName() );
|
||||
@SuppressWarnings("unchecked")
|
||||
final AbstractIdentifiableType<T> idType = (AbstractIdentifiableType<T>) idDomainType;
|
||||
applyIdAttributes( identifiableType, idType, propertySpan, cidProperties, idClassType );
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void applyIdAttributes(
|
||||
IdentifiableDomainType<T> identifiableType,
|
||||
AbstractIdentifiableType<T> idType,
|
||||
int propertySpan,
|
||||
List<Property> cidProperties,
|
||||
EmbeddableTypeImpl<?> idClassType) {
|
||||
Set<SingularPersistentAttribute<? super T, ?>> idAttributes = idType.getIdClassAttributesSafely();
|
||||
if ( idAttributes == null ) {
|
||||
idAttributes = new HashSet<>( propertySpan );
|
||||
for ( Property cidSubproperty : cidProperties ) {
|
||||
final SingularPersistentAttribute<?, Object> cidSubAttr =
|
||||
attributeFactory.buildIdAttribute( idType, cidSubproperty );
|
||||
//noinspection unchecked
|
||||
idAttributes.add( cidSubAttr );
|
||||
idAttributes.add( attributeFactory.buildIdAttribute( idType, cidSubproperty ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AttributeContainer<?> container = (AttributeContainer<?>) identifiableType;
|
||||
//noinspection unchecked
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<T> container = (AttributeContainer<T>) identifiableType;
|
||||
container.getInFlightAccess().applyNonAggregatedIdAttributes( idAttributes, idClassType);
|
||||
}
|
||||
}
|
||||
|
||||
private Property getMappedSuperclassIdentifier(PersistentClass persistentClass) {
|
||||
MappedSuperclass mappedSuperclass = getMappedSuperclass( persistentClass );
|
||||
|
@ -561,52 +559,48 @@ public class MetadataContext {
|
|||
}
|
||||
|
||||
private EmbeddableTypeImpl<?> applyIdClassMetadata(Component idClassComponent) {
|
||||
final JavaTypeRegistry registry = getTypeConfiguration()
|
||||
.getJavaTypeRegistry();
|
||||
final Class<?> componentClass = idClassComponent.getComponentClass();
|
||||
final JavaType<?> javaType = registry.resolveManagedTypeDescriptor( componentClass );
|
||||
|
||||
final EmbeddableTypeImpl<?> embeddableType = new EmbeddableTypeImpl<>(
|
||||
javaType,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
getJpaMetamodel()
|
||||
);
|
||||
final JavaType<?> javaType =
|
||||
getTypeConfiguration().getJavaTypeRegistry()
|
||||
.resolveManagedTypeDescriptor( idClassComponent.getComponentClass() );
|
||||
final EmbeddableTypeImpl<?> embeddableType =
|
||||
new EmbeddableTypeImpl<>( javaType, null, null, false, getJpaMetamodel() );
|
||||
registerEmbeddableType( embeddableType, idClassComponent );
|
||||
return embeddableType;
|
||||
}
|
||||
|
||||
private <X> void applyIdMetadata(MappedSuperclass mappingType, MappedSuperclassDomainType<X> jpaMappingType) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<X> attributeContainer = (AttributeContainer<X>) jpaMappingType;
|
||||
if ( mappingType.hasIdentifierProperty() ) {
|
||||
final Property declaredIdentifierProperty = mappingType.getDeclaredIdentifierProperty();
|
||||
if ( declaredIdentifierProperty != null ) {
|
||||
//noinspection unchecked
|
||||
final SingularPersistentAttribute<X, Object> attribute = (SingularPersistentAttribute<X, Object>) buildAttribute(
|
||||
final SingularPersistentAttribute<X, ?> attribute =
|
||||
(SingularPersistentAttribute<X, ?>)
|
||||
buildAttribute(
|
||||
declaredIdentifierProperty,
|
||||
jpaMappingType,
|
||||
attributeFactory::buildIdAttribute
|
||||
);
|
||||
//noinspection unchecked
|
||||
( (AttributeContainer<X>) jpaMappingType ).getInFlightAccess().applyIdAttribute( attribute );
|
||||
attributeContainer.getInFlightAccess().applyIdAttribute( attribute );
|
||||
}
|
||||
}
|
||||
//a MappedSuperclass can have no identifier if the id is set below in the hierarchy
|
||||
else if ( mappingType.getIdentifierMapper() != null ) {
|
||||
Set<SingularPersistentAttribute<? super X, ?>> attributes = buildIdClassAttributes(
|
||||
final Set<SingularPersistentAttribute<? super X, ?>> attributes =
|
||||
buildIdClassAttributes(
|
||||
jpaMappingType,
|
||||
mappingType.getIdentifierMapper().getProperties()
|
||||
);
|
||||
//noinspection unchecked
|
||||
( ( AttributeContainer<X>) jpaMappingType ).getInFlightAccess().applyIdClassAttributes( attributes );
|
||||
attributeContainer.getInFlightAccess().applyIdClassAttributes( attributes );
|
||||
}
|
||||
}
|
||||
|
||||
private <X> void applyVersionAttribute(PersistentClass persistentClass, EntityDomainType<X> jpaEntityType) {
|
||||
final Property declaredVersion = persistentClass.getDeclaredVersion();
|
||||
if ( declaredVersion != null ) {
|
||||
//noinspection unchecked
|
||||
( ( AttributeContainer<X>) jpaEntityType ).getInFlightAccess().applyVersionAttribute(
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<X> attributeContainer = (AttributeContainer<X>) jpaEntityType;
|
||||
attributeContainer.getInFlightAccess().applyVersionAttribute(
|
||||
attributeFactory.buildVersionAttribute( jpaEntityType, declaredVersion )
|
||||
);
|
||||
}
|
||||
|
@ -615,8 +609,9 @@ public class MetadataContext {
|
|||
private <X> void applyVersionAttribute(MappedSuperclass mappingType, MappedSuperclassDomainType<X> jpaMappingType) {
|
||||
final Property declaredVersion = mappingType.getDeclaredVersion();
|
||||
if ( declaredVersion != null ) {
|
||||
//noinspection unchecked
|
||||
( ( AttributeContainer<X>) jpaMappingType ).getInFlightAccess().applyVersionAttribute(
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<X> xAttributeContainer = (AttributeContainer<X>) jpaMappingType;
|
||||
xAttributeContainer.getInFlightAccess().applyVersionAttribute(
|
||||
attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion )
|
||||
);
|
||||
}
|
||||
|
@ -629,8 +624,9 @@ public class MetadataContext {
|
|||
if ( superclassProperty.isGeneric() ) {
|
||||
final Property property = persistentClass.getProperty( superclassProperty.getName() );
|
||||
final PersistentAttribute<X, ?> attribute = attributeFactory.buildAttribute( entityType, property );
|
||||
//noinspection unchecked
|
||||
( (AttributeContainer<X>) entityType ).getInFlightAccess().addConcreteGenericAttribute( attribute );
|
||||
@SuppressWarnings("unchecked")
|
||||
final AttributeContainer<X> attributeContainer = (AttributeContainer<X>) entityType;
|
||||
attributeContainer.getInFlightAccess().addConcreteGenericAttribute( attribute );
|
||||
}
|
||||
}
|
||||
mappedSuperclass = getMappedSuperclass( mappedSuperclass );
|
||||
|
@ -695,13 +691,9 @@ public class MetadataContext {
|
|||
|
||||
private <X> void populateStaticMetamodel(ManagedDomainType<X> managedType, Set<String> processedMetamodelClassName) {
|
||||
final Class<X> managedTypeClass = managedType.getJavaType();
|
||||
if ( managedTypeClass == null ) {
|
||||
// should indicate MAP entity mode, skip...
|
||||
return;
|
||||
}
|
||||
final String metamodelClassName = managedTypeClass.getName() + '_';
|
||||
if ( processedMetamodelClassName.add( metamodelClassName ) ) {
|
||||
final Class<?> metamodelClass = metamodelClass( metamodelClassName );
|
||||
if ( managedTypeClass != null // can be null for MAP entity mode, so skip...
|
||||
&& processedMetamodelClassName.add( metamodelClassName( managedType ) ) ) {
|
||||
final Class<?> metamodelClass = metamodelClass( managedType );
|
||||
if ( metamodelClass != null ) {
|
||||
populateMetamodelClass( managedType, metamodelClass );
|
||||
}
|
||||
|
@ -718,13 +710,6 @@ public class MetadataContext {
|
|||
private <X> void populateMetamodelClass(ManagedDomainType<X> managedType, Class<?> metamodelClass) {
|
||||
registerAttributes( metamodelClass, managedType );
|
||||
injectManagedType( managedType, metamodelClass );
|
||||
runtimeModelCreationContext.getBootModel()
|
||||
.visitNamedHqlQueryDefinitions( definition
|
||||
-> injectTypedQueryReference( definition, metamodelClass) );
|
||||
runtimeModelCreationContext.getBootModel()
|
||||
.visitNamedNativeQueryDefinitions( definition
|
||||
-> injectTypedQueryReference( definition, metamodelClass) );
|
||||
//TODO: named entity graphs
|
||||
}
|
||||
|
||||
private static <X> void injectManagedType(ManagedDomainType<X> managedType, Class<?> metamodelClass) {
|
||||
|
@ -736,7 +721,16 @@ public class MetadataContext {
|
|||
}
|
||||
}
|
||||
|
||||
private Class<?> metamodelClass(String metamodelClassName) {
|
||||
private static String metamodelClassName(ManagedDomainType<?> managedTypeClass) {
|
||||
return managedTypeClass.getJavaType().getName() + '_';
|
||||
}
|
||||
|
||||
public Class<?> metamodelClass(ManagedDomainType<?> managedDomainType) {
|
||||
if ( managedDomainType == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
final String metamodelClassName = metamodelClassName( managedDomainType );
|
||||
try {
|
||||
return classLoaderService.classForName( metamodelClassName );
|
||||
}
|
||||
|
@ -744,35 +738,6 @@ public class MetadataContext {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void injectTypedQueryReference(NamedQueryDefinition<?> definition, Class<?> metamodelClass) {
|
||||
try {
|
||||
injectField(
|
||||
metamodelClass,
|
||||
'_' + javaIdentifier( definition.getRegistrationName() ) + '_',
|
||||
definition,
|
||||
false
|
||||
);
|
||||
}
|
||||
catch ( NoSuchFieldException e ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
public static String javaIdentifier(String name) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
int position = 0;
|
||||
while ( position < name.length() ) {
|
||||
final int codePoint = name.codePointAt( position );
|
||||
if ( Character.isJavaIdentifierPart(codePoint) ) {
|
||||
result.appendCodePoint( codePoint );
|
||||
}
|
||||
else {
|
||||
result.append('_');
|
||||
}
|
||||
position += charCount( codePoint );
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private <X> void registerAttributes(Class<?> metamodelClass, ManagedDomainType<X> managedType) {
|
||||
|
@ -826,45 +791,6 @@ public class MetadataContext {
|
|||
}
|
||||
}
|
||||
|
||||
private static void injectField(
|
||||
Class<?> metamodelClass, String name, Object model,
|
||||
boolean allowNonDeclaredFieldReference)
|
||||
throws NoSuchFieldException {
|
||||
final Field field = allowNonDeclaredFieldReference
|
||||
? metamodelClass.getField(name)
|
||||
: metamodelClass.getDeclaredField(name);
|
||||
try {
|
||||
// should be public anyway, but to be sure...
|
||||
ReflectHelper.ensureAccessibility( field );
|
||||
field.set( null, model);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// todo : exception type?
|
||||
throw new AssertionFailure(
|
||||
"Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name,
|
||||
e
|
||||
);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// most likely a mismatch in the type we are injecting and the defined field; this represents a
|
||||
// mismatch in how the annotation processor interpreted the attribute and how our metamodel
|
||||
// and/or annotation binder did.
|
||||
|
||||
// This is particularly the case as arrays are not handled properly by the StaticMetamodel generator
|
||||
|
||||
// throw new AssertionFailure(
|
||||
// "Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name
|
||||
// + "; expected type : " + attribute.getClass().getName()
|
||||
// + "; encountered type : " + field.getType().getName()
|
||||
// );
|
||||
log.illegalArgumentOnStaticMetamodelFieldInjection(
|
||||
metamodelClass.getName(),
|
||||
name,
|
||||
model.getClass().getName(),
|
||||
field.getType().getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public MappedSuperclassDomainType<?> locateMappedSuperclassType(MappedSuperclass mappedSuperclass) {
|
||||
return mappedSuperclassByMappedSuperclassMapping.get( mappedSuperclass );
|
||||
|
@ -879,10 +805,8 @@ public class MetadataContext {
|
|||
stackOfPersistentClassesBeingProcessed.size() - 1
|
||||
);
|
||||
if ( stackTop != persistentClass ) {
|
||||
throw new AssertionFailure(
|
||||
"Inconsistent popping: "
|
||||
+ persistentClass.getEntityName() + " instead of " + stackTop.getEntityName()
|
||||
);
|
||||
throw new AssertionFailure( "Inconsistent popping: "
|
||||
+ persistentClass.getEntityName() + " instead of " + stackTop.getEntityName() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,20 +827,25 @@ public class MetadataContext {
|
|||
private final Map<Class<?>,BasicDomainType<?>> basicDomainTypeMap = new HashMap<>();
|
||||
|
||||
public <J> BasicDomainType<J> resolveBasicType(Class<J> javaType) {
|
||||
//noinspection unchecked
|
||||
return (BasicDomainType<J>) basicDomainTypeMap.computeIfAbsent(
|
||||
javaType,
|
||||
jt -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
final BasicDomainType<J> domainType = (BasicDomainType<J>) basicDomainTypeMap.get( javaType );
|
||||
if ( domainType == null ) {
|
||||
// we cannot use getTypeConfiguration().standardBasicTypeForJavaType(javaType)
|
||||
// because that doesn't return the right thing for primitive types
|
||||
final JavaTypeRegistry registry = getTypeConfiguration().getJavaTypeRegistry();
|
||||
JavaType<J> javaTypeDescriptor = registry.resolveDescriptor( javaType );
|
||||
JdbcType jdbcType = javaTypeDescriptor.getRecommendedJdbcType( typeConfiguration.getCurrentBaseSqlTypeIndicators() );
|
||||
return javaType.isPrimitive()
|
||||
final JavaType<J> javaTypeDescriptor =
|
||||
getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType );
|
||||
final JdbcType jdbcType =
|
||||
javaTypeDescriptor.getRecommendedJdbcType( typeConfiguration.getCurrentBaseSqlTypeIndicators() );
|
||||
final BasicDomainType<J> type =
|
||||
javaType.isPrimitive()
|
||||
? new PrimitiveBasicTypeImpl<>( javaTypeDescriptor, jdbcType, javaType )
|
||||
: new BasicTypeImpl<>( javaTypeDescriptor, jdbcType );
|
||||
basicDomainTypeMap.put( javaType, type );
|
||||
return type;
|
||||
}
|
||||
else {
|
||||
return domainType;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public <J> EmbeddableDomainType<J> locateEmbeddable(Class<J> embeddableClass, Component component) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
||||
import org.hibernate.boot.query.NamedQueryDefinition;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
|
@ -32,7 +33,6 @@ import org.hibernate.graph.spi.RootGraphImplementor;
|
|||
import org.hibernate.graph.spi.SubGraphImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.jpa.spi.JpaCompliance;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
@ -68,6 +68,9 @@ import jakarta.persistence.metamodel.ManagedType;
|
|||
import jakarta.persistence.metamodel.Type;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||
import static org.hibernate.metamodel.internal.InjectionHelper.injectEntityGraph;
|
||||
import static org.hibernate.metamodel.internal.InjectionHelper.injectTypedQueryReference;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -77,10 +80,10 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
private static final CoreMessageLogger log = CoreLogging.messageLogger( JpaMetamodel.class );
|
||||
|
||||
private static class ImportInfo<T> {
|
||||
final String importedName;
|
||||
Class<T> loadedClass; // could be null for boot metamodel import; not final to allow for populating later
|
||||
private final String importedName;
|
||||
private Class<T> loadedClass; // could be null for boot metamodel import; not final to allow for populating later
|
||||
|
||||
ImportInfo(String importedName, Class<T> loadedClass) {
|
||||
private ImportInfo(String importedName, Class<T> loadedClass) {
|
||||
this.importedName = importedName;
|
||||
this.loadedClass = loadedClass;
|
||||
}
|
||||
|
@ -301,6 +304,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
}
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -429,7 +433,6 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void applyNamedEntityGraphs(Collection<NamedEntityGraphDefinition> namedEntityGraphs) {
|
||||
for ( NamedEntityGraphDefinition definition : namedEntityGraphs ) {
|
||||
log.debugf(
|
||||
|
@ -438,7 +441,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
definition.getEntityName(),
|
||||
definition.getJpaEntityName()
|
||||
);
|
||||
final EntityDomainType<Object> entityType = (EntityDomainType<Object>) entity( definition.getEntityName() );
|
||||
final EntityDomainType<?> entityType = entity( definition.getEntityName() );
|
||||
if ( entityType == null ) {
|
||||
throw new IllegalArgumentException(
|
||||
"Attempted to register named entity graph [" + definition.getRegisteredName()
|
||||
|
@ -446,47 +449,47 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
|
||||
);
|
||||
}
|
||||
|
||||
final RootGraphImpl<Object> entityGraph = new RootGraphImpl<>( definition.getRegisteredName(), entityType );
|
||||
|
||||
final NamedEntityGraph namedEntityGraph = definition.getAnnotation();
|
||||
|
||||
if ( namedEntityGraph.includeAllAttributes() ) {
|
||||
for ( Attribute<? super Object, ?> attribute : entityType.getAttributes() ) {
|
||||
entityGraph.addAttributeNodes( attribute );
|
||||
}
|
||||
}
|
||||
|
||||
final RootGraphImpl<?> entityGraph =
|
||||
createRootGraph( definition.getRegisteredName(), entityType,
|
||||
namedEntityGraph.includeAllAttributes() );
|
||||
if ( namedEntityGraph.attributeNodes() != null ) {
|
||||
applyNamedAttributeNodes( namedEntityGraph.attributeNodes(), namedEntityGraph, entityGraph );
|
||||
}
|
||||
|
||||
entityGraphMap.put( definition.getRegisteredName(), entityGraph );
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> RootGraphImpl<T> createRootGraph(
|
||||
String name, EntityDomainType<T> entityType, boolean includeAllAttributes) {
|
||||
final RootGraphImpl<T> entityGraph = new RootGraphImpl<>( name, entityType );
|
||||
if ( includeAllAttributes ) {
|
||||
for ( Attribute<? super T, ?> attribute : entityType.getAttributes() ) {
|
||||
entityGraph.addAttributeNodes( attribute );
|
||||
}
|
||||
}
|
||||
return entityGraph;
|
||||
}
|
||||
|
||||
private void applyNamedAttributeNodes(
|
||||
NamedAttributeNode[] namedAttributeNodes,
|
||||
NamedEntityGraph namedEntityGraph,
|
||||
GraphImplementor<?> graphNode) {
|
||||
for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) {
|
||||
final String value = namedAttributeNode.value();
|
||||
final AttributeNodeImplementor<?> attributeNode = graphNode.findOrCreateAttributeNode( value );
|
||||
if ( StringHelper.isNotEmpty( namedAttributeNode.subgraph() ) ) {
|
||||
final SubGraphImplementor<?> subgraph = attributeNode.makeSubGraph();
|
||||
final AttributeNodeImplementor<?> attributeNode =
|
||||
graphNode.findOrCreateAttributeNode( namedAttributeNode.value() );
|
||||
if ( isNotEmpty( namedAttributeNode.subgraph() ) ) {
|
||||
applyNamedSubgraphs(
|
||||
namedEntityGraph,
|
||||
namedAttributeNode.subgraph(),
|
||||
subgraph
|
||||
attributeNode.makeSubGraph()
|
||||
);
|
||||
}
|
||||
if ( StringHelper.isNotEmpty( namedAttributeNode.keySubgraph() ) ) {
|
||||
final SubGraphImplementor<?> subgraph = attributeNode.makeKeySubGraph();
|
||||
|
||||
if ( isNotEmpty( namedAttributeNode.keySubgraph() ) ) {
|
||||
applyNamedSubgraphs(
|
||||
namedEntityGraph,
|
||||
namedAttributeNode.keySubgraph(),
|
||||
subgraph
|
||||
attributeNode.makeKeySubGraph()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -646,8 +649,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
typeConfiguration.getJavaTypeRegistry().forEachDescriptor( descriptor -> {
|
||||
if ( descriptor instanceof EnumJavaType<? extends Enum<?>> enumJavaType ) {
|
||||
final Class<? extends Enum<?>> enumJavaClass = enumJavaType.getJavaTypeClass();
|
||||
final Enum<?>[] enumConstants = enumJavaClass.getEnumConstants();
|
||||
for ( Enum<?> enumConstant : enumConstants ) {
|
||||
for ( Enum<?> enumConstant : enumJavaClass.getEnumConstants() ) {
|
||||
addAllowedEnumLiteralsToEnumTypesMap(
|
||||
allowedEnumLiteralsToEnumTypeNames,
|
||||
enumConstant.name(),
|
||||
|
@ -662,6 +664,26 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
} );
|
||||
|
||||
applyNamedEntityGraphs( namedEntityGraphDefinitions );
|
||||
|
||||
populateStaticMetamodel( bootMetamodel, context );
|
||||
}
|
||||
|
||||
private void populateStaticMetamodel(MetadataImplementor bootMetamodel, MetadataContext context) {
|
||||
bootMetamodel.visitNamedHqlQueryDefinitions( definition
|
||||
-> injectTypedQueryReference( definition, namedQueryMetamodelClass( definition, context ) ) );
|
||||
bootMetamodel.visitNamedNativeQueryDefinitions( definition
|
||||
-> injectTypedQueryReference( definition, namedQueryMetamodelClass( definition, context ) ) );
|
||||
bootMetamodel.getNamedEntityGraphs().values().forEach(definition
|
||||
-> injectEntityGraph( definition, graphMetamodelClass( definition, context ), this ) );
|
||||
}
|
||||
|
||||
private Class<?> namedQueryMetamodelClass(NamedQueryDefinition<?> definition, MetadataContext context) {
|
||||
final String location = definition.getLocation();
|
||||
return location == null ? null : context.metamodelClass( managedTypeByName.get( location ) );
|
||||
}
|
||||
|
||||
private Class<?> graphMetamodelClass(NamedEntityGraphDefinition definition, MetadataContext context) {
|
||||
return context.metamodelClass( managedTypeByName.get( definition.getEntityName() ) );
|
||||
}
|
||||
|
||||
public static void addAllowedEnumLiteralsToEnumTypesMap(
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
@NamedQuery(name = "allMouse",
|
||||
query = "select m from ApplicationServer m") package org.hibernate.orm.test.jpa.pack.defaultpar;
|
||||
query = "select m from ApplicationServer m")
|
||||
package org.hibernate.orm.test.jpa.pack.defaultpar;
|
||||
import org.hibernate.annotations.NamedQuery;
|
||||
|
|
Loading…
Reference in New Issue