HHH-17460 - Ongoing JPA 32 work
This commit is contained in:
parent
ff640b23e9
commit
3465ab7c97
|
@ -15,16 +15,13 @@ import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.Remove;
|
|
||||||
import org.hibernate.annotations.CacheModeType;
|
import org.hibernate.annotations.CacheModeType;
|
||||||
import org.hibernate.annotations.FlushModeType;
|
import org.hibernate.annotations.FlushModeType;
|
||||||
import org.hibernate.annotations.HQLSelect;
|
import org.hibernate.annotations.HQLSelect;
|
||||||
import org.hibernate.annotations.SQLSelect;
|
import org.hibernate.annotations.SQLSelect;
|
||||||
import org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor;
|
|
||||||
import org.hibernate.annotations.common.annotationfactory.AnnotationFactory;
|
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
|
||||||
import org.hibernate.boot.internal.NamedHqlQueryDefinitionImpl;
|
import org.hibernate.boot.internal.NamedHqlQueryDefinitionImpl;
|
||||||
import org.hibernate.boot.internal.NamedProcedureCallDefinitionImpl;
|
import org.hibernate.boot.internal.NamedProcedureCallDefinitionImpl;
|
||||||
|
import org.hibernate.boot.models.JpaAnnotations;
|
||||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||||
import org.hibernate.boot.query.NamedNativeQueryDefinitionBuilder;
|
import org.hibernate.boot.query.NamedNativeQueryDefinitionBuilder;
|
||||||
|
@ -34,23 +31,23 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.log.DeprecationLogger;
|
import org.hibernate.internal.log.DeprecationLogger;
|
||||||
import org.hibernate.jpa.HibernateHints;
|
import org.hibernate.jpa.HibernateHints;
|
||||||
|
import org.hibernate.models.internal.util.StringHelper;
|
||||||
import org.hibernate.models.spi.AnnotationUsage;
|
import org.hibernate.models.spi.AnnotationUsage;
|
||||||
import org.hibernate.models.spi.ClassDetails;
|
import org.hibernate.models.spi.ClassDetails;
|
||||||
|
import org.hibernate.models.spi.MutableAnnotationUsage;
|
||||||
|
import org.hibernate.models.spi.SourceModelBuildingContext;
|
||||||
import org.hibernate.query.sql.internal.ParameterParser;
|
import org.hibernate.query.sql.internal.ParameterParser;
|
||||||
import org.hibernate.query.sql.spi.ParameterRecognizer;
|
import org.hibernate.query.sql.spi.ParameterRecognizer;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import jakarta.persistence.NamedNativeQueries;
|
|
||||||
import jakarta.persistence.NamedNativeQuery;
|
import jakarta.persistence.NamedNativeQuery;
|
||||||
import jakarta.persistence.NamedQueries;
|
|
||||||
import jakarta.persistence.NamedQuery;
|
import jakarta.persistence.NamedQuery;
|
||||||
import jakarta.persistence.NamedStoredProcedureQuery;
|
import jakarta.persistence.NamedStoredProcedureQuery;
|
||||||
import jakarta.persistence.ParameterMode;
|
import jakarta.persistence.ParameterMode;
|
||||||
import jakarta.persistence.QueryHint;
|
import jakarta.persistence.QueryHint;
|
||||||
import jakarta.persistence.SqlResultSetMapping;
|
import jakarta.persistence.SqlResultSetMapping;
|
||||||
import jakarta.persistence.SqlResultSetMappings;
|
|
||||||
import jakarta.persistence.StoredProcedureParameter;
|
import jakarta.persistence.StoredProcedureParameter;
|
||||||
|
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
|
@ -111,7 +108,6 @@ public abstract class QueryBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void bindNativeQuery(
|
public static void bindNativeQuery(
|
||||||
AnnotationUsage<NamedNativeQuery> namedNativeQuery,
|
AnnotationUsage<NamedNativeQuery> namedNativeQuery,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
|
@ -150,7 +146,6 @@ public abstract class QueryBinder {
|
||||||
.setComment( hints.getString( HibernateHints.HINT_COMMENT ) )
|
.setComment( hints.getString( HibernateHints.HINT_COMMENT ) )
|
||||||
.addHints( hints.getHintsMap() );
|
.addHints( hints.getHintsMap() );
|
||||||
|
|
||||||
|
|
||||||
final NamedNativeQueryDefinition queryDefinition = builder.build();
|
final NamedNativeQueryDefinition queryDefinition = builder.build();
|
||||||
|
|
||||||
if ( LOG.isDebugEnabled() ) {
|
if ( LOG.isDebugEnabled() ) {
|
||||||
|
@ -252,123 +247,97 @@ public abstract class QueryBinder {
|
||||||
|
|
||||||
context.getMetadataCollector().addNamedNativeQuery( queryDefinition );
|
context.getMetadataCollector().addNamedNativeQuery( queryDefinition );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NamedProcedureCallDefinition createStoredProcedure(
|
public static NamedProcedureCallDefinition createStoredProcedure(
|
||||||
NamedNativeQueryDefinitionBuilder builder,
|
NamedNativeQueryDefinitionBuilder builder,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
Supplier<RuntimeException> exceptionProducer) {
|
Supplier<RuntimeException> exceptionProducer) {
|
||||||
List<StoredProcedureParameter> storedProcedureParameters = new ArrayList<>();
|
|
||||||
List<QueryHint> queryHints = new ArrayList<>();
|
|
||||||
final String sqlString = builder.getSqlString().trim();
|
final String sqlString = builder.getSqlString().trim();
|
||||||
if ( !sqlString.startsWith( "{" ) || !sqlString.endsWith( "}" ) ) {
|
if ( !sqlString.startsWith( "{" ) || !sqlString.endsWith( "}" ) ) {
|
||||||
throw exceptionProducer.get();
|
throw exceptionProducer.get();
|
||||||
}
|
}
|
||||||
final JdbcCall jdbcCall = parseJdbcCall( sqlString, exceptionProducer );
|
final JdbcCall jdbcCall = parseJdbcCall( sqlString, exceptionProducer );
|
||||||
|
|
||||||
AnnotationDescriptor descriptor = new AnnotationDescriptor( NamedStoredProcedureQuery.class );
|
final SourceModelBuildingContext sourceModelBuildingContext = context.getMetadataCollector()
|
||||||
descriptor.setValue( "name", builder.getName() );
|
.getSourceModelBuildingContext();
|
||||||
descriptor.setValue( "procedureName", jdbcCall.callableName );
|
final MutableAnnotationUsage<NamedStoredProcedureQuery> nameStoredProcedureQueryAnn = JpaAnnotations.NAMED_STORED_PROCEDURE_QUERY.createUsage(
|
||||||
|
null,
|
||||||
|
sourceModelBuildingContext
|
||||||
|
);
|
||||||
|
nameStoredProcedureQueryAnn.setAttributeValue( "name", builder.getName() );
|
||||||
|
nameStoredProcedureQueryAnn.setAttributeValue( "procedureName", jdbcCall.callableName );
|
||||||
|
|
||||||
|
final List<AnnotationUsage<StoredProcedureParameter>> storedProcedureParameters = new ArrayList<>();
|
||||||
for ( String parameterName : jdbcCall.parameters ) {
|
for ( String parameterName : jdbcCall.parameters ) {
|
||||||
AnnotationDescriptor parameterDescriptor = new AnnotationDescriptor( StoredProcedureParameter.class );
|
final MutableAnnotationUsage<StoredProcedureParameter> storedProcedureParameterAnn = JpaAnnotations.STORED_PROCEDURE_PARAMETER
|
||||||
parameterDescriptor.setValue( "name", parameterName );
|
.createUsage( null, sourceModelBuildingContext );
|
||||||
parameterDescriptor.setValue( "mode", ParameterMode.IN );
|
storedProcedureParameterAnn.setAttributeValue( "name", parameterName );
|
||||||
|
storedProcedureParameterAnn.setAttributeValue( "mode", ParameterMode.IN );
|
||||||
final String typeName = builder.getParameterTypes().get( parameterName );
|
final String typeName = builder.getParameterTypes().get( parameterName );
|
||||||
if ( typeName == null ) {
|
final ClassDetails classDetails;
|
||||||
parameterDescriptor.setValue( "type", Object.class );
|
if ( StringHelper.isEmpty( typeName ) ) {
|
||||||
|
classDetails = ClassDetails.VOID_CLASS_DETAILS;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final BasicType<Object> registeredType = context.getBootstrapContext()
|
final BasicType<Object> registeredType = context.getBootstrapContext()
|
||||||
.getTypeConfiguration()
|
.getTypeConfiguration()
|
||||||
.getBasicTypeRegistry()
|
.getBasicTypeRegistry()
|
||||||
.getRegisteredType( typeName );
|
.getRegisteredType( typeName );
|
||||||
parameterDescriptor.setValue( "type", registeredType.getJavaType() );
|
classDetails = storedProcedureParameterAnn.getClassDetails( registeredType.getJavaType().getName() );
|
||||||
}
|
}
|
||||||
storedProcedureParameters.add( AnnotationFactory.create( parameterDescriptor ) );
|
storedProcedureParameterAnn.setAttributeValue( "type", classDetails );
|
||||||
|
|
||||||
|
storedProcedureParameters.add( storedProcedureParameterAnn );
|
||||||
}
|
}
|
||||||
descriptor.setValue(
|
nameStoredProcedureQueryAnn.setAttributeValue( "parameters", storedProcedureParameters );
|
||||||
"parameters",
|
|
||||||
storedProcedureParameters.toArray( new StoredProcedureParameter[storedProcedureParameters.size()] )
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( builder.getResultSetMappingName() != null ) {
|
if ( builder.getResultSetMappingName() != null ) {
|
||||||
descriptor.setValue( "resultSetMappings", new String[]{ builder.getResultSetMappingName() } );
|
final List<String> resultSetMappings = new ArrayList<>( 1 );
|
||||||
}
|
resultSetMappings.add( builder.getResultSetMappingName() );
|
||||||
else {
|
nameStoredProcedureQueryAnn.setAttributeValue( "resultSetMappings", resultSetMappings );
|
||||||
descriptor.setValue( "resultSetMappings", new String[0] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( builder.getResultSetMappingClassName() != null ) {
|
final String resultSetMappingClassName = builder.getResultSetMappingClassName();
|
||||||
descriptor.setValue(
|
if ( resultSetMappingClassName != null ) {
|
||||||
"resultClasses",
|
final List<ClassDetails> resultClasses = new ArrayList<>( 1 );
|
||||||
new Class[] {
|
final ClassDetails classDetails;
|
||||||
context.getBootstrapContext()
|
if ( StringHelper.isEmpty( resultSetMappingClassName ) ) {
|
||||||
.getClassLoaderAccess().classForName( builder.getResultSetMappingClassName() )
|
classDetails = ClassDetails.VOID_CLASS_DETAILS;
|
||||||
}
|
}
|
||||||
);
|
else {
|
||||||
}
|
classDetails = nameStoredProcedureQueryAnn.getClassDetails( resultSetMappingClassName );
|
||||||
else {
|
}
|
||||||
descriptor.setValue( "resultClasses", new Class[0] );
|
|
||||||
|
resultClasses.add( classDetails );
|
||||||
|
nameStoredProcedureQueryAnn.setAttributeValue( "resultClasses", resultClasses );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<AnnotationUsage<QueryHint>> queryHints = new ArrayList<>();
|
||||||
if ( builder.getQuerySpaces() != null ) {
|
if ( builder.getQuerySpaces() != null ) {
|
||||||
AnnotationDescriptor hintDescriptor = new AnnotationDescriptor( QueryHint.class );
|
final MutableAnnotationUsage<QueryHint> queryHintAnn = JpaAnnotations.QUERY_HINT.createUsage(
|
||||||
hintDescriptor.setValue( "name", HibernateHints.HINT_NATIVE_SPACES );
|
null,
|
||||||
hintDescriptor.setValue( "value", String.join( " ", builder.getQuerySpaces() ) );
|
sourceModelBuildingContext
|
||||||
queryHints.add( AnnotationFactory.create( hintDescriptor ) );
|
);
|
||||||
|
queryHintAnn.setAttributeValue( "name", HibernateHints.HINT_NATIVE_SPACES );
|
||||||
|
queryHintAnn.setAttributeValue( "value", String.join( " ", builder.getQuerySpaces() ) );
|
||||||
|
queryHints.add( queryHintAnn );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( jdbcCall.resultParameter ) {
|
if ( jdbcCall.resultParameter ) {
|
||||||
// Mark native queries that have a result parameter as callable functions
|
// Mark native queries that have a result parameter as callable functions
|
||||||
AnnotationDescriptor hintDescriptor2 = new AnnotationDescriptor( QueryHint.class );
|
final MutableAnnotationUsage<QueryHint> queryHintAnn = JpaAnnotations.QUERY_HINT.createUsage(
|
||||||
hintDescriptor2.setValue( "name", HibernateHints.HINT_CALLABLE_FUNCTION );
|
null,
|
||||||
hintDescriptor2.setValue( "value", "true" );
|
sourceModelBuildingContext
|
||||||
queryHints.add( AnnotationFactory.create( hintDescriptor2 ) );
|
);
|
||||||
|
queryHintAnn.setAttributeValue( "name", HibernateHints.HINT_CALLABLE_FUNCTION );
|
||||||
|
queryHintAnn.setAttributeValue( "value", "true" );
|
||||||
|
queryHints.add( queryHintAnn );
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.setValue( "hints", queryHints.toArray( new QueryHint[queryHints.size()] ) );
|
nameStoredProcedureQueryAnn.setAttributeValue( "hints", queryHints );
|
||||||
|
|
||||||
return new NamedProcedureCallDefinitionImpl( AnnotationFactory.create( descriptor ) );
|
return new NamedProcedureCallDefinitionImpl( nameStoredProcedureQueryAnn );
|
||||||
}
|
|
||||||
|
|
||||||
public static void bindQueries(AnnotationUsage<NamedQueries> namedQueries, MetadataBuildingContext context, boolean isDefault) {
|
|
||||||
if ( namedQueries == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<AnnotationUsage<NamedQuery>> nestedValues = namedQueries.getList( "value" );
|
|
||||||
for ( AnnotationUsage<NamedQuery> nestedValue : nestedValues ) {
|
|
||||||
bindQuery( nestedValue, context, isDefault );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void bindNativeQueries(
|
|
||||||
AnnotationUsage<NamedNativeQueries> namedNativeQueries,
|
|
||||||
MetadataBuildingContext context,
|
|
||||||
boolean isDefault) {
|
|
||||||
if ( namedNativeQueries == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<AnnotationUsage<NamedNativeQuery>> nestedValues = namedNativeQueries.getList( "value" );
|
|
||||||
for ( AnnotationUsage<NamedNativeQuery> nestedValue : nestedValues ) {
|
|
||||||
bindNativeQuery( nestedValue, context, isDefault );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void bindNativeQueries(
|
|
||||||
AnnotationUsage<org.hibernate.annotations.NamedNativeQueries> namedNativeQueries,
|
|
||||||
MetadataBuildingContext context) {
|
|
||||||
if ( namedNativeQueries == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<AnnotationUsage<org.hibernate.annotations.NamedNativeQuery>> nestedValues = namedNativeQueries.getList( "value" );
|
|
||||||
for ( AnnotationUsage<org.hibernate.annotations.NamedNativeQuery> nestedValue : nestedValues ) {
|
|
||||||
bindNativeQuery( nestedValue, context );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindQuery(
|
public static void bindQuery(
|
||||||
|
@ -464,20 +433,6 @@ public abstract class QueryBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void bindQueries(
|
|
||||||
AnnotationUsage<org.hibernate.annotations.NamedQueries> namedQueries,
|
|
||||||
MetadataBuildingContext context) {
|
|
||||||
if ( namedQueries == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<AnnotationUsage<org.hibernate.annotations.NamedQuery>> nestedValues = namedQueries.getList( "value" );
|
|
||||||
for ( AnnotationUsage<org.hibernate.annotations.NamedQuery> nestedValue : nestedValues ) {
|
|
||||||
bindQuery( nestedValue, context );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void bindNamedStoredProcedureQuery(
|
public static void bindNamedStoredProcedureQuery(
|
||||||
AnnotationUsage<NamedStoredProcedureQuery> namedStoredProcedureQuery,
|
AnnotationUsage<NamedStoredProcedureQuery> namedStoredProcedureQuery,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
|
@ -498,20 +453,6 @@ public abstract class QueryBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindSqlResultSetMappings(
|
|
||||||
AnnotationUsage<SqlResultSetMappings> resultSetMappings,
|
|
||||||
MetadataBuildingContext context,
|
|
||||||
boolean isDefault) {
|
|
||||||
if ( resultSetMappings == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<AnnotationUsage<SqlResultSetMapping>> mappings = resultSetMappings.getList( "value" );
|
|
||||||
for ( AnnotationUsage<SqlResultSetMapping> mapping : mappings ) {
|
|
||||||
bindSqlResultSetMapping( mapping, context, isDefault );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void bindSqlResultSetMapping(
|
public static void bindSqlResultSetMapping(
|
||||||
AnnotationUsage<SqlResultSetMapping> resultSetMappingAnn,
|
AnnotationUsage<SqlResultSetMapping> resultSetMappingAnn,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
|
@ -591,67 +532,6 @@ public abstract class QueryBinder {
|
||||||
return new JdbcCall( callableName, resultParameter, parameters );
|
return new JdbcCall( callableName, resultParameter, parameters );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remove
|
|
||||||
@Deprecated(since = "6.2")
|
|
||||||
public static String parseJdbcCall(
|
|
||||||
String sqlString,
|
|
||||||
List<String> parameterNames,
|
|
||||||
Supplier<RuntimeException> exceptionProducer) {
|
|
||||||
String procedureName = null;
|
|
||||||
int index = skipWhitespace( sqlString, 1 );
|
|
||||||
// Parse the out param `?=` part
|
|
||||||
if ( sqlString.charAt( index ) == '?' ) {
|
|
||||||
index++;
|
|
||||||
index = skipWhitespace( sqlString, index );
|
|
||||||
if ( sqlString.charAt( index ) != '=' ) {
|
|
||||||
throw exceptionProducer.get();
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
index = skipWhitespace( sqlString, index );
|
|
||||||
}
|
|
||||||
// Parse the call keyword
|
|
||||||
if ( !sqlString.regionMatches( true, index, "call", 0, 4 ) ) {
|
|
||||||
throw exceptionProducer.get();
|
|
||||||
}
|
|
||||||
index += 4;
|
|
||||||
index = skipWhitespace( sqlString, index );
|
|
||||||
|
|
||||||
// Parse the procedure name
|
|
||||||
final int procedureStart = index;
|
|
||||||
for ( ; index < sqlString.length(); index++ ) {
|
|
||||||
final char c = sqlString.charAt( index );
|
|
||||||
if ( c == '(' || Character.isWhitespace( c ) ) {
|
|
||||||
procedureName = sqlString.substring( procedureStart, index );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index = skipWhitespace( sqlString, index );
|
|
||||||
ParameterParser.parse(
|
|
||||||
sqlString.substring( index, sqlString.length() - 1 ),
|
|
||||||
new ParameterRecognizer() {
|
|
||||||
@Override
|
|
||||||
public void ordinalParameter(int sourcePosition) {
|
|
||||||
parameterNames.add( "" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void namedParameter(String name, int sourcePosition) {
|
|
||||||
parameterNames.add( name );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void jpaPositionalParameter(int label, int sourcePosition) {
|
|
||||||
parameterNames.add( "" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void other(char character) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return procedureName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int skipWhitespace(String sqlString, int i) {
|
private static int skipWhitespace(String sqlString, int i) {
|
||||||
while ( i < sqlString.length() ) {
|
while ( i < sqlString.length() ) {
|
||||||
if ( !Character.isWhitespace( sqlString.charAt( i ) ) ) {
|
if ( !Character.isWhitespace( sqlString.charAt( i ) ) ) {
|
||||||
|
|
Loading…
Reference in New Issue