remove some obsolete and unused code and simplify GeneratedValuesProcessor
This commit is contained in:
parent
39ffcc91f4
commit
fb840ef84f
|
@ -1,238 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.metamodel.internal;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
|
|
||||||
import org.hibernate.EntityNameResolver;
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
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.internal.EntityManagerMessageLogger;
|
|
||||||
import org.hibernate.internal.HEMLogging;
|
|
||||||
import org.hibernate.mapping.Collection;
|
|
||||||
import org.hibernate.mapping.PersistentClass;
|
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
|
||||||
import org.hibernate.persister.spi.PersisterFactory;
|
|
||||||
import org.hibernate.type.EntityType;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class InflightRuntimeMetamodel {
|
|
||||||
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( InflightRuntimeMetamodel.class );
|
|
||||||
|
|
||||||
private final TypeConfiguration typeConfiguration;
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Hibernate metamodel
|
|
||||||
|
|
||||||
private final Map<String, EntityPersister> entityPersisterMap = new ConcurrentHashMap<>();
|
|
||||||
private final Map<Class, String> entityProxyInterfaceMap = new ConcurrentHashMap<>();
|
|
||||||
private final Map<String, CollectionPersister> collectionPersisterMap = new ConcurrentHashMap<>();
|
|
||||||
private final Map<String, Set<String>> collectionRolesByEntityParticipant = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Misc
|
|
||||||
|
|
||||||
private final Map<String, String> nameToImportNameMap = new HashMap<>();
|
|
||||||
private final Set<EntityNameResolver> entityNameResolvers = new CopyOnWriteArraySet<>();
|
|
||||||
private final Map<String, String> imports = new ConcurrentHashMap<>( );
|
|
||||||
|
|
||||||
public InflightRuntimeMetamodel(TypeConfiguration typeConfiguration) {
|
|
||||||
this.typeConfiguration = typeConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void processBootMetaModel(
|
|
||||||
MetadataImplementor bootMetamodel,
|
|
||||||
CacheImplementor cacheImplementor,
|
|
||||||
PersisterFactory persisterFactory,
|
|
||||||
RuntimeModelCreationContext modelCreationContext) {
|
|
||||||
this.imports.putAll( bootMetamodel.getImports() );
|
|
||||||
processBootEntities(
|
|
||||||
bootMetamodel.getEntityBindings(),
|
|
||||||
cacheImplementor,
|
|
||||||
persisterFactory,
|
|
||||||
modelCreationContext
|
|
||||||
);
|
|
||||||
|
|
||||||
processBootCollections(
|
|
||||||
bootMetamodel.getCollectionBindings(),
|
|
||||||
cacheImplementor,
|
|
||||||
persisterFactory,
|
|
||||||
modelCreationContext
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeConfiguration getTypeConfiguration() {
|
|
||||||
return typeConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, EntityPersister> getEntityPersisterMap() {
|
|
||||||
return entityPersisterMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Class, String> getEntityProxyInterfaceMap() {
|
|
||||||
return entityProxyInterfaceMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, CollectionPersister> getCollectionPersisterMap() {
|
|
||||||
return collectionPersisterMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Set<String>> getCollectionRolesByEntityParticipant() {
|
|
||||||
return collectionRolesByEntityParticipant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getNameToImportNameMap() {
|
|
||||||
return nameToImportNameMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<EntityNameResolver> getEntityNameResolvers() {
|
|
||||||
return entityNameResolvers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an entity mapping descriptor based on its Hibernate entity-name
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if the name does not refer to an entity
|
|
||||||
*/
|
|
||||||
public EntityPersister getEntityDescriptor(String entityName) {
|
|
||||||
final EntityPersister entityPersister = entityPersisterMap.get( entityName );
|
|
||||||
if ( entityPersister == null ) {
|
|
||||||
throw new IllegalArgumentException( "Unable to locate persister: " + entityName );
|
|
||||||
}
|
|
||||||
return entityPersister;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find an entity mapping descriptor based on its Hibernate entity-name.
|
|
||||||
*
|
|
||||||
* @apiNote Returns {@code null} rather than throwing exception
|
|
||||||
*/
|
|
||||||
public EntityPersister findEntityDescriptor(String entityName) {
|
|
||||||
return entityPersisterMap.get( entityName );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processBootEntities(
|
|
||||||
java.util.Collection<PersistentClass> entityBindings,
|
|
||||||
CacheImplementor cacheImplementor,
|
|
||||||
PersisterFactory persisterFactory,
|
|
||||||
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 );
|
|
||||||
|
|
||||||
if ( cp.getConcreteProxyClass() != null
|
|
||||||
&& cp.getConcreteProxyClass().isInterface()
|
|
||||||
&& !Map.class.isAssignableFrom( cp.getConcreteProxyClass() )
|
|
||||||
&& cp.getMappedClass() != cp.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 ( log.isDebugEnabled() ) {
|
|
||||||
log.debugf(
|
|
||||||
"Entity [%s] mapped same interface [%s] as class and proxy",
|
|
||||||
cp.getEntityName(),
|
|
||||||
cp.getMappedClass()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final String old = entityProxyInterfaceMap.put( cp.getConcreteProxyClass(), cp.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()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processBootCollections(
|
|
||||||
java.util.Collection<Collection> collectionBindings,
|
|
||||||
CacheImplementor cacheImplementor,
|
|
||||||
PersisterFactory persisterFactory,
|
|
||||||
PersisterCreationContext persisterCreationContext) {
|
|
||||||
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,
|
|
||||||
persisterCreationContext
|
|
||||||
);
|
|
||||||
collectionPersisterMap.put( model.getRole(), persister );
|
|
||||||
Type indexType = persister.getIndexType();
|
|
||||||
if ( indexType != null && indexType.isEntityType() && !indexType.isAnyType() ) {
|
|
||||||
String entityName = ( (EntityType) indexType ).getAssociatedEntityName();
|
|
||||||
Set<String> roles = collectionRolesByEntityParticipant.get( entityName );
|
|
||||||
if ( roles == null ) {
|
|
||||||
roles = new HashSet<>();
|
|
||||||
collectionRolesByEntityParticipant.put( entityName, roles );
|
|
||||||
}
|
|
||||||
roles.add( persister.getRole() );
|
|
||||||
}
|
|
||||||
Type elementType = persister.getElementType();
|
|
||||||
if ( elementType.isEntityType() && !elementType.isAnyType() ) {
|
|
||||||
String entityName = ( (EntityType) elementType ).getAssociatedEntityName();
|
|
||||||
Set<String> roles = collectionRolesByEntityParticipant.get( entityName );
|
|
||||||
if ( roles == null ) {
|
|
||||||
roles = new HashSet<>();
|
|
||||||
collectionRolesByEntityParticipant.put( entityName, roles );
|
|
||||||
}
|
|
||||||
roles.add( persister.getRole() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getImports() {
|
|
||||||
return imports;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.metamodel.mapping;
|
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generalized contract covering an attribute's generation handling
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
@Incubating
|
|
||||||
public interface GeneratedValueResolver {
|
|
||||||
// static GeneratedValueResolver from(
|
|
||||||
// Generator generator,
|
|
||||||
// GenerationTiming requestedTiming,
|
|
||||||
// int dbSelectionPosition) {
|
|
||||||
// assert requestedTiming.isNotNever();
|
|
||||||
//
|
|
||||||
// if ( generator == null || !generator.getGenerationTiming().includes( requestedTiming ) ) {
|
|
||||||
// return NoGeneratedValueResolver.INSTANCE;
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// return generator.generatedByDatabase()
|
|
||||||
// ? new InDatabaseGeneratedValueResolver( requestedTiming, dbSelectionPosition ) // in-db generation (column-default, function, etc)
|
|
||||||
// : new InMemoryGeneratedValueResolver( (BeforeExecutionGenerator) generator, requestedTiming );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// GenerationTiming getGenerationTiming();
|
|
||||||
Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue);
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.metamodel.mapping;
|
|
||||||
|
|
||||||
import org.hibernate.Internal;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.generator.EventType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GeneratedValueResolver impl for in-db generation. It extracts the generated value
|
|
||||||
* from a array of the ResultSet values
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
@Internal
|
|
||||||
public class InDatabaseGeneratedValueResolver implements GeneratedValueResolver {
|
|
||||||
private final EventType eventType;
|
|
||||||
private final int resultPosition;
|
|
||||||
|
|
||||||
public InDatabaseGeneratedValueResolver(EventType eventType, int resultPosition) {
|
|
||||||
this.eventType = eventType;
|
|
||||||
this.resultPosition = resultPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public GenerationTiming getGenerationTiming() {
|
|
||||||
// return timing;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {
|
|
||||||
return row[resultPosition];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.metamodel.mapping;
|
|
||||||
|
|
||||||
import org.hibernate.Internal;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.generator.EventType;
|
|
||||||
import org.hibernate.generator.BeforeExecutionGenerator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GeneratedValueResolver impl for in-memory generation
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
@Internal
|
|
||||||
public class InMemoryGeneratedValueResolver implements GeneratedValueResolver {
|
|
||||||
private final EventType eventType;
|
|
||||||
private final BeforeExecutionGenerator generator;
|
|
||||||
|
|
||||||
public InMemoryGeneratedValueResolver(BeforeExecutionGenerator generator, EventType eventType) {
|
|
||||||
this.generator = generator;
|
|
||||||
this.eventType = eventType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public GenerationTiming getGenerationTiming() {
|
|
||||||
// return generationTiming;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {
|
|
||||||
return generator.generate( session, entity, currentValue, eventType );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.metamodel.mapping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public interface MappingModelVisitor {
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.metamodel.mapping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class MappingModelWalker {
|
|
||||||
}
|
|
|
@ -21,22 +21,19 @@ import org.hibernate.loader.ast.internal.LoaderSelectBuilder;
|
||||||
import org.hibernate.loader.ast.internal.NoCallbackExecutionContext;
|
import org.hibernate.loader.ast.internal.NoCallbackExecutionContext;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.GeneratedValueResolver;
|
|
||||||
import org.hibernate.metamodel.mapping.InDatabaseGeneratedValueResolver;
|
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.sql.ast.Clause;
|
import org.hibernate.sql.ast.Clause;
|
||||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
|
||||||
import static org.hibernate.sql.results.spi.ListResultsConsumer.UniqueSemantic.FILTER;
|
import static org.hibernate.sql.results.spi.ListResultsConsumer.UniqueSemantic.FILTER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for retrieving {@linkplain OnExecutionGenerator
|
* Responsible for retrieving {@linkplain OnExecutionGenerator database-generated}
|
||||||
* database-generated} attribute values after an {@code insert} statement is executed.
|
* attribute values after an {@code insert} or {@code update} statement is executed.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that this class has responsibility for regular attributes of the entity. The
|
* Note that this class has responsibility for regular attributes of the entity. The
|
||||||
* primary key / id attribute is handled separately, being the responsibility of an
|
* primary key / id attribute is handled separately, being the responsibility of an
|
||||||
|
@ -49,7 +46,7 @@ import static org.hibernate.sql.results.spi.ListResultsConsumer.UniqueSemantic.F
|
||||||
@Incubating
|
@Incubating
|
||||||
public class GeneratedValuesProcessor {
|
public class GeneratedValuesProcessor {
|
||||||
private final SelectStatement selectStatement;
|
private final SelectStatement selectStatement;
|
||||||
private final List<GeneratedValueDescriptor> valueDescriptors = new ArrayList<>();
|
private final List<AttributeMapping> generatedValuesToSelect;
|
||||||
private final List<JdbcParameter> jdbcParameters = new ArrayList<>();
|
private final List<JdbcParameter> jdbcParameters = new ArrayList<>();
|
||||||
|
|
||||||
private final EntityMappingType entityDescriptor;
|
private final EntityMappingType entityDescriptor;
|
||||||
|
@ -62,7 +59,7 @@ public class GeneratedValuesProcessor {
|
||||||
this.entityDescriptor = entityDescriptor;
|
this.entityDescriptor = entityDescriptor;
|
||||||
this.sessionFactory = sessionFactory;
|
this.sessionFactory = sessionFactory;
|
||||||
|
|
||||||
final List<AttributeMapping> generatedValuesToSelect = getGeneratedAttributes( entityDescriptor, timing );
|
generatedValuesToSelect = getGeneratedAttributes( entityDescriptor, timing );
|
||||||
if ( generatedValuesToSelect.isEmpty() ) {
|
if ( generatedValuesToSelect.isEmpty() ) {
|
||||||
selectStatement = null;
|
selectStatement = null;
|
||||||
}
|
}
|
||||||
|
@ -82,11 +79,11 @@ public class GeneratedValuesProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find attributes generated by a {@link OnExecutionGenerator},
|
* Find attributes generated by an {@link OnExecutionGenerator}.
|
||||||
* populate the list of {@link GeneratedValueDescriptor}s by side effect, and
|
*
|
||||||
* return a list of {@link AttributeMapping}s.
|
* @return a list of {@link AttributeMapping}s.
|
||||||
*/
|
*/
|
||||||
private List<AttributeMapping> getGeneratedAttributes(EntityMappingType entityDescriptor, EventType timing) {
|
private static List<AttributeMapping> getGeneratedAttributes(EntityMappingType entityDescriptor, EventType timing) {
|
||||||
// todo (6.0): For now, we rely on the entity metamodel as composite attributes report
|
// todo (6.0): For now, we rely on the entity metamodel as composite attributes report
|
||||||
// GenerationTiming.NEVER even if they have attributes that would need generation
|
// GenerationTiming.NEVER even if they have attributes that would need generation
|
||||||
final Generator[] generators = entityDescriptor.getEntityPersister().getEntityMetamodel().getGenerators();
|
final Generator[] generators = entityDescriptor.getEntityPersister().getEntityMetamodel().getGenerators();
|
||||||
|
@ -95,12 +92,7 @@ public class GeneratedValuesProcessor {
|
||||||
final Generator generator = generators[ mapping.getStateArrayPosition() ];
|
final Generator generator = generators[ mapping.getStateArrayPosition() ];
|
||||||
if ( generator != null
|
if ( generator != null
|
||||||
&& generator.generatedOnExecute()
|
&& generator.generatedOnExecute()
|
||||||
&& generator.generatesSometimes() ) {
|
&& generator.getEventTypes().contains(timing) ) {
|
||||||
// this attribute is generated for the timing we are processing...
|
|
||||||
valueDescriptors.add( new GeneratedValueDescriptor(
|
|
||||||
new InDatabaseGeneratedValueResolver( timing, generatedValuesToSelect.size() ),
|
|
||||||
mapping
|
|
||||||
) );
|
|
||||||
generatedValuesToSelect.add( mapping );
|
generatedValuesToSelect.add( mapping );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
@ -114,7 +106,7 @@ public class GeneratedValuesProcessor {
|
||||||
if ( selectStatement != null ) {
|
if ( selectStatement != null ) {
|
||||||
final List<Object[]> results = executeSelect( id, session );
|
final List<Object[]> results = executeSelect( id, session );
|
||||||
assert results.size() == 1;
|
assert results.size() == 1;
|
||||||
setEntityAttributes( entity, state, session, results.get(0) );
|
setEntityAttributes( entity, state, results.get(0) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +117,7 @@ public class GeneratedValuesProcessor {
|
||||||
.buildSelectTranslator( sessionFactory, selectStatement )
|
.buildSelectTranslator( sessionFactory, selectStatement )
|
||||||
.translate( jdbcParamBindings, QueryOptions.NONE );
|
.translate( jdbcParamBindings, QueryOptions.NONE );
|
||||||
return session.getFactory().getJdbcServices().getJdbcSelectExecutor()
|
return session.getFactory().getJdbcServices().getJdbcSelectExecutor()
|
||||||
.list( jdbcSelect, jdbcParamBindings, createExecutionContext( session ), (row) -> row, FILTER );
|
.list( jdbcSelect, jdbcParamBindings, new NoCallbackExecutionContext(session), (row) -> row, FILTER );
|
||||||
}
|
}
|
||||||
|
|
||||||
private JdbcParameterBindings getJdbcParameterBindings(Object id, SharedSessionContractImplementor session) {
|
private JdbcParameterBindings getJdbcParameterBindings(Object id, SharedSessionContractImplementor session) {
|
||||||
|
@ -141,35 +133,12 @@ public class GeneratedValuesProcessor {
|
||||||
return jdbcParamBindings;
|
return jdbcParamBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEntityAttributes(
|
private void setEntityAttributes(Object entity, Object[] state, Object[] selectionResults) {
|
||||||
Object entity,
|
for ( int i = 0; i < generatedValuesToSelect.size(); i++ ) {
|
||||||
Object[] state,
|
final AttributeMapping attribute = generatedValuesToSelect.get( i );
|
||||||
SharedSessionContractImplementor session,
|
final Object generatedValue = selectionResults[i];
|
||||||
Object[] selectionResults) {
|
state[ attribute.getStateArrayPosition() ] = generatedValue;
|
||||||
for ( int i = 0; i < valueDescriptors.size(); i++ ) {
|
attribute.getAttributeMetadata().getPropertyAccess().getSetter().set( entity, generatedValue );
|
||||||
final GeneratedValueDescriptor descriptor = valueDescriptors.get( i );
|
|
||||||
final Object generatedValue =
|
|
||||||
descriptor.resolver.resolveGeneratedValue( selectionResults, entity, session, state[i] );
|
|
||||||
state[ descriptor.attribute.getStateArrayPosition() ] = generatedValue;
|
|
||||||
descriptor.attribute.getAttributeMetadata()
|
|
||||||
.getPropertyAccess()
|
|
||||||
.getSetter()
|
|
||||||
.set( entity, generatedValue );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExecutionContext createExecutionContext(SharedSessionContractImplementor session) {
|
|
||||||
return new NoCallbackExecutionContext( session );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class GeneratedValueDescriptor {
|
|
||||||
public final GeneratedValueResolver resolver;
|
|
||||||
public final AttributeMapping attribute;
|
|
||||||
|
|
||||||
public GeneratedValueDescriptor(GeneratedValueResolver resolver, AttributeMapping attribute) {
|
|
||||||
this.resolver = resolver;
|
|
||||||
this.attribute = attribute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.metamodel.mapping.internal;
|
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.metamodel.UnsupportedMappingException;
|
|
||||||
import org.hibernate.metamodel.mapping.GeneratedValueResolver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class NoGeneratedValueResolver implements GeneratedValueResolver {
|
|
||||||
/**
|
|
||||||
* Singleton access
|
|
||||||
*/
|
|
||||||
public static final NoGeneratedValueResolver INSTANCE = new NoGeneratedValueResolver();
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public GenerationTiming getGenerationTiming() {
|
|
||||||
// return GenerationTiming.NEVER;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {
|
|
||||||
throw new UnsupportedMappingException( "NoGeneratedValueResolver does not support generated values" );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1943,7 +1943,7 @@ public abstract class AbstractEntityPersister
|
||||||
throw new AssertionFailure( "cannot force version increment on non-versioned entity" );
|
throw new AssertionFailure( "cannot force version increment on non-versioned entity" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( entityMetamodel.isVersionGeneratedByDatabase() ) {
|
if ( entityMetamodel.isVersionGeneratedOnExecute() ) {
|
||||||
// the difficulty here is exactly what we update in order to
|
// the difficulty here is exactly what we update in order to
|
||||||
// force the version to be incremented in the db...
|
// force the version to be incremented in the db...
|
||||||
throw new HibernateException( "LockMode.FORCE is currently not supported for generated version properties" );
|
throw new HibernateException( "LockMode.FORCE is currently not supported for generated version properties" );
|
||||||
|
@ -2737,7 +2737,7 @@ public abstract class AbstractEntityPersister
|
||||||
private static final boolean[] SINGLE_TRUE = new boolean[] { true };
|
private static final boolean[] SINGLE_TRUE = new boolean[] { true };
|
||||||
|
|
||||||
public final boolean checkVersion(final boolean[] includeProperty) {
|
public final boolean checkVersion(final boolean[] includeProperty) {
|
||||||
return includeProperty[getVersionProperty()] || entityMetamodel.isVersionGeneratedByDatabase();
|
return includeProperty[getVersionProperty()] || entityMetamodel.isVersionGeneratedOnExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3945,8 +3945,8 @@ public abstract class AbstractEntityPersister
|
||||||
@Override
|
@Override
|
||||||
public boolean isVersionPropertyGenerated() {
|
public boolean isVersionPropertyGenerated() {
|
||||||
return isVersioned()
|
return isVersioned()
|
||||||
&& ( getEntityMetamodel().isVersionGeneratedByDatabase()
|
&& ( getEntityMetamodel().isVersionGeneratedOnExecute()
|
||||||
|| getEntityMetamodel().isVersionGeneratedInMemory() );
|
|| getEntityMetamodel().isVersionGeneratedBeforeExecute() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.persister.spi;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Where to begin... :)
|
|
||||||
*
|
|
||||||
* This gets to the internal concept of 2-phase loading of entity data and how specifically it is done. Essentially
|
|
||||||
* for composite values, the process of hydration results in a tuple array comprising the composition "atomic" values.
|
|
||||||
* For example, a Name component's hydrated state might look like {@code ["Steve", "L", "Ebersole"]}.
|
|
||||||
*
|
|
||||||
* There are times when we need to be able to extract individual pieces out of the hydrated tuple array. For example,
|
|
||||||
* for an entity with a composite identifier part of which is an association (a key-many-to-one) we often need to
|
|
||||||
* attempt 2-phase processing on the association portion of the identifier's hydrated tuple array.
|
|
||||||
*
|
|
||||||
* This contract allows us access to portions of the hydrated tuple state.
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public interface HydratedCompoundValueHandler {
|
|
||||||
Object extract(Object hydratedState);
|
|
||||||
void inject(Object hydratedState, Object value);
|
|
||||||
}
|
|
|
@ -689,12 +689,12 @@ public class EntityMetamodel implements Serializable {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVersionGeneratedByDatabase() {
|
public boolean isVersionGeneratedOnExecute() {
|
||||||
final Generator strategy = generators[ versionPropertyIndex ];
|
final Generator strategy = generators[ versionPropertyIndex ];
|
||||||
return strategy != null && strategy.generatesSometimes() && strategy.generatedOnExecute();
|
return strategy != null && strategy.generatesSometimes() && strategy.generatedOnExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVersionGeneratedInMemory() {
|
public boolean isVersionGeneratedBeforeExecute() {
|
||||||
final Generator strategy = generators[ versionPropertyIndex ];
|
final Generator strategy = generators[ versionPropertyIndex ];
|
||||||
return strategy != null && strategy.generatesSometimes() && !strategy.generatedOnExecute();
|
return strategy != null && strategy.generatesSometimes() && !strategy.generatedOnExecute();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue