Fix PluralAttributMappingImpl issue when both index and element of a Map are Entity types

This commit is contained in:
Andrea Boriero 2020-08-20 14:59:28 +01:00
parent 82de2b0a3f
commit 92aa612f4e
6 changed files with 326 additions and 203 deletions

View File

@ -29,7 +29,6 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor; import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
import org.hibernate.metamodel.mapping.CollectionMappingType; import org.hibernate.metamodel.mapping.CollectionMappingType;
import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.ColumnConsumer;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
@ -42,9 +41,7 @@ import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
import org.hibernate.metamodel.mapping.ordering.OrderByFragmentTranslator; import org.hibernate.metamodel.mapping.ordering.OrderByFragmentTranslator;
import org.hibernate.metamodel.mapping.ordering.TranslationContext; import org.hibernate.metamodel.mapping.ordering.TranslationContext;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.collection.AbstractCollectionPersister;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.Joinable;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
@ -112,7 +109,8 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
private final IndexMetadata indexMetadata; private final IndexMetadata indexMetadata;
private ForeignKeyDescriptor fkDescriptor; private ForeignKeyDescriptor fkDescriptor;
private ForeignKeyDescriptor manyToManyFkDescriptor; private ForeignKeyDescriptor elementFkDescriptor;
private ForeignKeyDescriptor indexFkDescriptor;
private OrderByFragment orderByFragment; private OrderByFragment orderByFragment;
private OrderByFragment manyToManyOrderByFragment; private OrderByFragment manyToManyOrderByFragment;
@ -243,68 +241,34 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
Property bootProperty, Property bootProperty,
Collection bootDescriptor, Collection bootDescriptor,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
if ( collectionDescriptor.getElementType() instanceof EntityType final Dialect dialect = creationProcess.getCreationContext()
|| collectionDescriptor.getIndexType() instanceof EntityType ) { .getSessionFactory()
.getJdbcServices()
.getDialect();
if ( collectionDescriptor.getElementType() instanceof EntityType ) {
creationProcess.registerForeignKeyPostInitCallbacks( creationProcess.registerForeignKeyPostInitCallbacks(
() -> { () -> {
final EntityPersister associatedEntityDescriptor;
final ModelPart fkTargetPart;
final Value fkBootDescriptorSource;
if ( collectionDescriptor.getElementType() instanceof EntityType ) {
final EntityType elementEntityType = (EntityType) collectionDescriptor.getElementType();
associatedEntityDescriptor = creationProcess.getEntityPersister( elementEntityType.getAssociatedEntityName() );
if ( ( (AbstractEntityPersister) associatedEntityDescriptor ).getTableName()
.equals( ( (AbstractCollectionPersister) collectionDescriptor ).getTableName() ) ) {
fkTargetPart = creationProcess
.getEntityPersister( bootDescriptor.getOwner().getEntityName() )
.getIdentifierMapping();
}
else {
fkTargetPart = associatedEntityDescriptor.getIdentifierMapping();
}
fkBootDescriptorSource = bootDescriptor.getElement();
}
else {
assert collectionDescriptor.getIndexType() != null;
assert bootDescriptor instanceof IndexedCollection;
final EntityType indexEntityType = (EntityType) collectionDescriptor.getIndexType(); elementFkDescriptor = createForeignKeyDescriptor(
associatedEntityDescriptor = creationProcess.getEntityPersister( indexEntityType.getAssociatedEntityName() ); bootDescriptor.getElement(),
fkTargetPart = indexEntityType.isReferenceToPrimaryKey() (EntityType) collectionDescriptor.getElementType(),
? associatedEntityDescriptor.getIdentifierMapping() creationProcess,
: associatedEntityDescriptor.findSubPart( indexEntityType.getRHSUniqueKeyPropertyName() ); dialect
fkBootDescriptorSource = ( (IndexedCollection) bootDescriptor ).getIndex(); );
} return true;
}
);
}
if ( collectionDescriptor.getIndexType() instanceof EntityType ) {
creationProcess.registerForeignKeyPostInitCallbacks(
() -> {
indexFkDescriptor = createForeignKeyDescriptor(
( (IndexedCollection) bootDescriptor ).getIndex(),
(EntityType) collectionDescriptor.getIndexType(),
creationProcess,
dialect
);
final Dialect dialect = creationProcess.getCreationContext()
.getSessionFactory()
.getJdbcServices()
.getDialect();
if ( fkTargetPart instanceof BasicValuedModelPart ) {
final BasicValuedModelPart basicFkTargetPart = (BasicValuedModelPart) fkTargetPart;
final Joinable collectionDescriptorAsJoinable = (Joinable) collectionDescriptor;
manyToManyFkDescriptor = new SimpleForeignKeyDescriptor(
collectionDescriptorAsJoinable.getTableName(),
fkBootDescriptorSource.getColumnIterator().next().getText( dialect ),
basicFkTargetPart.getContainingTableExpression(),
basicFkTargetPart.getMappedColumnExpression(),
basicFkTargetPart.getJdbcMapping()
);
}
else if ( fkTargetPart instanceof EmbeddableValuedModelPart ) {
manyToManyFkDescriptor = MappingModelCreationHelper.buildEmbeddedForeignKeyDescriptor(
(EmbeddableValuedModelPart) fkTargetPart,
this,
fkBootDescriptorSource,
dialect,
creationProcess
);
}
else {
throw new NotYetImplementedFor6Exception(
"Support for composite foreign keys not yet implemented : " + collectionDescriptor.getRole()
);
}
return true; return true;
} }
); );
@ -348,6 +312,44 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
} }
} }
private ForeignKeyDescriptor createForeignKeyDescriptor(
Value fkBootDescriptorSource,
EntityType entityType,
MappingModelCreationProcess creationProcess,
Dialect dialect) {
final EntityPersister associatedEntityDescriptor = creationProcess.getEntityPersister( entityType.getAssociatedEntityName() );
final ModelPart fkTargetPart = entityType.isReferenceToPrimaryKey()
? associatedEntityDescriptor.getIdentifierMapping()
: associatedEntityDescriptor.findSubPart( entityType.getRHSUniqueKeyPropertyName() );
if ( fkTargetPart instanceof BasicValuedModelPart ) {
final BasicValuedModelPart basicFkTargetPart = (BasicValuedModelPart) fkTargetPart;
final Joinable collectionDescriptorAsJoinable = (Joinable) collectionDescriptor;
return new SimpleForeignKeyDescriptor(
collectionDescriptorAsJoinable.getTableName(),
fkBootDescriptorSource.getColumnIterator().next().getText( dialect ),
basicFkTargetPart.getContainingTableExpression(),
basicFkTargetPart.getMappedColumnExpression(),
basicFkTargetPart.getJdbcMapping()
);
}
else if ( fkTargetPart instanceof EmbeddableValuedModelPart ) {
return MappingModelCreationHelper.buildEmbeddedForeignKeyDescriptor(
(EmbeddableValuedModelPart) fkTargetPart,
this,
fkBootDescriptorSource,
dialect,
creationProcess
);
}
else {
throw new NotYetImplementedFor6Exception(
"Support for composite foreign keys not yet implemented : " + collectionDescriptor
.getRole()
);
}
}
@Override @Override
public NavigableRole getNavigableRole() { public NavigableRole getNavigableRole() {
return getCollectionDescriptor().getNavigableRole(); return getCollectionDescriptor().getNavigableRole();
@ -698,68 +700,121 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
creationContext.getSessionFactory() creationContext.getSessionFactory()
); );
final EntityMappingType elementDescriptorEntityMappingType;
if ( elementDescriptor instanceof EntityCollectionPart ) {
elementDescriptorEntityMappingType = ( (EntityCollectionPart) elementDescriptor ).getEntityMappingType();
}
else {
elementDescriptorEntityMappingType = null;
}
final EntityMappingType indexDescriptorEntityMappingType;
if ( indexDescriptor instanceof EntityCollectionPart ) {
indexDescriptorEntityMappingType = ( (EntityCollectionPart) indexDescriptor ).getEntityMappingType();
}
else {
indexDescriptorEntityMappingType = null;
}
final BiFunction<String, TableGroup, TableReferenceJoin> tableReferenceJoinCreator; final BiFunction<String, TableGroup, TableReferenceJoin> tableReferenceJoinCreator;
final java.util.function.Predicate<String> tableReferenceJoinNameChecker;
if ( elementDescriptor instanceof EntityCollectionPart || indexDescriptor instanceof EntityCollectionPart ) {
final EntityCollectionPart entityPartDescriptor;
if ( elementDescriptor instanceof EntityCollectionPart ) {
entityPartDescriptor = (EntityCollectionPart) elementDescriptor;
}
else {
entityPartDescriptor = (EntityCollectionPart) indexDescriptor;
}
final EntityMappingType mappingType = entityPartDescriptor.getEntityMappingType(); final java.util.function.Predicate<String> tableReferenceJoinNameChecker = createTableReferenceJoinNameChecker(
final TableReference associatedPrimaryTable = mappingType.createPrimaryTableReference( elementDescriptorEntityMappingType,
indexDescriptorEntityMappingType
);
final TableReference elementAssociatedPrimaryTable;
final Function<TableGroup, TableReferenceJoin> elementTableGroupFinalizer;
// todo (6.0) : not sure it is
final boolean elementUseInnerJoin;
if ( elementDescriptorEntityMappingType != null ) {
elementUseInnerJoin = canUseInnerJoin && !getAttributeMetadataAccess()
.resolveAttributeMetadata( elementDescriptorEntityMappingType ).isNullable();
final SqlAstJoinType joinType = elementUseInnerJoin
? SqlAstJoinType.INNER
: SqlAstJoinType.LEFT;
elementAssociatedPrimaryTable = elementDescriptorEntityMappingType.createPrimaryTableReference(
sqlAliasBase, sqlAliasBase,
sqlExpressionResolver, sqlExpressionResolver,
creationContext creationContext
); );
final boolean useInnerJoin = canUseInnerJoin && !getAttributeMetadataAccess() elementTableGroupFinalizer = createTableGroupFinalizer(
.resolveAttributeMetadata( null ).isNullable(); sqlExpressionResolver,
creationContext,
collectionTableReference,
elementAssociatedPrimaryTable,
joinType,
elementFkDescriptor
);
}
else {
elementAssociatedPrimaryTable = null;
elementTableGroupFinalizer = null;
elementUseInnerJoin = false;
}
final Function<TableGroup,TableReferenceJoin> tableGroupFinalizer = tableGroup -> { TableReference indexAssociatedPrimaryTable;
final SqlAstJoinType joinType = useInnerJoin final Function<TableGroup, TableReferenceJoin> indexTableGroupFinalizer;
? SqlAstJoinType.INNER final boolean indexUseInnerJoin;
: SqlAstJoinType.LEFT; if ( indexDescriptorEntityMappingType != null ) {
final TableReferenceJoin associationJoin = new TableReferenceJoin( indexUseInnerJoin = canUseInnerJoin && !getAttributeMetadataAccess()
joinType, .resolveAttributeMetadata( indexDescriptorEntityMappingType ).isNullable();
associatedPrimaryTable, final SqlAstJoinType joinType = indexUseInnerJoin
manyToManyFkDescriptor.generateJoinPredicate( ? SqlAstJoinType.INNER
collectionTableReference, : SqlAstJoinType.LEFT;
associatedPrimaryTable, indexAssociatedPrimaryTable = indexDescriptorEntityMappingType.createPrimaryTableReference(
joinType, sqlAliasBase,
sqlExpressionResolver, sqlExpressionResolver,
creationContext creationContext
) );
);
return associationJoin;
};
tableReferenceJoinNameChecker = mappingType::containsTableReference; indexTableGroupFinalizer = createTableGroupFinalizer(
sqlExpressionResolver,
creationContext,
collectionTableReference,
indexAssociatedPrimaryTable,
joinType,
indexFkDescriptor
);
}
else {
indexAssociatedPrimaryTable = null;
indexTableGroupFinalizer = null;
indexUseInnerJoin = false;
}
if ( elementDescriptorEntityMappingType != null || indexDescriptorEntityMappingType != null ) {
tableReferenceJoinCreator = (tableExpression, tableGroup) -> { tableReferenceJoinCreator = (tableExpression, tableGroup) -> {
if ( associatedPrimaryTable.getTableExpression().equals( tableExpression ) ) { if ( elementDescriptorEntityMappingType != null
TableReferenceJoin tableReferenceJoin = tableGroupFinalizer.apply( tableGroup ); && elementDescriptorEntityMappingType.containsTableReference( tableExpression ) ) {
return tableReferenceJoin; return createTableReferenceJoin(
sqlExpressionResolver,
creationContext,
sqlAliasBase,
elementDescriptorEntityMappingType,
elementAssociatedPrimaryTable,
elementTableGroupFinalizer,
elementUseInnerJoin,
tableExpression,
tableGroup
);
} }
else { else if ( indexDescriptorEntityMappingType != null
StandardTableGroup standardTableGroup = (StandardTableGroup) tableGroup; && indexDescriptorEntityMappingType.containsTableReference( tableExpression ) ) {
if ( standardTableGroup.getTableReferenceJoins().isEmpty() ) { return createTableReferenceJoin(
TableReferenceJoin tableReferenceJoin = tableGroupFinalizer.apply( tableGroup ); sqlExpressionResolver,
standardTableGroup.addTableReferenceJoin( tableReferenceJoin ); creationContext,
} sqlAliasBase,
indexDescriptorEntityMappingType,
indexAssociatedPrimaryTable,
indexTableGroupFinalizer,
indexUseInnerJoin,
tableExpression,
tableGroup
);
} }
return mappingType.createTableReferenceJoin( throw new IllegalStateException( "could not create join for table `" + tableExpression + "`" );
tableExpression,
sqlAliasBase,
associatedPrimaryTable,
useInnerJoin,
sqlExpressionResolver,
creationContext
);
}; };
} }
else { else {
@ -768,7 +823,6 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
"element-collection cannot contain joins : " + collectionTableReference.getTableExpression() + " -> " + tableExpression "element-collection cannot contain joins : " + collectionTableReference.getTableExpression() + " -> " + tableExpression
); );
}; };
tableReferenceJoinNameChecker = s -> false;
} }
final StandardTableGroup tableGroup = new StandardTableGroup( final StandardTableGroup tableGroup = new StandardTableGroup(
@ -785,6 +839,75 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
return tableGroup; return tableGroup;
} }
private TableReferenceJoin createTableReferenceJoin(
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext,
SqlAliasBase sqlAliasBase,
EntityMappingType elementDescriptorEntityMappingType,
TableReference elementAssociatedPrimaryTable,
Function<TableGroup, TableReferenceJoin> elementTableGroupFinalizer,
boolean useInnerJoin,
String tableExpression, TableGroup tableGroup) {
if ( elementAssociatedPrimaryTable.getTableExpression().equals( tableExpression ) ) {
TableReferenceJoin tableReferenceJoin = elementTableGroupFinalizer.apply( tableGroup );
return tableReferenceJoin;
}
else {
StandardTableGroup standardTableGroup = (StandardTableGroup) tableGroup;
if ( standardTableGroup.getTableReferenceJoins().isEmpty() ) {
TableReferenceJoin tableReferenceJoin = elementTableGroupFinalizer.apply( tableGroup );
standardTableGroup.addTableReferenceJoin( tableReferenceJoin );
}
}
return elementDescriptorEntityMappingType.createTableReferenceJoin(
tableExpression,
sqlAliasBase,
elementAssociatedPrimaryTable,
useInnerJoin,
sqlExpressionResolver,
creationContext
);
}
private Function<TableGroup, TableReferenceJoin> createTableGroupFinalizer(
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext,
TableReference collectionTableReference,
TableReference elementAssociatedPrimaryTable,
SqlAstJoinType joinType,
ForeignKeyDescriptor elementFkDescriptor) {
return tableGroup -> {
final TableReferenceJoin associationJoin = new TableReferenceJoin(
joinType,
elementAssociatedPrimaryTable,
elementFkDescriptor.generateJoinPredicate(
collectionTableReference,
elementAssociatedPrimaryTable,
joinType,
sqlExpressionResolver,
creationContext
)
);
return associationJoin;
};
}
private java.util.function.Predicate<String> createTableReferenceJoinNameChecker(
EntityMappingType elementDescriptorEntityMappingType,
EntityMappingType indexDescriptorEntityMappingType) {
return tableExpression -> {
if ( elementDescriptorEntityMappingType != null
&& elementDescriptorEntityMappingType.containsTableReference( tableExpression ) ) {
return true;
}
if ( indexDescriptorEntityMappingType != null
&& indexDescriptorEntityMappingType.containsTableReference( tableExpression ) ) {
return true;
}
return false;
};
}
@Override @Override
public TableGroup createRootTableGroup( public TableGroup createRootTableGroup(

View File

@ -0,0 +1,88 @@
/*
* 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.map.hhh7557;
import java.util.HashMap;
import java.util.List;
import org.hibernate.Session;
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.assertEquals;
/**
* @author Elizabeth Chatman
* @author Steve Ebersole
*/
@DomainModel(
annotatedClasses = {
MapValue.class, MapKey.class, MapHolder.class
}
)
@SessionFactory
public class EntityMapTest {
@Test
public void testInsertIntoMap(SessionFactoryScope scope) {
// Session 1: Insert 3 values into the map
scope.inTransaction(
session -> {
MapHolder mapHolder = new MapHolder();
mapHolder.setMap( new HashMap<>() );
addMapEntry( session, mapHolder, "A", "1" );
addMapEntry( session, mapHolder, "B", "2" );
addMapEntry( session, mapHolder, "C", "3" );
session.save( mapHolder );
// Verify there are 3 entries in the map
assertEquals( 3, mapHolder.getMap().size() );
}
);
// Session 2: Add a 4th value to the map
scope.inTransaction(
session -> {
MapHolder mapHolder = getMapHolder( session );
assertEquals( 3, mapHolder.getMap().size() );
System.out.println( "Got MapHolder; checked map size -----" );
addMapEntry( session, mapHolder, "D", "4" );
// Verify there are 4 entries in the map
assertEquals( 4, mapHolder.getMap().size() );
}
);
// Session 3: Count the entries in the map
scope.inTransaction(
session -> {
MapHolder mapHolder = getMapHolder( session );
// Fails here (expected:<4> but was:<1>)
assertEquals( 4, mapHolder.getMap().size() );
}
);
}
private void addMapEntry(Session session, MapHolder mapHolder, String key, String value) {
MapValue entityValue = new MapValue( value );
session.save( entityValue );
MapKey entityKey = new MapKey( key, entityValue );
session.save( entityKey );
mapHolder.getMap().put( entityKey, entityValue );
}
private MapHolder getMapHolder(Session session) {
List mapHolders = session.createQuery( "select distinct mh from MapHolder mh" ).list();
assertEquals( 1, mapHolders.size() );
return (MapHolder) mapHolders.get( 0 );
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.collection.map.hhh7557; package org.hibernate.orm.test.collection.map.hhh7557;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.collection.map.hhh7557; package org.hibernate.orm.test.collection.map.hhh7557;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.collection.map.hhh7557; package org.hibernate.orm.test.collection.map.hhh7557;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -1,88 +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.map.hhh7557;
import java.util.HashMap;
import java.util.List;
import org.hibernate.Session;
import org.junit.Assert;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
* @author Elizabeth Chatman
* @author Steve Ebersole
*/
public class EntityMapTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {MapValue.class, MapKey.class, MapHolder.class};
}
@Test
public void testInsertIntoMap() throws Exception {
{
// Session 1: Insert 3 values into the map
Session session = openSession();
session.beginTransaction();
MapHolder mapHolder = new MapHolder();
mapHolder.setMap( new HashMap<MapKey, MapValue>() );
addMapEntry( session, mapHolder, "A", "1" );
addMapEntry( session, mapHolder, "B", "2" );
addMapEntry( session, mapHolder, "C", "3" );
session.save( mapHolder );
// Verify there are 3 entries in the map
Assert.assertEquals( 3, mapHolder.getMap().size() );
session.getTransaction().commit();
session.close();
}
{
// Session 2: Add a 4th value to the map
Session session = openSession();
session.beginTransaction();
MapHolder mapHolder = getMapHolder( session );
System.out.println( "Got MapHolder; checking map size -----" );
Assert.assertEquals( 3, mapHolder.getMap().size() );
System.out.println( "Got MapHolder; checked map size -----" );
addMapEntry( session, mapHolder, "D", "4" );
// Verify there are 4 entries in the map
Assert.assertEquals( 4, mapHolder.getMap().size() );
session.getTransaction().commit();
session.close();
}
{
// Session 3: Count the entries in the map
Session session = openSession();
session.beginTransaction();
MapHolder mapHolder = getMapHolder( session );
// Fails here (expected:<4> but was:<1>)
Assert.assertEquals( 4, mapHolder.getMap().size() );
session.getTransaction().commit();
session.close();
}
}
private void addMapEntry(Session session, MapHolder mapHolder, String key, String value) {
System.out.println( "Inserting (" + key + "," + value + ") into map" );
MapValue entityValue = new MapValue( value );
session.save( entityValue );
MapKey entityKey = new MapKey( key, entityValue );
session.save( entityKey );
mapHolder.getMap().put( entityKey, entityValue );
}
private MapHolder getMapHolder(Session session) {
List mapHolders = session.createQuery( "select distinct mh from MapHolder mh" ).list();
Assert.assertEquals( 1, mapHolders.size() );
return (MapHolder) mapHolders.get( 0 );
}
}