HHH-17460 - Ongoing JPA 32 work

This commit is contained in:
Steve Ebersole 2024-03-19 20:54:47 -05:00
parent 2cf379159b
commit 2d066d1ae5
11 changed files with 467 additions and 47 deletions

View File

@ -416,7 +416,7 @@ public class MapBinder extends CollectionBinder {
private AnnotationUsage<jakarta.persistence.ForeignKey> getMapKeyForeignKey(MemberDetails property) {
final AnnotationUsage<MapKeyJoinColumns> mapKeyJoinColumns = property.getAnnotationUsage( MapKeyJoinColumns.class );
final AnnotationUsage<MapKeyJoinColumn> mapKeyJoinColumn = property.getAnnotationUsage( MapKeyJoinColumn.class );
final AnnotationUsage<MapKeyJoinColumn> mapKeyJoinColumn = property.getSingleAnnotationUsage( MapKeyJoinColumn.class );
if ( mapKeyJoinColumns != null ) {
return mapKeyJoinColumns.getNestedUsage( "foreignKey" );
}

View File

@ -74,14 +74,11 @@ import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.AvailableHints;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.models.spi.AnnotationDescriptor;
import org.hibernate.models.spi.AnnotationDescriptorRegistry;
import org.hibernate.models.spi.AnnotationTarget;
import org.hibernate.models.spi.AnnotationUsage;
import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.ClassDetailsRegistry;
import org.hibernate.models.spi.MutableAnnotationUsage;
import org.hibernate.models.spi.SourceModelBuildingContext;
import org.hibernate.models.spi.SourceModelContext;
import jakarta.persistence.ColumnResult;
import jakarta.persistence.ConstructorResult;
@ -116,8 +113,7 @@ import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
* @author Steve Ebersole
*/
public class GlobalRegistrationsImpl implements GlobalRegistrations {
private final ClassDetailsRegistry classDetailsRegistry;
private final AnnotationDescriptorRegistry descriptorRegistry;
private final SourceModelBuildingContext sourceModelContext;
private List<JpaEventListener> jpaEventListeners;
private List<ConversionRegistration> converterRegistrations;
@ -141,13 +137,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
private Map<String, NamedNativeQueryRegistration> namedNativeQueryRegistrations;
private Map<String, NamedStoredProcedureQueryRegistration> namedStoredProcedureQueryRegistrations;
public GlobalRegistrationsImpl(SourceModelContext sourceModelContext) {
this( sourceModelContext.getClassDetailsRegistry(), sourceModelContext.getAnnotationDescriptorRegistry() );
}
public GlobalRegistrationsImpl(ClassDetailsRegistry classDetailsRegistry, AnnotationDescriptorRegistry descriptorRegistry) {
this.classDetailsRegistry = classDetailsRegistry;
this.descriptorRegistry = descriptorRegistry;
public GlobalRegistrationsImpl(SourceModelBuildingContext sourceModelContext) {
this.sourceModelContext = sourceModelContext;
}
@Override
@ -257,8 +248,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
}
registrations.forEach( (reg) -> collectJavaTypeRegistration(
classDetailsRegistry.resolveClassDetails( reg.getClazz() ),
classDetailsRegistry.resolveClassDetails( reg.getDescriptor() )
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getClazz() ),
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getDescriptor() )
) );
}
@ -291,7 +282,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
registrations.forEach( (reg) -> collectJdbcTypeRegistration(
reg.getCode(),
classDetailsRegistry.resolveClassDetails( reg.getDescriptor() )
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getDescriptor() )
) );
}
@ -324,12 +315,12 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
final ClassDetails explicitDomainType;
final String explicitDomainTypeName = registration.getClazz();
if ( StringHelper.isNotEmpty( explicitDomainTypeName ) ) {
explicitDomainType = classDetailsRegistry.resolveClassDetails( explicitDomainTypeName );
explicitDomainType = sourceModelContext.getClassDetailsRegistry().resolveClassDetails( explicitDomainTypeName );
}
else {
explicitDomainType = null;
}
final ClassDetails converterType = classDetailsRegistry.resolveClassDetails( registration.getConverter() );
final ClassDetails converterType = sourceModelContext.getClassDetailsRegistry().resolveClassDetails( registration.getConverter() );
final boolean autoApply = registration.isAutoApply();
collectConverterRegistration( new ConversionRegistration( explicitDomainType, converterType, autoApply, CONVERTER_REG ) );
} );
@ -359,8 +350,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
}
registrations.forEach( (reg) -> {
final ClassDetails domainTypeDetails = classDetailsRegistry.resolveClassDetails( reg.getClazz() );
final ClassDetails descriptorDetails = classDetailsRegistry.resolveClassDetails( reg.getDescriptor() );
final ClassDetails domainTypeDetails = sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getClazz() );
final ClassDetails descriptorDetails = sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getDescriptor() );
collectUserTypeRegistration( domainTypeDetails, descriptorDetails );
} );
}
@ -389,8 +380,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
}
registrations.forEach( (reg) -> collectCompositeUserTypeRegistration(
classDetailsRegistry.resolveClassDetails( reg.getClazz() ),
classDetailsRegistry.resolveClassDetails( reg.getDescriptor() )
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getClazz() ),
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getDescriptor() )
) );
}
@ -433,7 +424,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
registrations.forEach( (reg) -> collectCollectionTypeRegistration(
reg.getClassification(),
classDetailsRegistry.resolveClassDetails( reg.getDescriptor() ),
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getDescriptor() ),
extractParameterMap( reg.getParameters() )
) );
}
@ -475,8 +466,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
}
registrations.forEach( (reg) -> collectEmbeddableInstantiatorRegistration(
classDetailsRegistry.resolveClassDetails( reg.getEmbeddableClass() ),
classDetailsRegistry.resolveClassDetails( reg.getInstantiator() )
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getEmbeddableClass() ),
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( reg.getInstantiator() )
) );
}
@ -536,7 +527,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
// should resolve to Object - let's see how that reacts
final ClassDetails targetClassDetails = XmlAnnotationHelper.resolveJavaType(
parameter.getType(),
classDetailsRegistry
sourceModelContext.getClassDetailsRegistry()
);
result.put( parameter.getName(), targetClassDetails );
}
@ -592,7 +583,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
}
listeners.forEach( (jaxbEntityListener) -> {
final ClassDetails classDetails = classDetailsRegistry.resolveClassDetails( jaxbEntityListener.getClazz() );
final ClassDetails classDetails = sourceModelContext.getClassDetailsRegistry().resolveClassDetails( jaxbEntityListener.getClazz() );
final JpaEventListener listener = JpaEventListener.from(
JpaEventListenerStyle.LISTENER,
classDetails,
@ -653,7 +644,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
}
private <A extends Annotation> MutableAnnotationUsage<A> makeAnnotation(AnnotationDescriptor<A> annotationDescriptor) {
return annotationDescriptor.createUsage( null, null );
return annotationDescriptor.createUsage( null, sourceModelContext );
}
public void collectSequenceGenerator(AnnotationUsage<SequenceGenerator> usage) {
@ -766,7 +757,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
converters.forEach( (jaxbConverter) -> {
final String converterClassName = jaxbConverter.getClazz();
assert converterClassName != null;
final ClassDetails converterType = classDetailsRegistry.resolveClassDetails( converterClassName );
final ClassDetails converterType = sourceModelContext.getClassDetailsRegistry().resolveClassDetails( converterClassName );
final boolean autoApply = jaxbConverter.isAutoApply();
jpaConverters.add( new ConverterRegistration( converterType, autoApply ) );
@ -828,7 +819,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
final MutableAnnotationUsage<EntityResult> entityResultAnnotation = makeAnnotation( JpaAnnotations.ENTITY_RESULT );
entityResults.add( entityResultAnnotation );
applyAttributeIfSpecified( "entityClass", classDetailsRegistry.resolveClassDetails( jaxbEntityResult.getEntityClass() ), entityResultAnnotation );
applyAttributeIfSpecified( "entityClass", sourceModelContext.getClassDetailsRegistry().resolveClassDetails( jaxbEntityResult.getEntityClass() ), entityResultAnnotation );
applyAttributeIfSpecified( "lockMode", jaxbEntityResult.getLockMode(), entityResultAnnotation );
applyStringAttributeIfSpecified( "discriminatorColumn", jaxbEntityResult.getDiscriminatorColumn(), entityResultAnnotation );
@ -860,7 +851,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
result.setAttributeValue(
"entityClass",
classDetailsRegistry.resolveClassDetails( jaxbConstructorResult.getTargetClass() )
sourceModelContext.getClassDetailsRegistry().resolveClassDetails( jaxbConstructorResult.getTargetClass() )
);
if ( !jaxbConstructorResult.getColumns().isEmpty() ) {
@ -885,7 +876,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
columnResults.add( columnResultAnnotation );
columnResultAnnotation.setAttributeValue( "name", jaxbColumn.getName() );
applyAttributeIfSpecified( "type", classDetailsRegistry.resolveClassDetails( jaxbColumn.getClazz() ), columnResultAnnotation );
applyAttributeIfSpecified( "type", sourceModelContext.getClassDetailsRegistry().resolveClassDetails( jaxbColumn.getClazz() ), columnResultAnnotation );
}
annotationListConsumer.accept( columnResults );
}
@ -977,7 +968,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
queryAnnotation.setAttributeValue( "query", jaxbNamedQuery.getQuery() );
if ( StringHelper.isNotEmpty( jaxbNamedQuery.getResultClass() ) ) {
queryAnnotation.setAttributeValue( "resultClass", classDetailsRegistry.resolveClassDetails( jaxbNamedQuery.getResultClass() ) );
queryAnnotation.setAttributeValue( "resultClass", sourceModelContext.getClassDetailsRegistry().resolveClassDetails( jaxbNamedQuery.getResultClass() ) );
}
applyStringAttributeIfSpecified( "resultSetMapping", jaxbNamedQuery.getResultSetMapping(), queryAnnotation );
@ -1054,7 +1045,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
final ArrayList<ClassDetails> resultClasses = arrayList( jaxbQuery.getResultClasses().size() );
applyAttributeIfSpecified( "resultClasses", resultClasses, queryAnnotation );
for ( String resultClassName : jaxbQuery.getResultClasses() ) {
resultClasses.add( classDetailsRegistry.resolveClassDetails( resultClassName ) );
resultClasses.add( sourceModelContext.getClassDetailsRegistry().resolveClassDetails( resultClassName ) );
}
applyAttributeIfSpecified( "resultSetMappings", jaxbQuery.getResultSetMappings(), queryAnnotation );
@ -1069,7 +1060,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
applyStringAttributeIfSpecified( "name", jaxbProcedureParameter.getName(), parameterAnnotation );
applyAttributeIfSpecified( "mode", jaxbProcedureParameter.getMode(), parameterAnnotation );
applyAttributeIfSpecified( "type", classDetailsRegistry.resolveClassDetails( jaxbProcedureParameter.getClazz() ), parameterAnnotation );
applyAttributeIfSpecified( "type", sourceModelContext.getClassDetailsRegistry().resolveClassDetails( jaxbProcedureParameter.getClazz() ), parameterAnnotation );
}
}
}

View File

@ -3,7 +3,14 @@ package org.hibernate.boot.models.internal;
import java.lang.annotation.Annotation;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.models.spi.AnnotationDescriptor;
import org.hibernate.models.spi.AnnotationTarget;
import org.hibernate.models.spi.AnnotationUsage;
import org.hibernate.models.spi.MutableAnnotationUsage;
import org.hibernate.models.spi.MutableClassDetails;
import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.NamedQueries;
public class AnnotationUsageHelper {
@ -24,4 +31,31 @@ public class AnnotationUsageHelper {
annotationUsage.setAttributeValue( attributeName, value );
}
}
public static <A extends Annotation> MutableAnnotationUsage<A> getOrCreateUsage(
Class<A> annotationType,
AnnotationTarget target,
SourceModelBuildingContext modelBuildingContext) {
final MutableAnnotationUsage<A> existing = (MutableAnnotationUsage<A>) target.getAnnotationUsage( annotationType );
if ( existing != null ) {
return existing;
}
final AnnotationDescriptor<A> descriptor = modelBuildingContext
.getAnnotationDescriptorRegistry()
.getDescriptor( annotationType );
return descriptor.createUsage( target, modelBuildingContext );
}
public static <A extends Annotation> MutableAnnotationUsage<A> getOrCreateUsage(
AnnotationDescriptor<A> annotationDescriptor,
AnnotationTarget target,
SourceModelBuildingContext modelBuildingContext) {
final MutableAnnotationUsage<A> existing = (MutableAnnotationUsage<A>) target.getAnnotationUsage( annotationDescriptor );
if ( existing != null ) {
return existing;
}
return annotationDescriptor.createUsage( target, modelBuildingContext );
}
}

View File

@ -7,7 +7,7 @@
package org.hibernate.boot.models.xml;
/**
* Generally indicates a problem locating or table an XML resource
* Generally indicates a problem locating an XML resource
*
* @author Steve Ebersole
*/

View File

@ -69,6 +69,7 @@ import jakarta.persistence.MappedSuperclass;
import static org.hibernate.internal.util.NullnessHelper.coalesce;
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/**
* Helper for handling managed types defined in mapping XML, in either
@ -461,14 +462,14 @@ public class ManagedTypeProcessor {
XmlDocumentContext xmlDocumentContext) {
XmlAnnotationHelper.applyEntity( jaxbEntity, classDetails, xmlDocumentContext );
XmlAnnotationHelper.applyInheritance( jaxbEntity, classDetails, xmlDocumentContext );
classDetails.addAnnotationUsage( XmlAnnotationHelper.createAccessAnnotation( classAccessType, classDetails, xmlDocumentContext ) );
applyAccessAnnotation( classAccessType, classDetails, xmlDocumentContext );
applyCaching( jaxbEntity, classDetails, xmlDocumentContext );
if ( jaxbEntity.isAbstract() != null ) {
XmlProcessingHelper.makeAnnotation( Abstract.class, classDetails, xmlDocumentContext );
}
if ( StringHelper.isNotEmpty( jaxbEntity.getExtends() ) ) {
if ( isNotEmpty( jaxbEntity.getExtends() ) ) {
final MutableAnnotationUsage<Extends> extendsAnn = HibernateAnnotations.EXTENDS.createUsage(
classDetails,
xmlDocumentContext.getModelBuildingContext()
@ -505,6 +506,10 @@ public class ManagedTypeProcessor {
);
}
QueryProcessing.applyNamedQueries( jaxbEntity, classDetails, xmlDocumentContext );
QueryProcessing.applyNamedNativeQueries( jaxbEntity, classDetails, jaxbRoot, xmlDocumentContext );
QueryProcessing.applyNamedProcedureQueries( jaxbEntity, classDetails, xmlDocumentContext );
jaxbEntity.getFilters().forEach( jaxbFilter -> XmlAnnotationHelper.applyFilter(
jaxbFilter,
classDetails,
@ -548,6 +553,15 @@ public class ManagedTypeProcessor {
// todo : secondary-tables
}
private static void applyAccessAnnotation(
AccessType accessType,
MutableClassDetails target,
XmlDocumentContext xmlDocumentContext) {
final MutableAnnotationUsage<Access> annotationUsage = XmlProcessingHelper.makeAnnotation( Access.class, target, xmlDocumentContext );
annotationUsage.setAttributeValue( "value", accessType );
target.addAnnotationUsage( annotationUsage );
}
private static void applyCaching(
JaxbEntityImpl jaxbEntity,
MutableClassDetails classDetails,
@ -569,7 +583,7 @@ public class ManagedTypeProcessor {
classDetails.addAnnotationUsage( cacheableUsage );
XmlProcessingHelper.applyAttributeIfSpecified( "region", jaxbCaching.getRegion(), cacheableUsage );
XmlProcessingHelper.applyAttributeIfSpecified(
"access",
"usage",
convertCacheAccessType( jaxbCaching.getAccess() ),
cacheableUsage
);

View File

@ -0,0 +1,358 @@
/*
* 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.boot.models.xml.internal;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.CacheMode;
import org.hibernate.annotations.NamedNativeQueries;
import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
import org.hibernate.boot.jaxb.mapping.spi.JaxbColumnResultImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedNativeQueryImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedQueryBase;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedQueryImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbQueryHint;
import org.hibernate.boot.jaxb.mapping.spi.JaxbSynchronizedTableImpl;
import org.hibernate.boot.models.HibernateAnnotations;
import org.hibernate.boot.models.JpaAnnotations;
import org.hibernate.boot.models.internal.AnnotationUsageHelper;
import org.hibernate.boot.models.xml.spi.XmlDocumentContext;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.models.spi.AnnotationTarget;
import org.hibernate.models.spi.AnnotationUsage;
import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.MutableAnnotationUsage;
import org.hibernate.models.spi.MutableClassDetails;
import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.ColumnResult;
import jakarta.persistence.QueryHint;
import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/**
* @author Steve Ebersole
*/
public class QueryProcessing {
public static void applyNamedQueries(
JaxbEntityImpl jaxbEntity,
MutableClassDetails classDetails,
XmlDocumentContext xmlDocumentContext) {
if ( CollectionHelper.isEmpty( jaxbEntity.getNamedQueries() ) ) {
return;
}
final SourceModelBuildingContext modelBuildingContext = xmlDocumentContext.getModelBuildingContext();
List<MutableAnnotationUsage<NamedQuery>> namedHqlQueryList = null;
List<MutableAnnotationUsage<jakarta.persistence.NamedQuery>> namedJpqlQueryList = null;
for ( int i = 0; i < jaxbEntity.getNamedQueries().size(); i++ ) {
final JaxbNamedQueryImpl jaxbNamedQuery = jaxbEntity.getNamedQueries().get( i );
if ( CollectionHelper.isNotEmpty( jaxbNamedQuery.getHints() ) ) {
// treat this as a Jakarta Persistence named-query
if ( namedJpqlQueryList == null ) {
final MutableAnnotationUsage<jakarta.persistence.NamedQueries> namedJpqlQueriesUsage = AnnotationUsageHelper.getOrCreateUsage(
JpaAnnotations.NAMED_QUERIES,
classDetails,
modelBuildingContext
);
classDetails.addAnnotationUsage( namedJpqlQueriesUsage );
namedJpqlQueryList = new ArrayList<>();
namedJpqlQueriesUsage.setAttributeValue( "value", namedJpqlQueryList );
}
applyNamedJpqlQuery( jaxbNamedQuery, classDetails, namedJpqlQueryList, modelBuildingContext );
}
else {
// treat this as a named HQL query
if ( namedHqlQueryList == null ) {
final MutableAnnotationUsage<NamedQueries> namedHqlQueriesUsage = AnnotationUsageHelper.getOrCreateUsage(
HibernateAnnotations.NAMED_QUERIES,
classDetails,
modelBuildingContext
);
classDetails.addAnnotationUsage( namedHqlQueriesUsage );
namedHqlQueryList = new ArrayList<>();
namedHqlQueriesUsage.setAttributeValue( "value", namedHqlQueryList );
}
applyNamedHqlQuery( jaxbNamedQuery, classDetails, namedHqlQueryList, modelBuildingContext );
}
}
}
public static void applyNamedHqlQuery(
JaxbNamedQueryImpl jaxbNamedQuery,
MutableClassDetails classDetails,
List<MutableAnnotationUsage<NamedQuery>> namedQueryList,
SourceModelBuildingContext modelBuildingContext) {
final MutableAnnotationUsage<NamedQuery> namedQueryUsage = HibernateAnnotations.NAMED_QUERY.createUsage(
classDetails,
modelBuildingContext
);
namedQueryList.add( namedQueryUsage );
namedQueryUsage.setAttributeValue( "name", jaxbNamedQuery.getName() );
namedQueryUsage.setAttributeValue( "query", jaxbNamedQuery.getQuery() );
AnnotationUsageHelper.applyAttributeIfSpecified( "comment", jaxbNamedQuery.getComment(), namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "readOnly", jaxbNamedQuery.isReadOnly(), namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "flushMode", jaxbNamedQuery.getFlushMode(), namedQueryUsage );
if ( jaxbNamedQuery.isCacheable() == Boolean.TRUE ) {
namedQueryUsage.setAttributeValue( "cacheable", true );
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", jaxbNamedQuery.getCacheRegion(), namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheMode", jaxbNamedQuery.getCacheMode(), namedQueryUsage );
final CacheMode cacheMode = jaxbNamedQuery.getCacheMode();
if ( cacheMode != null && cacheMode != CacheMode.IGNORE ) {
switch ( cacheMode ) {
case GET -> {
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
}
}
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
}
}
AnnotationUsageHelper.applyAttributeIfSpecified( "fetchSize", jaxbNamedQuery.getFetchSize(), namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "timeout", jaxbNamedQuery.getTimeout(), namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "timeout", jaxbNamedQuery.getTimeout(), namedQueryUsage );
}
private static void applyNamedJpqlQuery(
JaxbNamedQueryImpl jaxbNamedQuery,
ClassDetails classDetails,
List<MutableAnnotationUsage<jakarta.persistence.NamedQuery>> namedQueryList,
SourceModelBuildingContext modelBuildingContext) {
final MutableAnnotationUsage<jakarta.persistence.NamedQuery> namedQueryUsage = JpaAnnotations.NAMED_QUERY.createUsage(
classDetails,
modelBuildingContext
);
namedQueryList.add( namedQueryUsage );
namedQueryUsage.setAttributeValue( "name", jaxbNamedQuery.getName() );
namedQueryUsage.setAttributeValue( "query", jaxbNamedQuery.getQuery() );
applyQueryHints( jaxbNamedQuery, classDetails, namedQueryUsage, modelBuildingContext );
}
private static void applyQueryHints(
JaxbNamedQueryBase jaxbNamedQuery,
ClassDetails classDetails,
MutableAnnotationUsage<?> namedQueryUsage,
SourceModelBuildingContext modelBuildingContext) {
if ( CollectionHelper.isNotEmpty( jaxbNamedQuery.getHints() ) ) {
final ArrayList<AnnotationUsage<QueryHint>> hints = CollectionHelper.arrayList( jaxbNamedQuery.getHints().size() );
namedQueryUsage.setAttributeValue( "hints", hints );
for ( JaxbQueryHint jaxbHint : jaxbNamedQuery.getHints() ) {
final MutableAnnotationUsage<QueryHint> queryHintUsage = JpaAnnotations.QUERY_HINT.createUsage(
classDetails,
modelBuildingContext
);
queryHintUsage.setAttributeValue( "name", jaxbHint.getName() );
queryHintUsage.setAttributeValue( "value", jaxbHint.getValue() );
}
}
}
public static void applyNamedNativeQueries(
JaxbEntityImpl jaxbEntity,
MutableClassDetails classDetails,
JaxbEntityMappingsImpl jaxbRoot,
XmlDocumentContext xmlDocumentContext) {
if ( CollectionHelper.isEmpty( jaxbEntity.getNamedNativeQueries() ) ) {
return;
}
final SourceModelBuildingContext modelBuildingContext = xmlDocumentContext.getModelBuildingContext();
List<MutableAnnotationUsage<NamedNativeQuery>> namedHibernateQueryList = null;
List<MutableAnnotationUsage<jakarta.persistence.NamedNativeQuery>> namedJpaQueryList = null;
for ( int i = 0; i < jaxbEntity.getNamedNativeQueries().size(); i++ ) {
final JaxbNamedNativeQueryImpl jaxbNamedQuery = jaxbEntity.getNamedNativeQueries().get( i );
if ( needsJpaNativeQuery( jaxbNamedQuery ) ) {
// @jakarta.persistence.NamedNativeQuery
if ( namedJpaQueryList == null ) {
final MutableAnnotationUsage<jakarta.persistence.NamedNativeQueries> namedQueriesUsage = AnnotationUsageHelper.getOrCreateUsage(
JpaAnnotations.NAMED_NATIVE_QUERIES,
classDetails,
modelBuildingContext
);
classDetails.addAnnotationUsage( namedQueriesUsage );
namedJpaQueryList = new ArrayList<>();
namedQueriesUsage.setAttributeValue( "value", namedQueriesUsage );
}
applyJpaNativeQuery( jaxbNamedQuery, classDetails, namedJpaQueryList, modelBuildingContext, xmlDocumentContext );
}
else {
// @org.hibernate.annotations.NamedNativeQuery
if ( namedHibernateQueryList == null ) {
final MutableAnnotationUsage<NamedNativeQueries> namedQueriesUsage = AnnotationUsageHelper.getOrCreateUsage(
HibernateAnnotations.NAMED_NATIVE_QUERIES,
classDetails,
modelBuildingContext
);
classDetails.addAnnotationUsage( namedQueriesUsage );
namedHibernateQueryList = new ArrayList<>();
namedQueriesUsage.setAttributeValue( "value", namedHibernateQueryList );
}
applyHibernateNativeQuery( jaxbNamedQuery, classDetails, namedHibernateQueryList, modelBuildingContext, xmlDocumentContext );
}
}
}
private static boolean needsJpaNativeQuery(JaxbNamedNativeQueryImpl jaxbNamedQuery) {
return CollectionHelper.isNotEmpty( jaxbNamedQuery.getHints() )
|| CollectionHelper.isNotEmpty( jaxbNamedQuery.getColumnResult() )
|| CollectionHelper.isNotEmpty( jaxbNamedQuery.getConstructorResult() )
|| CollectionHelper.isNotEmpty( jaxbNamedQuery.getEntityResult() );
}
private static void applyJpaNativeQuery(
JaxbNamedNativeQueryImpl jaxbNamedQuery,
MutableClassDetails classDetails,
List<MutableAnnotationUsage<jakarta.persistence.NamedNativeQuery>> namedQueryUsageList,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
final MutableAnnotationUsage<jakarta.persistence.NamedNativeQuery> namedQueryUsage = JpaAnnotations.NAMED_NATIVE_QUERY.createUsage(
classDetails,
modelBuildingContext
);
namedQueryUsageList.add( namedQueryUsage );
namedQueryUsage.setAttributeValue( "name", jaxbNamedQuery.getName() );
namedQueryUsage.setAttributeValue( "query", jaxbNamedQuery.getQuery() );
applyQueryHints( jaxbNamedQuery, classDetails, namedQueryUsage, modelBuildingContext );
applyResultClassAndSynchronizations( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext );
applyResultSetMappings( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext );
applyResults( jaxbNamedQuery, namedQueryUsage, classDetails, modelBuildingContext, xmlDocumentContext );
}
private static void applyResultClassAndSynchronizations(
JaxbNamedNativeQueryImpl jaxbNamedQuery,
MutableAnnotationUsage<?> namedQueryUsage,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
final List<String> syncSpaces = new ArrayList<>();
if ( jaxbNamedQuery.getResultClass() != null ) {
final String resultClassName = xmlDocumentContext.resolveClassName( jaxbNamedQuery.getResultClass() );
syncSpaces.add( resultClassName );
namedQueryUsage.setAttributeValue(
"resultClass",
modelBuildingContext.getClassDetailsRegistry().getClassDetails( resultClassName )
);
}
for ( JaxbSynchronizedTableImpl synchronization : jaxbNamedQuery.getSynchronizations() ) {
syncSpaces.add( synchronization.getTable() );
}
if ( CollectionHelper.isNotEmpty( syncSpaces ) ) {
namedQueryUsage.setAttributeValue( "querySpaces", syncSpaces );
}
}
private static void applyResultSetMappings(
JaxbNamedNativeQueryImpl jaxbNamedQuery,
MutableAnnotationUsage<?> namedQueryUsage,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
if ( isEmpty( jaxbNamedQuery.getResultSetMapping() ) ) {
return;
}
namedQueryUsage.setAttributeValue( "resultSetMapping", jaxbNamedQuery.getResultSetMapping() );
}
private static void applyResults(
JaxbNamedNativeQueryImpl jaxbNamedQuery,
MutableAnnotationUsage<jakarta.persistence.NamedNativeQuery> namedQueryUsage,
AnnotationTarget annotationTarget,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
if ( CollectionHelper.isNotEmpty( jaxbNamedQuery.getColumnResult() ) ) {
for ( JaxbColumnResultImpl jaxbColumnResult : jaxbNamedQuery.getColumnResult() ) {
final MutableAnnotationUsage<ColumnResult> columnResultUsage = JpaAnnotations.COLUMN_RESULT.createUsage(
annotationTarget,
modelBuildingContext
);
columnResultUsage.setAttributeValue( "name", jaxbColumnResult.getName() );
if ( isNotEmpty( jaxbColumnResult.getClazz() ) ) {
final String className = xmlDocumentContext.resolveClassName( jaxbColumnResult.getClazz() );
columnResultUsage.setAttributeValue( "type", modelBuildingContext.getClassDetailsRegistry().getClassDetails( className ) );
}
}
}
// todo (7.0) : finish the rest
}
private static void applyHibernateNativeQuery(
JaxbNamedNativeQueryImpl jaxbNamedQuery,
MutableClassDetails classDetails,
List<MutableAnnotationUsage<NamedNativeQuery>> namedQueryUsageList,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
final MutableAnnotationUsage<NamedNativeQuery> namedQueryUsage = HibernateAnnotations.NAMED_NATIVE_QUERY.createUsage(
classDetails,
modelBuildingContext
);
namedQueryUsageList.add( namedQueryUsage );
namedQueryUsage.setAttributeValue( "name", jaxbNamedQuery.getName() );
namedQueryUsage.setAttributeValue( "query", jaxbNamedQuery.getQuery() );
applyResultClassAndSynchronizations( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext );
applyResultSetMappings( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext );
}
public static void applyNamedProcedureQueries(
JaxbEntityImpl jaxbEntity,
MutableClassDetails classDetails,
XmlDocumentContext xmlDocumentContext) {
// todo (7.0) : implement
}
private static void applyNamedQueryBaseDetails(
JaxbNamedQueryBase baseDetails,
MutableAnnotationUsage<?> namedQueryUsage,
MutableClassDetails classDetails,
SourceModelBuildingContext modelBuildingContext) {
assert isNotEmpty( baseDetails.getName() );
namedQueryUsage.setAttributeValue( "name", baseDetails.getName() );
if ( CollectionHelper.isNotEmpty( baseDetails.getHints() ) ) {
final ArrayList<AnnotationUsage<QueryHint>> hints = CollectionHelper.arrayList( baseDetails.getHints().size() );
namedQueryUsage.setAttributeValue( "hints", hints );
for ( JaxbQueryHint jaxbHint : baseDetails.getHints() ) {
final MutableAnnotationUsage<QueryHint> queryHintUsage = JpaAnnotations.QUERY_HINT.createUsage( classDetails, modelBuildingContext );
queryHintUsage.setAttributeValue( "name", jaxbHint.getName() );
queryHintUsage.setAttributeValue( "value", jaxbHint.getValue() );
}
}
}
}

View File

@ -87,6 +87,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbUuidGeneratorImpl;
import org.hibernate.boot.jaxb.mapping.spi.db.JaxbCheckable;
import org.hibernate.boot.jaxb.mapping.spi.db.JaxbColumnJoined;
import org.hibernate.boot.jaxb.mapping.spi.db.JaxbTableMapping;
import org.hibernate.boot.models.JpaAnnotations;
import org.hibernate.boot.models.categorize.spi.JpaEventListener;
import org.hibernate.boot.models.categorize.spi.JpaEventListenerStyle;
import org.hibernate.boot.models.internal.AnnotationUsageHelper;
@ -155,6 +156,7 @@ import jakarta.persistence.UniqueConstraint;
import static java.lang.Boolean.FALSE;
import static java.util.Collections.emptyList;
import static org.hibernate.boot.models.JpaAnnotations.NAMED_ATTRIBUTE_NODE;
import static org.hibernate.boot.models.xml.internal.XmlProcessingHelper.makeNestedAnnotation;
/**
@ -308,7 +310,13 @@ public class XmlAnnotationHelper {
}
final List<AnnotationUsage<JoinColumn>> joinColumns = new ArrayList<>( jaxbJoinColumns.size() );
jaxbJoinColumns.forEach( jaxbJoinColumn -> {
joinColumns.add( applyJoinColumn( jaxbJoinColumn, memberDetails, xmlDocumentContext ) );
final MutableAnnotationUsage<JoinColumn> annotationUsage = createJoinColumnAnnotation(
jaxbJoinColumn,
memberDetails,
JoinColumn.class,
xmlDocumentContext
);
joinColumns.add( annotationUsage );
} );
return joinColumns;
}
@ -1554,10 +1562,9 @@ public class XmlAnnotationHelper {
final List<MutableAnnotationUsage<NamedAttributeNode>> namedAttributeNodeAnnotations =
new ArrayList<>( namedAttributeNodes.size() );
for ( JaxbNamedAttributeNodeImpl namedAttributeNode : namedAttributeNodes ) {
final MutableAnnotationUsage<NamedAttributeNode> namedAttributeNodeAnn = makeNestedAnnotation(
NamedAttributeNode.class,
final MutableAnnotationUsage<NamedAttributeNode> namedAttributeNodeAnn = NAMED_ATTRIBUTE_NODE.createUsage(
target,
xmlDocumentContext
xmlDocumentContext.getModelBuildingContext()
);
XmlProcessingHelper.applyAttributeIfSpecified( "value", namedAttributeNode.getName(), namedAttributeNodeAnn );
final AnnotationDescriptor<NamedAttributeNode> namedAttributeNodeDescriptor = xmlDocumentContext

View File

@ -22,6 +22,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl;
import org.hibernate.boot.models.xml.internal.XmlAnnotationHelper;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.models.internal.dynamic.DynamicClassDetails;
import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.MutableClassDetails;
@ -196,4 +197,15 @@ public interface XmlDocumentContext {
throw new HibernateException( "Unable to create instance from incoming ClassDetails - " + classDetails );
}
}
default String resolveClassName(String specifiedName) {
if ( specifiedName.contains( "." ) ) {
return specifiedName;
}
return StringHelper.qualifyConditionallyIfNot(
getXmlDocument().getDefaults().getPackage(),
specifiedName
);
}
}

View File

@ -7,6 +7,8 @@
package org.hibernate.orm.test.annotations.idclass.xml;
import java.util.List;
import org.hibernate.community.dialect.AltibaseDialect;
import org.hibernate.query.Query;
@ -41,7 +43,8 @@ public class IdClassXmlTest {
session.persist( link );
Query q = session.getNamedQuery( "testQuery" );
assertEquals( 1, q.list().size() );
final List<HabitatSpeciesLink> list = q.list();
assertEquals( 1, list.size() );
}
);
}

View File

@ -32,6 +32,7 @@ import java.util.Properties;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.models.spi.FieldDetails;
import org.hibernate.usertype.DynamicParameterizedType;
import org.hibernate.usertype.UserType;
@ -75,9 +76,9 @@ public class MyStringType implements UserType<String>, DynamicParameterizedType
String entity = params.getProperty( DynamicParameterizedType.ENTITY );
String propertyName = params.getProperty( DynamicParameterizedType.PROPERTY );
XProperty xproperty = (XProperty) params.get( DynamicParameterizedType.XPROPERTY );
FieldDetails xproperty = (FieldDetails) params.get( DynamicParameterizedType.XPROPERTY );
Assert.assertEquals( propertyName, xproperty.getName() );
Assert.assertEquals( entity, xproperty.getDeclaringClass().getName() );
Assert.assertEquals( entity, xproperty.getDeclaringType().getName() );
Assert.assertEquals( String.class.getName(), xproperty.getType().getName() );
String tableName = propertyName.toUpperCase().split( "_" )[0];

View File

@ -70,7 +70,7 @@ dependencyResolutionManagement {
def byteBuddyVersion = version "byteBuddy", "1.14.18"
def classmateVersion = version "classmate", "1.5.1"
def geolatteVersion = version "geolatte", "1.9.1"
def hibernateModelsVersion = version "hibernateModels", "0.7.2"
def hibernateModelsVersion = version "hibernateModels", "0.7.3"
def jandexVersion = version "jandex", "3.2.0"
def hcannVersion = version "hcann", "7.0.1.Final"
def jacksonVersion = version "jackson", "2.17.0"