HHH-17460 - Ongoing JPA 32 work

This commit is contained in:
Steve Ebersole 2024-03-26 13:00:20 -05:00
parent 38de392b2b
commit aededc93a2
7 changed files with 136 additions and 5 deletions

View File

@ -203,7 +203,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
this.uuid = UUID.randomUUID(); this.uuid = UUID.randomUUID();
this.globalRegistrations = new GlobalRegistrationsImpl( sourceModelBuildingContext ); this.globalRegistrations = new GlobalRegistrationsImpl( sourceModelBuildingContext, bootstrapContext );
this.persistenceUnitMetadata = new PersistenceUnitMetadataImpl(); this.persistenceUnitMetadata = new PersistenceUnitMetadataImpl();
for ( Map.Entry<String, SqmFunctionDescriptor> sqlFunctionEntry : bootstrapContext.getSqlFunctions().entrySet() ) { for ( Map.Entry<String, SqmFunctionDescriptor> sqlFunctionEntry : bootstrapContext.getSqlFunctions().entrySet() ) {

View File

@ -70,6 +70,9 @@ import org.hibernate.boot.models.categorize.spi.SqlResultSetMappingRegistration;
import org.hibernate.boot.models.categorize.spi.TableGeneratorRegistration; import org.hibernate.boot.models.categorize.spi.TableGeneratorRegistration;
import org.hibernate.boot.models.categorize.spi.UserTypeRegistration; import org.hibernate.boot.models.categorize.spi.UserTypeRegistration;
import org.hibernate.boot.models.xml.internal.XmlAnnotationHelper; import org.hibernate.boot.models.xml.internal.XmlAnnotationHelper;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.AvailableHints; import org.hibernate.jpa.AvailableHints;
@ -116,6 +119,7 @@ import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
*/ */
public class GlobalRegistrationsImpl implements GlobalRegistrations { public class GlobalRegistrationsImpl implements GlobalRegistrations {
private final SourceModelBuildingContext sourceModelContext; private final SourceModelBuildingContext sourceModelContext;
private final BootstrapContext bootstrapContext;
private List<JpaEventListener> jpaEventListeners; private List<JpaEventListener> jpaEventListeners;
private List<ConversionRegistration> converterRegistrations; private List<ConversionRegistration> converterRegistrations;
@ -139,8 +143,9 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
private Map<String, NamedNativeQueryRegistration> namedNativeQueryRegistrations; private Map<String, NamedNativeQueryRegistration> namedNativeQueryRegistrations;
private Map<String, NamedStoredProcedureQueryRegistration> namedStoredProcedureQueryRegistrations; private Map<String, NamedStoredProcedureQueryRegistration> namedStoredProcedureQueryRegistrations;
public GlobalRegistrationsImpl(SourceModelBuildingContext sourceModelContext) { public GlobalRegistrationsImpl(SourceModelBuildingContext sourceModelContext, BootstrapContext bootstrapContext) {
this.sourceModelContext = sourceModelContext; this.sourceModelContext = sourceModelContext;
this.bootstrapContext = bootstrapContext;
} }
@Override @Override
@ -696,6 +701,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
} }
public void collectSequenceGenerator(SequenceGeneratorRegistration generatorRegistration) { public void collectSequenceGenerator(SequenceGeneratorRegistration generatorRegistration) {
checkGeneratorName( generatorRegistration.name() );
if ( sequenceGeneratorRegistrations == null ) { if ( sequenceGeneratorRegistrations == null ) {
sequenceGeneratorRegistrations = new HashMap<>(); sequenceGeneratorRegistrations = new HashMap<>();
} }
@ -703,6 +710,26 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
sequenceGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration ); sequenceGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration );
} }
private void checkGeneratorName(String name) {
checkGeneratorName( name, sequenceGeneratorRegistrations );
checkGeneratorName( name, tableGeneratorRegistrations );
checkGeneratorName( name, genericGeneratorRegistrations );
}
private void checkGeneratorName(String name, Map<String, ?> generatorMap) {
if ( generatorMap == null ) {
return;
}
if ( generatorMap.containsKey( name ) ) {
if ( bootstrapContext.getJpaCompliance().isGlobalGeneratorScopeEnabled() ) {
throw new IllegalArgumentException( "Duplicate generator name " + name + "; you will likely want to set the property " + AvailableSettings.JPA_ID_GENERATOR_GLOBAL_SCOPE_COMPLIANCE + " to false " );
}
else {
CoreLogging.messageLogger( GlobalRegistrationsImpl.class ).duplicateGeneratorName( name );
}
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Table generator // Table generator
@ -736,6 +763,7 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
} }
public void collectTableGenerator(TableGeneratorRegistration generatorRegistration) { public void collectTableGenerator(TableGeneratorRegistration generatorRegistration) {
checkGeneratorName( generatorRegistration.name() );
if ( tableGeneratorRegistrations == null ) { if ( tableGeneratorRegistrations == null ) {
tableGeneratorRegistrations = new HashMap<>(); tableGeneratorRegistrations = new HashMap<>();
} }
@ -770,6 +798,8 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
} }
public void collectGenericGenerator(GenericGeneratorRegistration generatorRegistration) { public void collectGenericGenerator(GenericGeneratorRegistration generatorRegistration) {
checkGeneratorName( generatorRegistration.name() );
if ( genericGeneratorRegistrations == null ) { if ( genericGeneratorRegistrations == null ) {
genericGeneratorRegistrations = new HashMap<>(); genericGeneratorRegistrations = new HashMap<>();
} }
@ -952,17 +982,20 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
final MutableAnnotationUsage<QueryHint> cacheableHint = makeAnnotation( JpaAnnotations.QUERY_HINT ); final MutableAnnotationUsage<QueryHint> cacheableHint = makeAnnotation( JpaAnnotations.QUERY_HINT );
cacheableHint.setAttributeValue( "name", AvailableHints.HINT_CACHEABLE ); cacheableHint.setAttributeValue( "name", AvailableHints.HINT_CACHEABLE );
cacheableHint.setAttributeValue( "value", Boolean.TRUE.toString() ); cacheableHint.setAttributeValue( "value", Boolean.TRUE.toString() );
hints.add( cacheableHint );
if ( jaxbNamedQuery.getCacheMode() != null ) { if ( jaxbNamedQuery.getCacheMode() != null ) {
final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT ); final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT );
hint.setAttributeValue( "name", AvailableHints.HINT_CACHE_MODE ); hint.setAttributeValue( "name", AvailableHints.HINT_CACHE_MODE );
hint.setAttributeValue( "value", jaxbNamedQuery.getCacheMode().name() ); hint.setAttributeValue( "value", jaxbNamedQuery.getCacheMode().name() );
hints.add( hint );
} }
if ( isNotEmpty( jaxbNamedQuery.getCacheRegion() ) ) { if ( isNotEmpty( jaxbNamedQuery.getCacheRegion() ) ) {
final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT ); final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT );
hint.setAttributeValue( "name", AvailableHints.HINT_CACHE_REGION ); hint.setAttributeValue( "name", AvailableHints.HINT_CACHE_REGION );
hint.setAttributeValue( "value", jaxbNamedQuery.getCacheRegion() ); hint.setAttributeValue( "value", jaxbNamedQuery.getCacheRegion() );
hints.add( hint );
} }
} }
@ -970,24 +1003,28 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT ); final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT );
hint.setAttributeValue( "name", AvailableHints.HINT_COMMENT ); hint.setAttributeValue( "name", AvailableHints.HINT_COMMENT );
hint.setAttributeValue( "value", jaxbNamedQuery.getComment() ); hint.setAttributeValue( "value", jaxbNamedQuery.getComment() );
hints.add( hint );
} }
if ( jaxbNamedQuery.getFetchSize() != null ) { if ( jaxbNamedQuery.getFetchSize() != null ) {
final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT ); final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT );
hint.setAttributeValue( "name", AvailableHints.HINT_FETCH_SIZE ); hint.setAttributeValue( "name", AvailableHints.HINT_FETCH_SIZE );
hint.setAttributeValue( "value", jaxbNamedQuery.getFetchSize().toString() ); hint.setAttributeValue( "value", jaxbNamedQuery.getFetchSize().toString() );
hints.add( hint );
} }
if ( jaxbNamedQuery.isReadOnly() == Boolean.TRUE ) { if ( jaxbNamedQuery.isReadOnly() == Boolean.TRUE ) {
final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT ); final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT );
hint.setAttributeValue( "name", AvailableHints.HINT_READ_ONLY ); hint.setAttributeValue( "name", AvailableHints.HINT_READ_ONLY );
hint.setAttributeValue( "value", Boolean.TRUE.toString() ); hint.setAttributeValue( "value", Boolean.TRUE.toString() );
hints.add( hint );
} }
if ( jaxbNamedQuery.getFlushMode() != null ) { if ( jaxbNamedQuery.getFlushMode() != null ) {
final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT ); final MutableAnnotationUsage<QueryHint> hint = makeAnnotation( JpaAnnotations.QUERY_HINT );
hint.setAttributeValue( "name", AvailableHints.HINT_FLUSH_MODE ); hint.setAttributeValue( "name", AvailableHints.HINT_FLUSH_MODE );
hint.setAttributeValue( "value", jaxbNamedQuery.getFlushMode().name() ); hint.setAttributeValue( "value", jaxbNamedQuery.getFlushMode().name() );
hints.add( hint );
} }
} }
} }

View File

@ -14,7 +14,6 @@ import java.util.stream.Collectors;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.annotations.TenantId; import org.hibernate.annotations.TenantId;
import org.hibernate.boot.internal.BootstrapContextImpl;
import org.hibernate.boot.internal.MetadataBuilderImpl; import org.hibernate.boot.internal.MetadataBuilderImpl;
import org.hibernate.boot.internal.RootMappingDefaults; import org.hibernate.boot.internal.RootMappingDefaults;
import org.hibernate.boot.model.process.spi.ManagedResources; import org.hibernate.boot.model.process.spi.ManagedResources;
@ -137,7 +136,7 @@ public class ManagedResourcesProcessor {
final boolean areIdGeneratorsGlobal = true; final boolean areIdGeneratorsGlobal = true;
final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry(); final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry();
final AnnotationDescriptorRegistry descriptorRegistry = sourceModelBuildingContext.getAnnotationDescriptorRegistry(); final AnnotationDescriptorRegistry descriptorRegistry = sourceModelBuildingContext.getAnnotationDescriptorRegistry();
final GlobalRegistrationsImpl globalRegistrations = new GlobalRegistrationsImpl( sourceModelBuildingContext ); final GlobalRegistrationsImpl globalRegistrations = new GlobalRegistrationsImpl( sourceModelBuildingContext, bootstrapContext );
final DomainModelCategorizationCollector modelCategorizationCollector = new DomainModelCategorizationCollector( final DomainModelCategorizationCollector modelCategorizationCollector = new DomainModelCategorizationCollector(
areIdGeneratorsGlobal, areIdGeneratorsGlobal,
globalRegistrations, globalRegistrations,

View File

@ -23,6 +23,7 @@ import org.hibernate.models.spi.SourceModelBuildingContext;
import org.hibernate.orm.test.boot.models.XmlHelper; import org.hibernate.orm.test.boot.models.XmlHelper;
import org.hibernate.type.descriptor.jdbc.ClobJdbcType; import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
import org.hibernate.testing.boot.BootstrapContextImpl;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static jakarta.persistence.AccessType.FIELD; import static jakarta.persistence.AccessType.FIELD;
@ -126,7 +127,7 @@ public class XmlProcessingSmokeTests {
final DomainModelCategorizationCollector collector = new DomainModelCategorizationCollector( final DomainModelCategorizationCollector collector = new DomainModelCategorizationCollector(
false, false,
new GlobalRegistrationsImpl( buildingContext ), new GlobalRegistrationsImpl( buildingContext, new BootstrapContextImpl() ),
null, null,
buildingContext buildingContext
); );

View File

@ -0,0 +1,47 @@
/*
* 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.orm.test.hbm.query;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Basic;
import jakarta.persistence.NamedQuery;
/**
* @author Steve Ebersole
*/
@Entity
@NamedQuery(name = SimpleEntity.FIND_ALL, query = "from SimpleEntity")
public class SimpleEntity {
public static final String FIND_ALL = "SimpleEntity.findAll";
@Id
private Integer id;
@Basic
private String name;
protected SimpleEntity() {
// for Hibernate use
}
public SimpleEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.orm.test.hbm.query;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
public class XmlCacheableNamedQueryTests {
@Test
@DomainModel(
annotatedClasses = SimpleEntity.class,
xmlMappings = "org/hibernate/orm/test/hbm/query/CacheableNamedQueryOverride.xml"
)
@SessionFactory
@SuppressWarnings("JUnitMalformedDeclaration")
void testCacheableQueryOverride(SessionFactoryScope scope) {
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
final NamedObjectRepository namedObjectRepository = sessionFactory.getQueryEngine().getNamedObjectRepository();
final NamedSqmQueryMemento queryMemento = namedObjectRepository.getSqmQueryMemento( SimpleEntity.FIND_ALL );
assertThat( queryMemento ).isNotNull();
assertThat( queryMemento.getCacheable() ).isNotNull();
assertThat( queryMemento.getCacheable() ).isTrue();
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping" version="7.0">
<named-query name="SimpleEntity.findAll">
<query>from SimpleEntity</query>
<cacheable>true</cacheable>
</named-query>
</entity-mappings>