HHH-17460 - Ongoing JPA 32 work

This commit is contained in:
Steve Ebersole 2024-03-26 14:41:09 -05:00
parent aededc93a2
commit 2b4d64dd92
1 changed files with 229 additions and 34 deletions

View File

@ -15,12 +15,17 @@ import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.annotations.NamedQueries; import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery; import org.hibernate.annotations.NamedQuery;
import org.hibernate.boot.jaxb.mapping.spi.JaxbColumnResultImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbColumnResultImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbConstructorResultImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityResultImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbFieldResultImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedNativeQueryImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedNativeQueryImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedQueryBase; import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedQueryBase;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedQueryImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedQueryImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNamedStoredProcedureQueryImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbQueryHint; import org.hibernate.boot.jaxb.mapping.spi.JaxbQueryHint;
import org.hibernate.boot.jaxb.mapping.spi.JaxbStoredProcedureParameterImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbSynchronizedTableImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbSynchronizedTableImpl;
import org.hibernate.boot.models.HibernateAnnotations; import org.hibernate.boot.models.HibernateAnnotations;
import org.hibernate.boot.models.JpaAnnotations; import org.hibernate.boot.models.JpaAnnotations;
@ -35,8 +40,16 @@ import org.hibernate.models.spi.MutableClassDetails;
import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.ColumnResult; import jakarta.persistence.ColumnResult;
import jakarta.persistence.ConstructorResult;
import jakarta.persistence.EntityResult;
import jakarta.persistence.FieldResult;
import jakarta.persistence.NamedStoredProcedureQueries;
import jakarta.persistence.NamedStoredProcedureQuery;
import jakarta.persistence.QueryHint; import jakarta.persistence.QueryHint;
import jakarta.persistence.StoredProcedureParameter;
import static org.hibernate.boot.models.internal.AnnotationUsageHelper.applyAttributeIfSpecified;
import static org.hibernate.boot.models.internal.AnnotationUsageHelper.applyStringAttributeIfSpecified;
import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty;
@ -117,11 +130,9 @@ public class QueryProcessing {
final CacheMode cacheMode = jaxbNamedQuery.getCacheMode(); final CacheMode cacheMode = jaxbNamedQuery.getCacheMode();
if ( cacheMode != null && cacheMode != CacheMode.IGNORE ) { if ( cacheMode != null && cacheMode != CacheMode.IGNORE ) {
switch ( cacheMode ) { if ( cacheMode == CacheMode.GET ) {
case GET -> { applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage ); applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
}
} }
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage ); AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage ); AnnotationUsageHelper.applyAttributeIfSpecified( "cacheRegion", cacheMode, namedQueryUsage );
@ -246,7 +257,7 @@ public class QueryProcessing {
applyQueryHints( jaxbNamedQuery, classDetails, namedQueryUsage, modelBuildingContext ); applyQueryHints( jaxbNamedQuery, classDetails, namedQueryUsage, modelBuildingContext );
applyResultClassAndSynchronizations( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext ); applyResultClassAndSynchronizations( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext );
applyResultSetMappings( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext ); applyResultSetMappings( jaxbNamedQuery, namedQueryUsage, xmlDocumentContext );
applyResults( jaxbNamedQuery, namedQueryUsage, classDetails, modelBuildingContext, xmlDocumentContext ); applyResults( jaxbNamedQuery, namedQueryUsage, classDetails, modelBuildingContext, xmlDocumentContext );
} }
@ -278,7 +289,6 @@ public class QueryProcessing {
private static void applyResultSetMappings( private static void applyResultSetMappings(
JaxbNamedNativeQueryImpl jaxbNamedQuery, JaxbNamedNativeQueryImpl jaxbNamedQuery,
MutableAnnotationUsage<?> namedQueryUsage, MutableAnnotationUsage<?> namedQueryUsage,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) { XmlDocumentContext xmlDocumentContext) {
if ( isEmpty( jaxbNamedQuery.getResultSetMapping() ) ) { if ( isEmpty( jaxbNamedQuery.getResultSetMapping() ) ) {
return; return;
@ -294,20 +304,141 @@ public class QueryProcessing {
SourceModelBuildingContext modelBuildingContext, SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) { XmlDocumentContext xmlDocumentContext) {
if ( CollectionHelper.isNotEmpty( jaxbNamedQuery.getColumnResult() ) ) { if ( CollectionHelper.isNotEmpty( jaxbNamedQuery.getColumnResult() ) ) {
for ( JaxbColumnResultImpl jaxbColumnResult : jaxbNamedQuery.getColumnResult() ) { final ArrayList<MutableAnnotationUsage<ColumnResult>> columnResultList = extractColumnResults(
final MutableAnnotationUsage<ColumnResult> columnResultUsage = JpaAnnotations.COLUMN_RESULT.createUsage( jaxbNamedQuery.getColumnResult(),
annotationTarget,
modelBuildingContext,
xmlDocumentContext
);
namedQueryUsage.setAttributeValue( "columns", columnResultList );
}
if ( CollectionHelper.isNotEmpty( jaxbNamedQuery.getConstructorResult() ) ) {
final ArrayList<MutableAnnotationUsage<ConstructorResult>> constructorResultList = extractConstructorResults(
jaxbNamedQuery.getConstructorResult(),
annotationTarget,
modelBuildingContext,
xmlDocumentContext
);
namedQueryUsage.setAttributeValue( "classes", constructorResultList );
}
if ( CollectionHelper.isNotEmpty( jaxbNamedQuery.getEntityResult() ) ) {
final ArrayList<MutableAnnotationUsage<EntityResult>> entityResultList = extractEntityResults(
jaxbNamedQuery.getEntityResult(),
annotationTarget,
modelBuildingContext,
xmlDocumentContext
);
namedQueryUsage.setAttributeValue( "entities", entityResultList );
}
}
private static ArrayList<MutableAnnotationUsage<ColumnResult>> extractColumnResults(
List<JaxbColumnResultImpl> jaxbColumnResultList,
AnnotationTarget annotationTarget,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
assert CollectionHelper.isNotEmpty( jaxbColumnResultList );
final ArrayList<MutableAnnotationUsage<ColumnResult>> columnResultList = CollectionHelper.arrayList( jaxbColumnResultList.size() );
for ( JaxbColumnResultImpl jaxbColumnResult : jaxbColumnResultList ) {
final MutableAnnotationUsage<ColumnResult> columnResultUsage = JpaAnnotations.COLUMN_RESULT.createUsage(
annotationTarget,
modelBuildingContext
);
columnResultList.add( columnResultUsage );
columnResultUsage.setAttributeValue( "name", jaxbColumnResult.getName() );
if ( isNotEmpty( jaxbColumnResult.getClazz() ) ) {
columnResultUsage.setAttributeValue( "type", xmlDocumentContext.resolveJavaType( jaxbColumnResult.getClazz() ) );
}
}
return columnResultList;
}
private static ArrayList<MutableAnnotationUsage<ConstructorResult>> extractConstructorResults(
List<JaxbConstructorResultImpl> jaxbConstructorResultList,
AnnotationTarget annotationTarget,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
assert CollectionHelper.isNotEmpty( jaxbConstructorResultList );
final ArrayList<MutableAnnotationUsage<ConstructorResult>> constructorResultList = CollectionHelper.arrayList( jaxbConstructorResultList.size() );
for ( JaxbConstructorResultImpl jaxbConstructorResult : jaxbConstructorResultList ) {
final MutableAnnotationUsage<ConstructorResult> constructorResultUsage = JpaAnnotations.CONSTRUCTOR_RESULT.createUsage(
annotationTarget,
modelBuildingContext
);
constructorResultList.add( constructorResultUsage );
constructorResultUsage.setAttributeValue( "targetClass", xmlDocumentContext.resolveJavaType( jaxbConstructorResult.getTargetClass() ) );
if ( CollectionHelper.isNotEmpty( jaxbConstructorResult.getColumns() ) ) {
final ArrayList<MutableAnnotationUsage<ColumnResult>> columnResultList = extractColumnResults(
jaxbConstructorResult.getColumns(),
annotationTarget, annotationTarget,
modelBuildingContext modelBuildingContext,
xmlDocumentContext
); );
columnResultUsage.setAttributeValue( "name", jaxbColumnResult.getName() ); constructorResultUsage.setAttributeValue( "columns", columnResultList );
if ( isNotEmpty( jaxbColumnResult.getClazz() ) ) { }
final String className = xmlDocumentContext.resolveClassName( jaxbColumnResult.getClazz() ); }
columnResultUsage.setAttributeValue( "type", modelBuildingContext.getClassDetailsRegistry().getClassDetails( className ) ); return constructorResultList;
} }
private static ArrayList<MutableAnnotationUsage<EntityResult>> extractEntityResults(
List<JaxbEntityResultImpl> jaxbEntityResults,
AnnotationTarget annotationTarget,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
assert CollectionHelper.isNotEmpty( jaxbEntityResults );
final ArrayList<MutableAnnotationUsage<EntityResult>> entityResultList = CollectionHelper.arrayList( jaxbEntityResults.size() );
for ( JaxbEntityResultImpl jaxbEntityResult : jaxbEntityResults ) {
final MutableAnnotationUsage<EntityResult> entityResultUsage = JpaAnnotations.ENTITY_RESULT.createUsage(
annotationTarget,
modelBuildingContext
);
entityResultList.add( entityResultUsage );
entityResultUsage.setAttributeValue( "entityClass", xmlDocumentContext.resolveJavaType( jaxbEntityResult.getEntityClass() ) );
applyAttributeIfSpecified( "lockMode", jaxbEntityResult.getLockMode(), entityResultUsage );
applyStringAttributeIfSpecified( "discriminatorColumn", jaxbEntityResult.getDiscriminatorColumn(), entityResultUsage );
if ( CollectionHelper.isNotEmpty( jaxbEntityResult.getFieldResult() ) ) {
final ArrayList<MutableAnnotationUsage<FieldResult>> fieldResultList = extractFieldResults(
jaxbEntityResult.getFieldResult(),
annotationTarget,
modelBuildingContext,
xmlDocumentContext
);
entityResultUsage.setAttributeValue( "fields", fieldResultList );
} }
} }
// todo (7.0) : finish the rest return entityResultList;
}
private static ArrayList<MutableAnnotationUsage<FieldResult>> extractFieldResults(
List<JaxbFieldResultImpl> jaxbFieldResults,
AnnotationTarget annotationTarget,
SourceModelBuildingContext modelBuildingContext,
XmlDocumentContext xmlDocumentContext) {
assert CollectionHelper.isNotEmpty( jaxbFieldResults );
final ArrayList<MutableAnnotationUsage<FieldResult>> fieldResultList = CollectionHelper.arrayList( jaxbFieldResults.size() );
for ( JaxbFieldResultImpl jaxbFieldResult : jaxbFieldResults ) {
final MutableAnnotationUsage<FieldResult> fieldResultUsage = JpaAnnotations.FIELD_RESULT.createUsage(
annotationTarget,
modelBuildingContext
);
fieldResultList.add( fieldResultUsage );
fieldResultUsage.setAttributeValue( "name", jaxbFieldResult.getName() );
fieldResultUsage.setAttributeValue( "column", jaxbFieldResult.getColumn() );
}
return fieldResultList;
} }
private static void applyHibernateNativeQuery( private static void applyHibernateNativeQuery(
@ -326,33 +457,97 @@ public class QueryProcessing {
namedQueryUsage.setAttributeValue( "query", jaxbNamedQuery.getQuery() ); namedQueryUsage.setAttributeValue( "query", jaxbNamedQuery.getQuery() );
applyResultClassAndSynchronizations( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext ); applyResultClassAndSynchronizations( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext );
applyResultSetMappings( jaxbNamedQuery, namedQueryUsage, modelBuildingContext, xmlDocumentContext ); applyResultSetMappings( jaxbNamedQuery, namedQueryUsage, xmlDocumentContext );
} }
public static void applyNamedProcedureQueries( public static void applyNamedProcedureQueries(
JaxbEntityImpl jaxbEntity, JaxbEntityImpl jaxbEntity,
MutableClassDetails classDetails, MutableClassDetails classDetails,
XmlDocumentContext xmlDocumentContext) { XmlDocumentContext xmlDocumentContext) {
// todo (7.0) : implement if ( CollectionHelper.isEmpty( jaxbEntity.getNamedStoredProcedureQueries() ) ) {
} return;
}
private static void applyNamedQueryBaseDetails( final SourceModelBuildingContext modelBuildingContext = xmlDocumentContext.getModelBuildingContext();
JaxbNamedQueryBase baseDetails, final MutableAnnotationUsage<NamedStoredProcedureQueries> namedQueriesUsage = JpaAnnotations.NAMED_STORED_PROCEDURE_QUERIES.createUsage(
MutableAnnotationUsage<?> namedQueryUsage, classDetails,
MutableClassDetails classDetails, modelBuildingContext
SourceModelBuildingContext modelBuildingContext) { );
assert isNotEmpty( baseDetails.getName() ); classDetails.addAnnotationUsage( namedQueriesUsage );
namedQueryUsage.setAttributeValue( "name", baseDetails.getName() ); final ArrayList<AnnotationUsage<NamedStoredProcedureQuery>> namedQueryList = CollectionHelper.arrayList( jaxbEntity.getNamedStoredProcedureQueries().size() );
namedQueriesUsage.setAttributeValue( "value", namedQueryList );
if ( CollectionHelper.isNotEmpty( baseDetails.getHints() ) ) { for ( JaxbNamedStoredProcedureQueryImpl jaxbQuery : jaxbEntity.getNamedStoredProcedureQueries() ) {
final ArrayList<AnnotationUsage<QueryHint>> hints = CollectionHelper.arrayList( baseDetails.getHints().size() ); final MutableAnnotationUsage<NamedStoredProcedureQuery> namedQueryUsage = JpaAnnotations.NAMED_STORED_PROCEDURE_QUERY.createUsage(
namedQueryUsage.setAttributeValue( "hints", hints ); classDetails,
modelBuildingContext
);
namedQueryList.add( namedQueryUsage );
for ( JaxbQueryHint jaxbHint : baseDetails.getHints() ) { namedQueryUsage.setAttributeValue( "name", jaxbQuery.getName() );
final MutableAnnotationUsage<QueryHint> queryHintUsage = JpaAnnotations.QUERY_HINT.createUsage( classDetails, modelBuildingContext ); namedQueryUsage.setAttributeValue( "procedureName", jaxbQuery.getProcedureName() );
queryHintUsage.setAttributeValue( "name", jaxbHint.getName() );
queryHintUsage.setAttributeValue( "value", jaxbHint.getValue() ); applyQueryHints( jaxbQuery, classDetails, namedQueryUsage, modelBuildingContext );
} applyQueryParameters( jaxbQuery, classDetails, namedQueryUsage, xmlDocumentContext );
applyResultSetMappings( jaxbQuery, namedQueryUsage, xmlDocumentContext );
applyResultClasses( jaxbQuery, namedQueryUsage, xmlDocumentContext );
} }
} }
private static void applyQueryParameters(
JaxbNamedStoredProcedureQueryImpl jaxbQuery,
MutableClassDetails classDetails,
MutableAnnotationUsage<NamedStoredProcedureQuery> queryUsage,
XmlDocumentContext xmlDocumentContext) {
if ( CollectionHelper.isEmpty( jaxbQuery.getProcedureParameters() ) ) {
return;
}
final SourceModelBuildingContext sourceModelBuildingContext = xmlDocumentContext.getModelBuildingContext();
final ArrayList<AnnotationUsage<StoredProcedureParameter>> parameterList = CollectionHelper.arrayList( jaxbQuery.getProcedureParameters().size() );
queryUsage.setAttributeValue( "parameters", parameterList );
for ( JaxbStoredProcedureParameterImpl jaxbParameter : jaxbQuery.getProcedureParameters() ) {
final MutableAnnotationUsage<StoredProcedureParameter> parameterUsage = JpaAnnotations.STORED_PROCEDURE_PARAMETER.createUsage(
classDetails,
sourceModelBuildingContext
);
parameterList.add( parameterUsage );
applyStringAttributeIfSpecified( "name", jaxbParameter.getName(), parameterUsage );
applyAttributeIfSpecified( "mode", jaxbParameter.getMode(), parameterUsage );
parameterUsage.setAttributeValue( "type", xmlDocumentContext.resolveJavaType( jaxbParameter.getClazz() ) );
}
}
private static void applyResultSetMappings(
JaxbNamedStoredProcedureQueryImpl jaxbQuery,
MutableAnnotationUsage<NamedStoredProcedureQuery> namedQueryUsage,
XmlDocumentContext xmlDocumentContext) {
if ( CollectionHelper.isEmpty( jaxbQuery.getResultSetMappings() ) ) {
return;
}
namedQueryUsage.setAttributeValue( "resultSetMappings", jaxbQuery.getResultSetMappings() );
}
private static void applyResultClasses(
JaxbNamedStoredProcedureQueryImpl jaxbQuery,
MutableAnnotationUsage<NamedStoredProcedureQuery> namedQueryUsage,
XmlDocumentContext xmlDocumentContext) {
if ( CollectionHelper.isEmpty( jaxbQuery.getResultClasses() ) ) {
return;
}
final ArrayList<ClassDetails> resultClasses = CollectionHelper.arrayList( jaxbQuery.getResultClasses().size() );
namedQueryUsage.setAttributeValue( "resultClasses", resultClasses );
for ( String resultClass : jaxbQuery.getResultClasses() ) {
final MutableClassDetails resultClassDetails = xmlDocumentContext.resolveJavaType( resultClass );
resultClasses.add( resultClassDetails );
}
}
} }