Implemented CollectionElementLoaderByIndex

This commit is contained in:
Andrea Boriero 2020-08-19 13:53:01 +01:00
parent 2cd869c73b
commit 638d1b2d46
22 changed files with 746 additions and 490 deletions

View File

@ -0,0 +1,200 @@
/*
* 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.loader.ast.internal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.LockOptions;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.ast.spi.Loader;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
/**
* @author Andrea Boriero
*/
public class CollectionElementLoaderByIndex implements Loader {
private final PluralAttributeMapping attributeMapping;
private final SelectStatement sqlAst;
private final List<JdbcParameter> jdbcParameters;
private final int baseIndex;
private final int keyJdbcCount;
public CollectionElementLoaderByIndex(
PluralAttributeMapping attributeMapping,
int baseIndex,
LoadQueryInfluencers influencers,
SessionFactoryImplementor sessionFactory) {
this.attributeMapping = attributeMapping;
this.baseIndex = baseIndex;
final ForeignKeyDescriptor keyDescriptor = attributeMapping.getKeyDescriptor();
final CollectionPart indexDescriptor = attributeMapping.getIndexDescriptor();
List<ModelPart> restrictedParts = new ArrayList<>();
restrictedParts.add( keyDescriptor );
if ( indexDescriptor instanceof EntityCollectionPart ) {
EntityIdentifierMapping identifierMapping = ( (EntityCollectionPart) indexDescriptor ).getEntityMappingType()
.getIdentifierMapping();
restrictedParts.add( identifierMapping );
this.keyJdbcCount = keyDescriptor.getJdbcTypeCount( sessionFactory.getTypeConfiguration() ) +
identifierMapping.getJdbcTypeCount( sessionFactory.getTypeConfiguration() );
}
else {
restrictedParts.add( indexDescriptor );
this.keyJdbcCount = keyDescriptor.getJdbcTypeCount( sessionFactory.getTypeConfiguration() ) +
indexDescriptor.getJdbcTypeCount( sessionFactory.getTypeConfiguration() );
}
List<ModelPart> partsToSelect = new ArrayList<>();
partsToSelect.add( attributeMapping.getElementDescriptor() );
this.jdbcParameters = new ArrayList<>( keyJdbcCount );
this.sqlAst = LoaderSelectBuilder.createSelect(
attributeMapping,
partsToSelect,
restrictedParts,
null,
1,
influencers,
LockOptions.READ,
jdbcParameters::add,
sessionFactory
);
}
@Override
public PluralAttributeMapping getLoadable() {
return getAttributeMapping();
}
public PluralAttributeMapping getAttributeMapping() {
return attributeMapping;
}
public SelectStatement getSqlAst() {
return sqlAst;
}
public List<JdbcParameter> getJdbcParameters() {
return jdbcParameters;
}
public Object load(Object key, Object index, SharedSessionContractImplementor session) {
final SessionFactoryImplementor sessionFactory = session.getFactory();
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory )
.translate( sqlAst );
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount );
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
final Iterator<JdbcParameter> paramItr = jdbcParameters.iterator();
attributeMapping.getKeyDescriptor().visitJdbcValues(
key,
Clause.WHERE,
(value, type) -> {
assert paramItr.hasNext();
final JdbcParameter parameter = paramItr.next();
jdbcParameterBindings.addBinding(
parameter,
new JdbcParameterBindingImpl( type, value )
);
},
session
);
attributeMapping.getIndexDescriptor().visitJdbcValues(
incrementIndexByBase( index ),
Clause.WHERE,
(value, type) -> {
assert paramItr.hasNext();
final JdbcParameter parameter = paramItr.next();
jdbcParameterBindings.addBinding(
parameter,
new JdbcParameterBindingImpl( type, value )
);
},
session
);
assert !paramItr.hasNext();
List<Object> list = jdbcServices.getJdbcSelectExecutor().list(
jdbcSelect,
jdbcParameterBindings,
new ExecutionContext() {
@Override
public SharedSessionContractImplementor getSession() {
return session;
}
@Override
public CollectionKey getCollectionKey() {
return null;
}
@Override
public QueryOptions getQueryOptions() {
return QueryOptions.NONE;
}
@Override
public QueryParameterBindings getQueryParameterBindings() {
return QueryParameterBindings.NO_PARAM_BINDINGS;
}
@Override
public Callback getCallback() {
return null;
}
},
RowTransformerPassThruImpl.instance(),
true
);
if ( list.isEmpty() ) {
return null;
}
return list.get( 0 );
}
protected Object incrementIndexByBase(Object index) {
if ( baseIndex != 0 ) {
index = (Integer) index + baseIndex;
}
return index;
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.loader.ast.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@ -33,6 +34,7 @@ import org.hibernate.loader.ast.spi.Loadable;
import org.hibernate.loader.ast.spi.Loader;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
@ -130,6 +132,32 @@ public class LoaderSelectBuilder {
return process.generateSelect();
}
public static SelectStatement createSelect(
Loadable loadable,
List<? extends ModelPart> partsToSelect,
List<ModelPart> restrictedParts,
DomainResult cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer,
SessionFactoryImplementor sessionFactory) {
final LoaderSelectBuilder process = new LoaderSelectBuilder(
sessionFactory,
loadable,
partsToSelect,
restrictedParts,
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
return process.generateSelect();
}
/**
* Create an SQL AST select-statement used for subselect-based CollectionLoader
*
@ -169,13 +197,14 @@ public class LoaderSelectBuilder {
private final SqlAstCreationContext creationContext;
private final Loadable loadable;
private final List<? extends ModelPart> partsToSelect;
private final ModelPart restrictedPart;
private final List<ModelPart> restrictedParts;
private final DomainResult cachedDomainResult;
private final int numberOfKeysToLoad;
private final LoadQueryInfluencers loadQueryInfluencers;
private final LockOptions lockOptions;
private final Consumer<JdbcParameter> jdbcParameterConsumer;
private final EntityGraphTraversalState entityGraphTraversalState;
private boolean forceIdentifierSelection;
private int fetchDepth;
private Map<OrderByFragment, TableGroup> orderByFragments;
@ -184,7 +213,7 @@ public class LoaderSelectBuilder {
SqlAstCreationContext creationContext,
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
List<ModelPart> restrictedParts,
DomainResult cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
@ -193,10 +222,20 @@ public class LoaderSelectBuilder {
this.creationContext = creationContext;
this.loadable = loadable;
this.partsToSelect = partsToSelect;
this.restrictedPart = restrictedPart;
this.restrictedParts = restrictedParts;
this.cachedDomainResult = cachedDomainResult;
this.numberOfKeysToLoad = numberOfKeysToLoad;
this.loadQueryInfluencers = loadQueryInfluencers;
if ( numberOfKeysToLoad > 1 ) {
forceIdentifierSelection = true;
}
else {
for ( ModelPart restrictedPart : restrictedParts ) {
if ( restrictedPart instanceof ForeignKeyDescriptor ) {
forceIdentifierSelection = true;
}
}
}
EntityGraphTraversalState entityGraphTraversalState = null;
if ( loadQueryInfluencers != null ) {
@ -215,6 +254,29 @@ public class LoaderSelectBuilder {
this.jdbcParameterConsumer = jdbcParameterConsumer;
}
private LoaderSelectBuilder(
SqlAstCreationContext creationContext,
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer) {
this(
creationContext,
loadable,
partsToSelect,
Arrays.asList( restrictedPart ),
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
}
private SelectStatement generateSelect() {
final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
@ -227,7 +289,7 @@ public class LoaderSelectBuilder {
new SimpleFromClauseAccessImpl(),
lockOptions,
this::visitFetches,
numberOfKeysToLoad > 1 || restrictedPart instanceof ForeignKeyDescriptor,
forceIdentifierSelection,
creationContext
);
@ -281,19 +343,21 @@ public class LoaderSelectBuilder {
domainResults = Collections.singletonList( domainResult );
}
final int numberOfKeyColumns = restrictedPart.getJdbcTypeCount(
creationContext.getDomainModel().getTypeConfiguration()
);
for ( ModelPart restrictedPart : restrictedParts ) {
final int numberOfRestrictionColumns = restrictedPart.getJdbcTypeCount(
creationContext.getDomainModel().getTypeConfiguration()
);
applyKeyRestriction(
rootQuerySpec,
rootNavigablePath,
rootTableGroup,
restrictedPart,
numberOfKeyColumns,
jdbcParameterConsumer,
sqlAstCreationState
);
applyRestriction(
rootQuerySpec,
rootNavigablePath,
rootTableGroup,
restrictedPart,
numberOfRestrictionColumns,
jdbcParameterConsumer,
sqlAstCreationState
);
}
if ( loadable instanceof PluralAttributeMapping ) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) loadable;
@ -310,60 +374,60 @@ public class LoaderSelectBuilder {
return new SelectStatement( rootQuerySpec, domainResults );
}
private void applyKeyRestriction(
private void applyRestriction(
QuerySpec rootQuerySpec,
NavigablePath rootNavigablePath,
TableGroup rootTableGroup,
ModelPart keyPart,
int numberOfKeyColumns,
ModelPart modelPart,
int numberColumns,
Consumer<JdbcParameter> jdbcParameterConsumer,
LoaderSqlAstCreationState sqlAstCreationState) {
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
if ( numberOfKeyColumns == 1 ) {
assert keyPart instanceof BasicValuedModelPart;
final BasicValuedModelPart basicKeyPart = (BasicValuedModelPart) keyPart;
if ( numberColumns == 1 ) {
modelPart.visitColumns(
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference(
containingTableExpression );
final ColumnReference columnRef =
(ColumnReference) sqlExpressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, columnExpression ),
p -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
creationContext.getSessionFactory()
)
final JdbcMapping jdbcMapping = basicKeyPart.getJdbcMapping();
);
if ( numberOfKeysToLoad == 1 ) {
final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
jdbcParameterConsumer.accept( jdbcParameter );
final String tableExpression = basicKeyPart.getContainingTableExpression();
final String columnExpression = basicKeyPart.getMappedColumnExpression();
final TableReference tableReference = rootTableGroup.resolveTableReference( tableExpression );
final ColumnReference columnRef = (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, columnExpression ),
p -> new ColumnReference(
tableReference,
columnExpression,
false,
jdbcMapping,
creationContext.getSessionFactory()
)
rootQuerySpec.applyPredicate(
new ComparisonPredicate( columnRef, ComparisonOperator.EQUAL, jdbcParameter )
);
}
else {
final InListPredicate predicate = new InListPredicate( columnRef );
for ( int i = 0; i < numberOfKeysToLoad; i++ ) {
for ( int j = 0; j < numberColumns; j++ ) {
final JdbcParameter jdbcParameter = new JdbcParameterImpl( columnRef.getJdbcMapping() );
jdbcParameterConsumer.accept( jdbcParameter );
predicate.addExpression( jdbcParameter );
}
}
rootQuerySpec.applyPredicate( predicate );
}
}
);
if ( numberOfKeysToLoad == 1 ) {
final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
jdbcParameterConsumer.accept( jdbcParameter );
rootQuerySpec.applyPredicate(
new ComparisonPredicate( columnRef, ComparisonOperator.EQUAL, jdbcParameter )
);
}
else {
final InListPredicate predicate = new InListPredicate( columnRef );
for ( int i = 0; i < numberOfKeysToLoad; i++ ) {
for ( int j = 0; j < numberOfKeyColumns; j++ ) {
final JdbcParameter jdbcParameter = new JdbcParameterImpl( columnRef.getJdbcMapping() );
jdbcParameterConsumer.accept( jdbcParameter );
predicate.addExpression( jdbcParameter );
}
}
rootQuerySpec.applyPredicate( predicate );
}
}
else {
final List<ColumnReference> columnReferences = new ArrayList<>( numberOfKeyColumns );
final List<ColumnReference> columnReferences = new ArrayList<>( numberColumns );
keyPart.visitColumns(
modelPart.visitColumns(
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference( containingTableExpression );
columnReferences.add(
@ -381,18 +445,18 @@ public class LoaderSelectBuilder {
}
);
final SqlTuple tuple = new SqlTuple( columnReferences, keyPart );
final SqlTuple tuple = new SqlTuple( columnReferences, modelPart );
final InListPredicate predicate = new InListPredicate( tuple );
for ( int i = 0; i < numberOfKeysToLoad; i++ ) {
final List<JdbcParameter> tupleParams = new ArrayList<>( numberOfKeyColumns );
for ( int j = 0; j < numberOfKeyColumns; j++ ) {
final List<JdbcParameter> tupleParams = new ArrayList<>( numberColumns );
for ( int j = 0; j < numberColumns; j++ ) {
final ColumnReference columnReference = columnReferences.get( j );
final JdbcParameter jdbcParameter = new JdbcParameterImpl( columnReference.getJdbcMapping() );
jdbcParameterConsumer.accept( jdbcParameter );
tupleParams.add( jdbcParameter );
}
final SqlTuple paramTuple = new SqlTuple( tupleParams, keyPart );
final SqlTuple paramTuple = new SqlTuple( tupleParams, modelPart );
predicate.addExpression( paramTuple );
}
@ -719,7 +783,6 @@ public class LoaderSelectBuilder {
final SessionFactoryImplementor sessionFactory = sqlAstCreationContext.getSessionFactory();
assert loadable instanceof PluralAttributeMapping;
assert restrictedPart == null || restrictedPart instanceof ForeignKeyDescriptor;
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();

View File

@ -13,6 +13,7 @@ import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.ColumnConsumer;
@ -243,4 +244,19 @@ public class BasicValuedCollectionPart
public void visitColumns(ColumnConsumer consumer) {
consumer.accept( tableExpression, columnExpression, false, getJdbcMapping() );
}
@Override
public void visitDisassembledJdbcValues(
Object value, Clause clause, JdbcValuesConsumer valuesConsumer, SharedSessionContractImplementor session) {
valuesConsumer.consume( value, getJdbcMapping() );
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
if ( valueConverter != null ) {
//noinspection unchecked
return valueConverter.toRelationalValue( value );
}
return value;
}
}

View File

@ -16,6 +16,7 @@ import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.ColumnConsumer;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
@ -291,4 +292,9 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
public FetchTiming getTiming() {
return FetchTiming.IMMEDIATE;
}
@Override
public void visitColumns(ColumnConsumer consumer) {
getEmbeddableTypeDescriptor().visitColumns( consumer );
}
}

View File

@ -57,6 +57,7 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.loader.ast.internal.CollectionElementLoaderByIndex;
import org.hibernate.loader.ast.internal.CollectionLoaderBatchKey;
import org.hibernate.loader.ast.internal.CollectionLoaderNamedQuery;
import org.hibernate.loader.ast.internal.CollectionLoaderSingleKey;
@ -138,7 +139,6 @@ public abstract class AbstractCollectionPersister
private final String sqlUpdateRowString;
private final String sqlDeleteRowString;
private final String sqlSelectSizeString;
private final String sqlSelectRowByIndexString;
private final String sqlDetectRowByIndexString;
private final String sqlDetectRowByElementString;
@ -246,7 +246,8 @@ public abstract class AbstractCollectionPersister
private final Comparator comparator;
private CollectionLoader collectionLoader;
private volatile CollectionLoader standardCollectionLoader;
private CollectionElementLoaderByIndex collectionElementLoaderByIndex;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// "mapping model"
@ -263,10 +264,10 @@ public abstract class AbstractCollectionPersister
public AbstractCollectionPersister(
Collection collectionBootDescriptor,
CollectionDataAccess cacheAccessStrategy,
PersisterCreationContext pcc) throws MappingException, CacheException {
assert pcc instanceof RuntimeModelCreationContext;
PersisterCreationContext persisterCreationContext) throws MappingException, CacheException {
assert persisterCreationContext instanceof RuntimeModelCreationContext;
final RuntimeModelCreationContext creationContext = (RuntimeModelCreationContext) pcc;
final RuntimeModelCreationContext creationContext = (RuntimeModelCreationContext) persisterCreationContext;
final Value elementBootDescriptor = collectionBootDescriptor.getElement();
final Value indexBootDescriptor = collectionBootDescriptor instanceof IndexedCollection
@ -558,7 +559,6 @@ public abstract class AbstractCollectionPersister
sqlSelectSizeString = generateSelectSizeString( collectionBootDescriptor.isIndexed() && !collectionBootDescriptor.isMap() );
sqlDetectRowByIndexString = generateDetectRowByIndexString();
sqlDetectRowByElementString = generateDetectRowByElementString();
sqlSelectRowByIndexString = generateSelectRowByIndexString();
logStaticSQL();
@ -727,6 +727,14 @@ public abstract class AbstractCollectionPersister
collectionLoader = queryLoaderName == null
? createCollectionLoader( LoadQueryInfluencers.NONE )
: new CollectionLoaderNamedQuery( queryLoaderName, this, attributeMapping );
if ( attributeMapping.getIndexDescriptor() != null ) {
collectionElementLoaderByIndex = new CollectionElementLoaderByIndex(
attributeMapping,
baseIndex,
LoadQueryInfluencers.NONE,
getFactory()
);
}
}
protected void logStaticSQL() {
@ -747,8 +755,6 @@ public abstract class AbstractCollectionPersister
}
}
private volatile CollectionLoader standardCollectionLoader;
@Override
public void initialize(Object key, SharedSessionContractImplementor session) throws HibernateException {
// getAppropriateInitializer( key, session ).initialize( key, session );
@ -763,7 +769,12 @@ public abstract class AbstractCollectionPersister
synchronized (this) {
localCopy = standardCollectionLoader;
if ( localCopy == null ) {
localCopy = createCollectionLoader( LoadQueryInfluencers.NONE );
if ( queryLoaderName != null ) {
localCopy = collectionLoader;
}
else {
localCopy = createCollectionLoader( LoadQueryInfluencers.NONE );
}
standardCollectionLoader = localCopy;
}
}
@ -1190,20 +1201,6 @@ public abstract class AbstractCollectionPersister
.toStatementString();
}
protected String generateSelectRowByIndexString() {
if ( !hasIndex() ) {
return null;
}
return new SimpleSelect( dialect )
.setTableName( getTableName() )
.addCondition( getKeyColumnNames(), "=?" )
.addCondition( getIndexColumnNames(), "=?" )
.addCondition( indexFormulas, "=?" )
.addWhereToken( sqlWhereString )
.addColumns( getElementColumnNames(), elementColumnAliases )
.addColumns( indexFormulas, indexColumnAliases )
.toStatementString();
}
protected String generateDetectRowByElementString() {
return new SimpleSelect( dialect )
@ -2170,40 +2167,7 @@ public abstract class AbstractCollectionPersister
@Override
public Object getElementByIndex(Object key, Object index, SharedSessionContractImplementor session, Object owner) {
try {
final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
PreparedStatement st = jdbcCoordinator
.getStatementPreparer()
.prepareStatement( sqlSelectRowByIndexString );
try {
getKeyType().nullSafeSet( st, key, 1, session );
getIndexType().nullSafeSet( st, incrementIndexByBase( index ), keyColumnNames.length + 1, session );
ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st );
try {
if ( rs.next() ) {
return getElementType().nullSafeGet( rs, elementColumnAliases, session, owner );
}
else {
return null;
}
}
finally {
jdbcCoordinator.getResourceRegistry().release( rs, st );
}
}
finally {
jdbcCoordinator.getResourceRegistry().release( st );
jdbcCoordinator.afterStatementExecution();
}
}
catch ( SQLException sqle ) {
throw getSQLExceptionHelper().convert(
sqle,
"could not read row: " +
MessageHelper.collectionInfoString( this, key, getFactory() ),
sqlSelectSizeString
);
}
return collectionElementLoaderByIndex.load( key, index, session );
}
@Override

View File

@ -2213,41 +2213,45 @@ public abstract class BaseSqmToSqlAstConverter
currentClauseStack::getCurrent
)
);
try {
final TableGroup rootTableGroup = mappingModelExpressable.createRootTableGroup(
pluralPath.getNavigablePath(),
null,
true,
LockOptions.NONE.getLockMode(),
sqlAliasBaseManager,
getSqlExpressionResolver(),
() -> querySpec::applyPredicate,
creationContext
);
final TableGroup rootTableGroup = mappingModelExpressable.createRootTableGroup(
pluralPath.getNavigablePath(),
null,
true,
LockOptions.NONE.getLockMode(),
sqlAliasBaseManager,
getSqlExpressionResolver(),
() -> querySpec::applyPredicate,
creationContext
);
fromClauseIndex.registerTableGroup( pluralPath.getNavigablePath(), rootTableGroup );
fromClauseIndex.registerTableGroup( pluralPath.getNavigablePath(), rootTableGroup );
querySpec.getFromClause().addRoot( rootTableGroup );
querySpec.getFromClause().addRoot( rootTableGroup );
final CollectionPart elementDescriptor = mappingModelExpressable.getElementDescriptor();
final CollectionPart elementDescriptor = mappingModelExpressable.getElementDescriptor();
elementDescriptor.createDomainResult(
pluralPath.getNavigablePath(),
rootTableGroup,
null,
this
);
elementDescriptor.createDomainResult(
pluralPath.getNavigablePath(),
rootTableGroup,
null,
this
);
final Predicate predicate = mappingModelExpressable.getKeyDescriptor().generateJoinPredicate(
getFromClauseAccess().findTableGroup( pluralPath.getNavigablePath().getParent() ),
rootTableGroup,
null,
getSqlExpressionResolver(),
creationContext
);
querySpec.applyPredicate( predicate );
final Predicate predicate = mappingModelExpressable.getKeyDescriptor().generateJoinPredicate(
getFromClauseAccess().findTableGroup( pluralPath.getNavigablePath().getParent() ),
rootTableGroup,
null,
getSqlExpressionResolver(),
creationContext
);
querySpec.applyPredicate( predicate );
}
finally {
processingStateStack.pop();
}
processingStateStack.pop();
return querySpec;
}

View File

@ -19,6 +19,7 @@ import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
* @author Steve Ebersole
*/
public interface ExecutionContext {
SharedSessionContractImplementor getSession();
QueryOptions getQueryOptions();

View File

@ -0,0 +1,281 @@
/*
* 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.collection.backref.map.compkey;
import org.hibernate.Hibernate;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.SerializationHelper;
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.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* BackrefCompositeMapKeyTest implementation. Test access to a composite map-key
* backref via a number of different access methods.
*
* @author Steve Ebersole
*/
@DomainModel(
xmlMappings = (
"org/hibernate/orm/test/collection/backref/map/compkey/Mappings.hbm.xml"
)
)
@SessionFactory
public class BackrefCompositeMapKeyTest {
@Test
public void testOrphanDeleteOnDelete(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
session.flush();
prod.getParts().remove( mapKey );
session.delete( prod );
}
);
scope.inTransaction(
session -> {
assertNull( session.get( Part.class, "Widge" ), "Orphan 'Widge' was not deleted" );
assertNull( session.get( Part.class, "Get" ), "Orphan 'Get' was not deleted" );
assertNull( session.get( Product.class, "Widget" ), "Orphan 'Widget' was not deleted" );
}
);
}
@Test
public void testOrphanDeleteAfterPersist(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
prod.getParts().remove( mapKey );
}
);
scope.inTransaction(
session ->
session.delete( session.get( Product.class, "Widget" ) )
);
}
@Test
public void testOrphanDeleteAfterPersistAndFlush(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
session.flush();
prod.getParts().remove( mapKey );
}
);
scope.inTransaction(
session -> {
assertNull( session.get( Part.class, "Widge" ) );
assertNotNull( session.get( Part.class, "Get" ) );
session.delete( session.get( Product.class, "Widget" ) );
}
);
}
@Test
public void testOrphanDeleteAfterLock(SessionFactoryScope scope) {
Product prod = new Product( "Widget" );
MapKey mapKey = new MapKey( "Top" );
scope.inTransaction(
session -> {
Part part = new Part( "Widge", "part if a Widget" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
}
);
scope.inTransaction(
session -> {
session.lock( prod, LockMode.READ );
prod.getParts().remove( mapKey );
}
);
scope.inTransaction(
session -> {
assertNull( session.get( Part.class, "Widge" ) );
assertNotNull( session.get( Part.class, "Get" ) );
session.delete( session.get( Product.class, "Widget" ) );
}
);
}
@Test
public void testOrphanDeleteOnSaveOrUpdate(SessionFactoryScope scope) {
Product prod = new Product( "Widget" );
MapKey mapKey = new MapKey( "Top" );
scope.inTransaction(
session -> {
Part part = new Part( "Widge", "part if a Widget" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
}
);
prod.getParts().remove( mapKey );
scope.inTransaction(
session ->
session.saveOrUpdate( prod )
);
scope.inTransaction(
session -> {
assertNull( session.get( Part.class, "Widge" ) );
assertNotNull( session.get( Part.class, "Get" ) );
session.delete( session.get( Product.class, "Widget" ) );
}
);
}
@Test
public void testOrphanDeleteOnSaveOrUpdateAfterSerialization(SessionFactoryScope scope) {
Product prod = new Product( "Widget" );
MapKey mapKey = new MapKey( "Top" );
scope.inTransaction(
session -> {
Part part = new Part( "Widge", "part if a Widget" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
}
);
prod.getParts().remove( mapKey );
Product cloned = (Product) SerializationHelper.clone( prod );
scope.inTransaction(
session ->
session.saveOrUpdate( cloned )
);
scope.inTransaction(
session -> {
assertNull( session.get( Part.class, "Widge" ) );
assertNotNull( session.get( Part.class, "Get" ) );
session.delete( session.get( Product.class, "Widget" ) );
}
);
}
@Test
public void testOrphanDelete(SessionFactoryScope scope) {
MapKey mapKey = new MapKey( "Top" );
scope.inTransaction(
session -> {
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
}
);
SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
sessionFactory.getCache().evictEntityRegion( Product.class );
sessionFactory.getCache().evictEntityRegion( Part.class );
scope.inTransaction(
session -> {
Product prod = session.get( Product.class, "Widget" );
assertTrue( Hibernate.isInitialized( prod.getParts() ) );
Part part = session.get( Part.class, "Widge" );
prod.getParts().remove( mapKey );
}
);
sessionFactory.getCache().evictEntityRegion( Product.class );
sessionFactory.getCache().evictEntityRegion( Part.class );
scope.inTransaction(
session -> {
Product prod = session.get( Product.class, "Widget" );
assertTrue( Hibernate.isInitialized( prod.getParts() ) );
assertNull( prod.getParts().get( new MapKey( "Top" ) ) );
assertNotNull( session.get( Part.class, "Get" ) );
session.delete( session.get( Product.class, "Widget" ) );
}
);
}
@Test
public void testOrphanDeleteOnMerge(SessionFactoryScope scope) {
Product prod = new Product( "Widget" );
MapKey mapKey = new MapKey( "Top" );
scope.inTransaction(
session -> {
Part part = new Part( "Widge", "part if a Widget" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
}
);
prod.getParts().remove( mapKey );
scope.inTransaction(
session ->
session.merge( prod )
);
scope.inTransaction(
session -> {
assertNull( session.get( Part.class, "Widge" ) );
assertNotNull( session.get( Part.class, "Get" ) );
session.delete( session.get( Product.class, "Widget" ) );
}
);
}
}

View File

@ -4,7 +4,7 @@
* 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.test.collection.backref.map.compkey;
package org.hibernate.orm.test.collection.backref.map.compkey;
import java.io.Serializable;
/**

View File

@ -15,7 +15,7 @@
a backref. We want to make sure the backref works properly with
the component.
-->
<hibernate-mapping package="org.hibernate.test.collection.backref.map.compkey" default-access="field">
<hibernate-mapping package="org.hibernate.orm.test.collection.backref.map.compkey" default-access="field">
<class name="Product" table="t_product">
<id name="name"/>

View File

@ -4,7 +4,7 @@
* 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.test.collection.backref.map.compkey;
package org.hibernate.orm.test.collection.backref.map.compkey;
import java.io.Serializable;
/**

View File

@ -4,7 +4,7 @@
* 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.test.collection.backref.map.compkey;
package org.hibernate.orm.test.collection.backref.map.compkey;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

View File

@ -4,7 +4,7 @@
* 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.test.collection.original;
package org.hibernate.orm.test.collection.original;
public class Animal {

View File

@ -4,14 +4,12 @@
* 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.test.collection.original;
package org.hibernate.orm.test.collection.original;
import java.sql.SQLException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.engine.spi.SessionImplementor;
@ -19,28 +17,31 @@ import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
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.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gavin King
*/
@RequiresDialectFeature(DialectChecks.SupportsNoColumnInsert.class)
public class CollectionTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "collection/original/UserPermissions.hbm.xml", "collection/original/Zoo.hbm.xml" };
}
@DomainModel(xmlMappings = {
"org/hibernate/orm/test/collection/original/UserPermissions.hbm.xml",
"org/hibernate/orm/test/collection/original/Zoo.hbm.xml",
})
@SessionFactory
public class CollectionTest {
@Test
public void testExtraLazy() throws HibernateException {
inTransaction(
public void testExtraLazy(SessionFactoryScope scope) {
scope.inTransaction(
s -> {
User u = new User( "gavin" );
u.getPermissions().add( new Permission( "obnoxiousness" ) );
@ -50,13 +51,12 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
User u = s.get( User.class, "gavin" );
assertFalse( Hibernate.isInitialized( u.getPermissions() ) );
assertEquals( u.getPermissions().size(), 2 );
assertEquals( 2, u.getPermissions().size() );
assertTrue( u.getPermissions().contains( new Permission( "obnoxiousness" ) ) );
assertFalse( u.getPermissions().contains( new Permission( "silliness" ) ) );
assertNotNull( u.getPermissions().get( 1 ) );
@ -64,7 +64,7 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
assertFalse( Hibernate.isInitialized( u.getPermissions() ) );
assertFalse( Hibernate.isInitialized( u.getSessionData() ) );
assertEquals( u.getSessionData().size(), 1 );
assertEquals( 1, u.getSessionData().size() );
assertTrue( u.getSessionData().containsKey( "foo" ) );
assertFalse( u.getSessionData().containsKey( "bar" ) );
assertTrue( u.getSessionData().containsValue( "foo value" ) );
@ -85,9 +85,9 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
}
@Test
public void testMerge() throws HibernateException, SQLException {
public void testMerge(SessionFactoryScope scope) {
User u = new User( "gavin" );
inTransaction(
scope.inTransaction(
s -> {
u.getPermissions().add( new Permission( "obnoxiousness" ) );
u.getPermissions().add( new Permission( "pigheadedness" ) );
@ -95,7 +95,7 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
User u2 = findUser( s );
u2.setPermissions( null ); //forces one shot delete
@ -105,22 +105,21 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
u.getPermissions().add( new Permission( "silliness" ) );
inTransaction(
scope.inTransaction(
s -> s.merge( u )
);
;
inTransaction(
scope.inTransaction(
s -> {
User u2 = findUser( s );
assertEquals( u2.getPermissions().size(), 3 );
assertEquals( ( (Permission) u2.getPermissions().get( 0 ) ).getType(), "obnoxiousness" );
assertEquals( ( (Permission) u2.getPermissions().get( 2 ) ).getType(), "silliness" );
assertEquals( "obnoxiousness", ( (Permission) u2.getPermissions().get( 0 ) ).getType() );
assertEquals( "silliness", ( (Permission) u2.getPermissions().get( 2 ) ).getType() );
}
);
inTransaction(
scope.inTransaction(
s -> {
User u2 = findUser( s );
s.delete( u2 );
@ -130,8 +129,8 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
}
@Test
public void testFetch() {
inTransaction(
public void testFetch(SessionFactoryScope scope) {
scope.inTransaction(
s -> {
User u = new User( "gavin" );
u.getPermissions().add( new Permission( "obnoxiousness" ) );
@ -142,21 +141,21 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
User u2 = findUser( s );
assertTrue( Hibernate.isInitialized( u2.getEmailAddresses() ) );
assertFalse( Hibernate.isInitialized( u2.getPermissions() ) );
assertEquals( u2.getEmailAddresses().size(), 2 );
assertEquals( 2, u2.getEmailAddresses().size() );
s.delete( u2 );
}
);
}
@Test
public void testUpdateOrder() {
public void testUpdateOrder(SessionFactoryScope scope) {
User u = new User( "gavin" );
inTransaction(
scope.inTransaction(
s -> {
u.getSessionData().put( "foo", "foo value" );
u.getSessionData().put( "bar", "bar value" );
@ -175,7 +174,7 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
u.getEmailAddresses().remove( 0 );
u.getEmailAddresses().remove( 2 );
inTransaction(
scope.inTransaction(
s -> s.update( u )
);
@ -183,18 +182,18 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
u.getEmailAddresses().add( 0, new Email( "gavin@nospam.com" ) );
u.getEmailAddresses().add( new Email( "gavin.king@jboss.com" ) );
inTransaction(
scope.inTransaction(
s -> s.update( u )
);
inTransaction(
scope.inTransaction(
s -> s.delete( u )
);
}
@Test
public void testValueMap() {
inTransaction(
public void testValueMap(SessionFactoryScope scope) {
scope.inTransaction(
s -> {
User u = new User( "gavin" );
u.getSessionData().put( "foo", "foo value" );
@ -206,13 +205,14 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
s.persist( u );
}
);
inTransaction(
scope.inTransaction(
s -> {
User u2 = findUser( s );
// User u2 = (User) s.createCriteria( User.class ).uniqueResult();
assertFalse( Hibernate.isInitialized( u2.getSessionData() ) );
assertEquals( u2.getSessionData().size(), 1 );
assertEquals( u2.getEmailAddresses().size(), 2 );
assertEquals( 1, u2.getSessionData().size() );
assertEquals( 2, u2.getEmailAddresses().size() );
u2.getSessionData().put( "foo", "new foo value" );
u2.getEmailAddresses().set( 1, new Email( "gavin@hibernate.org" ) );
//u2.getEmailAddresses().remove(3);
@ -220,15 +220,15 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
User u2 = findUser( s );
// User u2 = (User) s.createCriteria( User.class ).uniqueResult();
assertFalse( Hibernate.isInitialized( u2.getSessionData() ) );
assertEquals( u2.getSessionData().size(), 1 );
assertEquals( u2.getEmailAddresses().size(), 2 );
assertEquals( u2.getSessionData().get( "foo" ), "new foo value" );
assertEquals( ( (Email) u2.getEmailAddresses().get( 1 ) ).getAddress(), "gavin@hibernate.org" );
assertEquals( 1, u2.getSessionData().size() );
assertEquals( 2, u2.getEmailAddresses().size() );
assertEquals( "new foo value", u2.getSessionData().get( "foo" ) );
assertEquals( "gavin@hibernate.org", ( (Email) u2.getEmailAddresses().get( 1 ) ).getAddress() );
s.delete( u2 );
}
);
@ -244,9 +244,9 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
@Test
@TestForIssue(jiraKey = "HHH-3636")
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollectionInheritance() {
public void testCollectionInheritance(SessionFactoryScope scope) {
Zoo zoo = new Zoo();
inTransaction(
scope.inTransaction(
s -> {
Mammal m = new Mammal();
m.setMammalName( "name1" );
@ -258,9 +258,9 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
Zoo found = (Zoo) s.get( Zoo.class, zoo.getId() );
Zoo found = s.get( Zoo.class, zoo.getId() );
found.getAnimals().size();
s.delete( found );
}

View File

@ -6,7 +6,7 @@
*/
//$Id: Email.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
package org.hibernate.test.collection.original;
package org.hibernate.orm.test.collection.original;
/**

View File

@ -4,7 +4,7 @@
* 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.test.collection.original;
package org.hibernate.orm.test.collection.original;
public class Mammal extends Animal {

View File

@ -6,7 +6,7 @@
*/
//$Id: Permission.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
package org.hibernate.test.collection.original;
package org.hibernate.orm.test.collection.original;
/**

View File

@ -6,7 +6,7 @@
*/
//$Id: User.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
package org.hibernate.test.collection.original;
package org.hibernate.orm.test.collection.original;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

View File

@ -16,7 +16,7 @@
-->
<hibernate-mapping package="org.hibernate.test.collection.original">
<hibernate-mapping package="org.hibernate.orm.test.collection.original">
<import class="Permission"/>

View File

@ -9,7 +9,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.collection.original">
<hibernate-mapping package="org.hibernate.orm.test.collection.original">
<class name="Zoo">
<id name="id" type="long">

View File

@ -4,7 +4,7 @@
* 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.test.collection.original;
package org.hibernate.orm.test.collection.original;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,279 +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.test.collection.backref.map.compkey;
import org.hibernate.Hibernate;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.internal.util.SerializationHelper;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* BackrefCompositeMapKeyTest implementation. Test access to a composite map-key
* backref via a number of different access methods.
*
* @author Steve Ebersole
*/
public class BackrefCompositeMapKeyTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "collection/backref/map/compkey/Mappings.hbm.xml" };
}
@Test
public void testOrphanDeleteOnDelete() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
session.flush();
prod.getParts().remove( mapKey );
session.delete( prod );
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
assertNull( "Orphan 'Widge' was not deleted", session.get(Part.class, "Widge") );
assertNull( "Orphan 'Get' was not deleted", session.get(Part.class, "Get") );
assertNull( "Orphan 'Widget' was not deleted", session.get(Product.class, "Widget") );
t.commit();
session.close();
}
@Test
public void testOrphanDeleteAfterPersist() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
prod.getParts().remove( mapKey );
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
session.delete( session.get(Product.class, "Widget") );
t.commit();
session.close();
}
@Test
public void testOrphanDeleteAfterPersistAndFlush() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
session.flush();
prod.getParts().remove( mapKey );
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
assertNull( session.get(Part.class, "Widge") );
assertNotNull( session.get(Part.class, "Get") );
session.delete( session.get(Product.class, "Widget") );
t.commit();
session.close();
}
@Test
public void testOrphanDeleteAfterLock() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ),part2 );
session.persist( prod );
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
session.lock(prod, LockMode.READ);
prod.getParts().remove(mapKey);
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
assertNull( session.get(Part.class, "Widge") );
assertNotNull( session.get(Part.class, "Get") );
session.delete( session.get(Product.class, "Widget") );
t.commit();
session.close();
}
@Test
public void testOrphanDeleteOnSaveOrUpdate() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
t.commit();
session.close();
prod.getParts().remove( mapKey );
session = openSession();
t = session.beginTransaction();
session.saveOrUpdate(prod);
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
assertNull( session.get(Part.class, "Widge") );
assertNotNull( session.get(Part.class, "Get") );
session.delete( session.get(Product.class, "Widget") );
t.commit();
session.close();
}
@Test
public void testOrphanDeleteOnSaveOrUpdateAfterSerialization() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
t.commit();
session.close();
prod.getParts().remove( mapKey );
prod = (Product) SerializationHelper.clone( prod );
session = openSession();
t = session.beginTransaction();
session.saveOrUpdate(prod);
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
assertNull( session.get(Part.class, "Widge") );
assertNotNull( session.get(Part.class, "Get") );
session.delete( session.get(Product.class, "Widget") );
t.commit();
session.close();
}
@Test
public void testOrphanDelete() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey( "Bottom" ), part2 );
session.persist( prod );
t.commit();
session.close();
sessionFactory().getCache().evictEntityRegion(Product.class);
sessionFactory().getCache().evictEntityRegion(Part.class);
session = openSession();
t = session.beginTransaction();
prod = (Product) session.get(Product.class, "Widget");
assertTrue( Hibernate.isInitialized( prod.getParts() ) );
part = (Part) session.get(Part.class, "Widge");
prod.getParts().remove(mapKey);
t.commit();
session.close();
sessionFactory().getCache().evictEntityRegion( Product.class );
sessionFactory().getCache().evictEntityRegion(Part.class);
session = openSession();
t = session.beginTransaction();
prod = (Product) session.get(Product.class, "Widget");
assertTrue( Hibernate.isInitialized( prod.getParts() ) );
assertNull( prod.getParts().get(new MapKey("Top")));
assertNotNull( session.get(Part.class, "Get") );
session.delete( session.get(Product.class, "Widget") );
t.commit();
session.close();
}
@Test
public void testOrphanDeleteOnMerge() {
Session session = openSession();
Transaction t = session.beginTransaction();
Product prod = new Product( "Widget" );
Part part = new Part( "Widge", "part if a Widget" );
MapKey mapKey = new MapKey( "Top" );
prod.getParts().put( mapKey, part );
Part part2 = new Part( "Get", "another part if a Widget" );
prod.getParts().put( new MapKey("Bottom"), part2 );
session.persist( prod );
t.commit();
session.close();
prod.getParts().remove( mapKey );
session = openSession();
t = session.beginTransaction();
session.merge(prod);
t.commit();
session.close();
session = openSession();
t = session.beginTransaction();
assertNull( session.get(Part.class, "Widge") );
assertNotNull( session.get(Part.class, "Get") );
session.delete( session.get(Product.class, "Widget") );
t.commit();
session.close();
}
}