Implemented CollectionElementLoaderByIndex
This commit is contained in:
parent
2cd869c73b
commit
638d1b2d46
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ExecutionContext {
|
||||
|
||||
SharedSessionContractImplementor getSession();
|
||||
|
||||
QueryOptions getQueryOptions();
|
||||
|
|
|
@ -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" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
|
@ -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"/>
|
|
@ -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;
|
||||
|
||||
/**
|
|
@ -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;
|
|
@ -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 {
|
|
@ -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 );
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
|
@ -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 {
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
|
@ -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;
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
-->
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.collection.original">
|
||||
<hibernate-mapping package="org.hibernate.orm.test.collection.original">
|
||||
|
||||
<import class="Permission"/>
|
||||
|
|
@ -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">
|
|
@ -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;
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue