Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions hibernate-core/src/main/java/org/hibernate/SessionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@
* used in a sophisticated way by libraries or frameworks to implement generic
* concerns involving entity classes.
* <p>
* When the Metamodel Generator is used, elements of this metamodel may also
* be obtained in a typesafe way, via the generated metamodel classes. For
* an entity class {@code Book}, the generated {@code Book_} class has:
* When Hibernate Processor is used, elements of this metamodel may also be
* obtained in a typesafe way, via the generated metamodel classes. For an
* entity class {@code Book}, the generated {@code Book_} class has:
* <ul>
* <li>a single member named {@code class_} of type
* {@link jakarta.persistence.metamodel.EntityType EntityType&lt;Book&gt;},
Expand Down Expand Up @@ -129,7 +129,8 @@
* underlying {@code SessionFactory}.
* <p>
* The very simplest way to obtain a new {@code SessionFactory} is using a
* {@link org.hibernate.cfg.Configuration}.
* {@link org.hibernate.cfg.Configuration} or
* {@link org.hibernate.jpa.HibernatePersistenceConfiguration}.
*
* @see Session
* @see org.hibernate.cfg.Configuration
Expand All @@ -139,7 +140,7 @@
*/
public interface SessionFactory extends EntityManagerFactory, Referenceable, Serializable {
/**
* The JNDI name, used to bind the SessionFactory to JNDI
* The JNDI name, used to bind the {@code SessionFactory} to JNDI.
*/
String getJndiName();

Expand Down Expand Up @@ -203,7 +204,7 @@ public interface SessionFactory extends EntityManagerFactory, Referenceable, Ser
/**
* Open a new stateless session.
*
* @return The created stateless session.
* @return The new stateless session.
*/
StatelessSession openStatelessSession();

Expand All @@ -213,7 +214,7 @@ public interface SessionFactory extends EntityManagerFactory, Referenceable, Ser
*
* @param connection Connection provided by the application.
*
* @return The created stateless session.
* @return The new stateless session.
*/
StatelessSession openStatelessSession(Connection connection);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.hibernate.metamodel.model.domain.internal;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
Expand All @@ -20,13 +19,9 @@
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.UnknownEntityTypeException;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cache.spi.CacheImplementor;
import org.hibernate.cache.spi.access.CollectionDataAccess;
import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
import org.hibernate.graph.RootGraph;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.CoreLogging;
Expand All @@ -40,7 +35,6 @@
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.model.domain.BasicDomainType;
Expand Down Expand Up @@ -81,7 +75,6 @@
import jakarta.persistence.metamodel.ManagedType;
import jakarta.persistence.metamodel.Metamodel;

import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_STRING_ARRAY;
import static org.hibernate.metamodel.internal.JpaMetamodelPopulationSetting.determineJpaMetaModelPopulationSetting;
import static org.hibernate.metamodel.internal.JpaStaticMetamodelPopulationSetting.determineJpaStaticMetaModelPopulationSetting;

Expand All @@ -97,11 +90,8 @@
*/
public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
implements MappingMetamodelImplementor,JpaMetamodel, Metamodel, Serializable {
// todo : Integrate EntityManagerLogger into CoreMessageLogger
private static final CoreMessageLogger log = CoreLogging.messageLogger( MappingMetamodelImpl.class );

//NOTE: we suppress deprecation warnings because at the moment we
//implement a deprecated API so have to override deprecated things
private static final CoreMessageLogger log = CoreLogging.messageLogger( MappingMetamodelImpl.class );

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JpaMetamodel
Expand All @@ -110,7 +100,6 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl

private final Map<Class<?>, String> entityProxyInterfaceMap = new ConcurrentHashMap<>();


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// RuntimeModel

Expand All @@ -119,28 +108,29 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
private final Map<String, Set<String>> collectionRolesByEntityParticipant = new ConcurrentHashMap<>();

private final Map<NavigableRole, EmbeddableValuedModelPart> embeddableValuedModelPart = new ConcurrentHashMap<>();

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DomainMetamodel

private final Set<EntityNameResolver> entityNameResolvers = new HashSet<>();


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NOTE : Relational/mapping information is not part of the JPA metamodel
// (type system). However, this relational/mapping info *is* part of the
// Hibernate metamodel. This is a mismatch. Normally this is not a
// problem - ignoring Hibernate's representation mode (entity mode),
// an entity (or mapped superclass) *Class* always refers to the same
// EntityType (JPA) and EntityPersister (Hibernate).. The problem is
// in regards to embeddables. For an embeddable, as with the rest of its
// metamodel, Hibernate combines the embeddable's relational/mapping
// while JPA does not. This is consistent with each's model paradigm.
// However, it causes a mismatch in that while JPA expects a single
// "type descriptor" for a given embeddable class, Hibernate incorporates
// the relational/mapping info so we have a "type descriptor" for each
// usage of that embeddable. Think embeddable versus embedded.
// NOTE: Relational/mapping information is not part of the JPA metamodel
// (type system). However, this relational/mapping info *is* part of the
// Hibernate metamodel. This is a mismatch. Normally this is not a problem
// - ignoring Hibernate's representation mode (entity mode), the Class
// object for an entity (or mapped superclass) always refers to the same
// JPA EntityType and Hibernate EntityPersister. The problem arises with
// embeddables. For an embeddable, as with the rest of its metamodel,
// Hibernate combines the embeddable's relational/mapping while JPA does
// not. This is perfectly consistent with each paradigm. But it results
// in a mismatch since JPA expects a single "type descriptor" for a
// given embeddable class while Hibernate incorporates the
// relational/mapping info so we have a "type descriptor" for each usage
// of that embeddable type. (Think embeddable versus embedded.)
//
// To account for this, we track both paradigms here...
// To account for this, we track both paradigms here.

// There can be multiple instances of an Embeddable type, each one being relative to its parent entity.

Expand Down Expand Up @@ -225,54 +215,50 @@ private void processBootEntities(
RuntimeModelCreationContext modelCreationContext) {
for ( final PersistentClass model : entityBindings ) {
final NavigableRole rootEntityRole = new NavigableRole( model.getRootClass().getEntityName() );
final EntityDataAccess accessStrategy = cacheImplementor.getEntityRegionAccess( rootEntityRole );
final NaturalIdDataAccess naturalIdAccessStrategy = cacheImplementor
.getNaturalIdCacheRegionAccessStrategy( rootEntityRole );

final EntityPersister cp = persisterFactory.createEntityPersister(
model,
accessStrategy,
naturalIdAccessStrategy,
modelCreationContext
);
entityPersisterMap.put( model.getEntityName(), cp );
final EntityPersister entityPersister =
persisterFactory.createEntityPersister(
model,
cacheImplementor.getEntityRegionAccess( rootEntityRole ),
cacheImplementor.getNaturalIdCacheRegionAccessStrategy( rootEntityRole ),
modelCreationContext
);
entityPersisterMap.put( model.getEntityName(), entityPersister );
// Also register the persister under the class name if available,
// otherwise the getEntityDescriptor(Class) won't work for entities with custom entity names
if ( model.getClassName() != null && !model.getClassName().equals( model.getEntityName() ) ) {
// But only if the class name is not registered already,
// as we can have the same class mapped to multiple entity names
entityPersisterMap.putIfAbsent( model.getClassName(), cp );
entityPersisterMap.putIfAbsent( model.getClassName(), entityPersister );
}

if ( cp.getConcreteProxyClass() != null
&& cp.getConcreteProxyClass().isInterface()
&& !Map.class.isAssignableFrom( cp.getConcreteProxyClass() )
&& cp.getMappedClass() != cp.getConcreteProxyClass() ) {
if ( entityPersister.getConcreteProxyClass() != null
&& entityPersister.getConcreteProxyClass().isInterface()
&& !Map.class.isAssignableFrom( entityPersister.getConcreteProxyClass() )
&& entityPersister.getMappedClass() != entityPersister.getConcreteProxyClass() ) {
// IMPL NOTE : we exclude Map based proxy interfaces here because that should
// indicate MAP entity mode.0

if ( cp.getMappedClass().equals( cp.getConcreteProxyClass() ) ) {
// this part handles an odd case in the Hibernate test suite where we map an interface
// as the class and the proxy. I cannot think of a real life use case for that
// specific test, but..
if ( entityPersister.getMappedClass().equals( entityPersister.getConcreteProxyClass() ) ) {
// This part handles an odd case in the Hibernate test suite where we map an interface
// as the class and the proxy. I cannot think of a real-life use case for this.
if ( log.isDebugEnabled() ) {
log.debugf(
"Entity [%s] mapped same interface [%s] as class and proxy",
cp.getEntityName(),
cp.getMappedClass()
entityPersister.getEntityName(),
entityPersister.getMappedClass()
);
}
}
else {
final String old = entityProxyInterfaceMap.put( cp.getConcreteProxyClass(), cp.getEntityName() );
final String old = entityProxyInterfaceMap.put( entityPersister.getConcreteProxyClass(), entityPersister.getEntityName() );
if ( old != null ) {
throw new HibernateException(
String.format(
Locale.ENGLISH,
"Multiple entities [%s, %s] named the same interface [%s] as their proxy which is not supported",
old,
cp.getEntityName(),
cp.getConcreteProxyClass().getName()
entityPersister.getEntityName(),
entityPersister.getConcreteProxyClass().getName()
)
);
}
Expand All @@ -288,15 +274,12 @@ private void processBootCollections(
RuntimeModelCreationContext modelCreationContext) {
for ( final Collection model : collectionBindings ) {
final NavigableRole navigableRole = new NavigableRole( model.getRole() );

final CollectionDataAccess accessStrategy = cacheImplementor.getCollectionRegionAccess(
navigableRole );

final CollectionPersister persister = persisterFactory.createCollectionPersister(
model,
accessStrategy,
modelCreationContext
);
final CollectionPersister persister =
persisterFactory.createCollectionPersister(
model,
cacheImplementor.getCollectionRegionAccess( navigableRole ),
modelCreationContext
);
collectionPersisterMap.put( model.getRole(), persister );
if ( persister.getIndexType() instanceof org.hibernate.type.EntityType entityType ) {
registerEntityParticipant( entityType, persister );
Expand Down Expand Up @@ -400,7 +383,7 @@ public boolean isEntityClass(Class<?> entityJavaType) {
public EntityPersister getEntityDescriptor(Class<?> entityJavaType) {
EntityPersister entityPersister = entityPersisterMap.get( entityJavaType.getName() );
if ( entityPersister == null ) {
String mappedEntityName = entityProxyInterfaceMap.get( entityJavaType );
final String mappedEntityName = entityProxyInterfaceMap.get( entityJavaType );
if ( mappedEntityName != null ) {
entityPersister = entityPersisterMap.get( mappedEntityName );
}
Expand All @@ -417,7 +400,7 @@ public EntityPersister getEntityDescriptor(Class<?> entityJavaType) {
public EntityPersister locateEntityDescriptor(Class<?> byClass) {
EntityPersister entityPersister = entityPersisterMap.get( byClass.getName() );
if ( entityPersister == null ) {
String mappedEntityName = entityProxyInterfaceMap.get( byClass );
final String mappedEntityName = entityProxyInterfaceMap.get( byClass );
if ( mappedEntityName != null ) {
entityPersister = entityPersisterMap.get( mappedEntityName );
}
Expand Down Expand Up @@ -655,35 +638,6 @@ public List<RootGraph<?>> findRootGraphsForType(EntityPersister baseEntityDescri
return null;
}

private String[] doGetImplementors(Class<?> clazz) throws MappingException {
final ArrayList<String> results = new ArrayList<>();
forEachEntityDescriptor( descriptor -> {
final String checkQueryableEntityName = ((EntityMappingType) descriptor).getEntityName();
final boolean isMappedClass = clazz.getName().equals( checkQueryableEntityName );
if ( isMappedClass ) {
results.add( checkQueryableEntityName );
}
else {
final Class<?> mappedClass = descriptor.getMappedClass();
if ( mappedClass != null && clazz.isAssignableFrom( mappedClass ) ) {
final boolean assignableSuperclass;
if ( descriptor.isInherited() ) {
final String superTypeName = descriptor.getSuperMappingType().getEntityName();
final Class<?> mappedSuperclass = getEntityDescriptor( superTypeName ).getMappedClass();
assignableSuperclass = clazz.isAssignableFrom( mappedSuperclass );
}
else {
assignableSuperclass = false;
}
if ( !assignableSuperclass ) {
results.add( checkQueryableEntityName );
}
}
}
} );
return results.toArray( EMPTY_STRING_ARRAY );
}

@Override
public MappingModelExpressible<?> resolveMappingExpressible(
SqmExpressible<?> sqmExpressible,
Expand Down
Loading