EntityValuedPathInterpretation fix TableGroup resolution for implicit join e.g or
This commit is contained in:
parent
0bd2c32f76
commit
fc6f515407
|
@ -68,7 +68,10 @@ public interface EntityValuedModelPart extends FetchableContainer {
|
|||
Consumer<JdbcMapping> action,
|
||||
Clause clause,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
getEntityMappingType().visitJdbcTypes( action, clause, typeConfiguration );
|
||||
getEntityMappingType().getAttributeMappings().forEach(
|
||||
attributeMapping ->
|
||||
attributeMapping.visitJdbcTypes( action, clause, typeConfiguration )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,6 +94,8 @@ public interface EntityValuedModelPart extends FetchableContainer {
|
|||
Clause clause,
|
||||
JdbcValuesConsumer consumer,
|
||||
SharedSessionContractImplementor session) {
|
||||
getEntityMappingType().visitJdbcValues( value, clause, consumer, session );
|
||||
}
|
||||
getEntityMappingType().getAttributeMappings().forEach(
|
||||
attributeMapping ->
|
||||
attributeMapping.visitJdbcValues( value, clause, consumer, session )
|
||||
); }
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public abstract class AbstractDomainPath implements DomainPath {
|
|||
SessionFactoryImplementor sessionFactory,
|
||||
SqlExpressionResolver sqlExprResolver) {
|
||||
if ( referenceModelPart instanceof BasicValuedModelPart ) {
|
||||
assSortSpecification(
|
||||
addSortSpecification(
|
||||
(BasicValuedModelPart) referenceModelPart,
|
||||
ast,
|
||||
tableGroup,
|
||||
|
@ -92,7 +92,7 @@ public abstract class AbstractDomainPath implements DomainPath {
|
|||
);
|
||||
}
|
||||
else if ( referenceModelPart instanceof EmbeddableValuedModelPart ) {
|
||||
assSortSpecification(
|
||||
addSortSpecification(
|
||||
(EmbeddableValuedModelPart) referenceModelPart,
|
||||
ast,
|
||||
tableGroup,
|
||||
|
@ -105,11 +105,12 @@ public abstract class AbstractDomainPath implements DomainPath {
|
|||
);
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedFor6Exception( "Ordering for " + getReferenceModelPart() + "not yet supported" );
|
||||
// sure it can happen
|
||||
throw new NotYetImplementedFor6Exception( "Ordering for " + getReferenceModelPart() + "not supported" );
|
||||
}
|
||||
}
|
||||
|
||||
private void assSortSpecification(
|
||||
private void addSortSpecification(
|
||||
EmbeddableValuedModelPart embeddableValuedModelPart,
|
||||
QuerySpec ast,
|
||||
TableGroup tableGroup,
|
||||
|
@ -151,7 +152,7 @@ public abstract class AbstractDomainPath implements DomainPath {
|
|||
else {
|
||||
ModelPart subPart = embeddableValuedModelPart.findSubPart( modelPartName, null );
|
||||
assert subPart instanceof BasicValuedModelPart;
|
||||
assSortSpecification(
|
||||
addSortSpecification(
|
||||
(BasicValuedModelPart) subPart,
|
||||
ast,
|
||||
tableGroup,
|
||||
|
@ -162,7 +163,7 @@ public abstract class AbstractDomainPath implements DomainPath {
|
|||
}
|
||||
}
|
||||
|
||||
private void assSortSpecification(
|
||||
private void addSortSpecification(
|
||||
BasicValuedModelPart basicValuedPart,
|
||||
QuerySpec ast,
|
||||
TableGroup tableGroup,
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.hibernate.internal.util.collections.StandardStack;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
|
@ -380,9 +381,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
final List<SqmCteTableColumn> sqmCteColumns = sqmCteTable.getColumns();
|
||||
final List<CteColumn> sqlCteColumns = new ArrayList<>( sqmCteColumns.size() );
|
||||
|
||||
for ( int i = 0; i < sqmCteColumns.size(); i++ ) {
|
||||
final SqmCteTableColumn sqmCteTableColumn = sqmCteColumns.get( i );
|
||||
|
||||
for ( final SqmCteTableColumn sqmCteTableColumn : sqmCteColumns ) {
|
||||
sqlCteColumns.add(
|
||||
new CteColumn(
|
||||
sqmCteTableColumn.getColumnName(),
|
||||
|
@ -1148,11 +1147,20 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
SqmParameter expression,
|
||||
MappingModelExpressable valueMapping,
|
||||
Consumer<JdbcParameter> jdbcParameterConsumer) {
|
||||
valueMapping.visitJdbcTypes(
|
||||
jdbcMapping -> jdbcParameterConsumer.accept( new JdbcParameterImpl( jdbcMapping ) ),
|
||||
getCurrentClauseStack().getCurrent(),
|
||||
getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
if ( valueMapping instanceof EntityValuedModelPart ) {
|
||||
( (EntityValuedModelPart) valueMapping ).getEntityMappingType().getIdentifierMapping().visitJdbcTypes(
|
||||
jdbcMapping -> jdbcParameterConsumer.accept( new JdbcParameterImpl( jdbcMapping ) ),
|
||||
getCurrentClauseStack().getCurrent(),
|
||||
getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
else {
|
||||
valueMapping.visitJdbcTypes(
|
||||
jdbcMapping -> jdbcParameterConsumer.accept( new JdbcParameterImpl( jdbcMapping ) ),
|
||||
getCurrentClauseStack().getCurrent(),
|
||||
getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,11 +6,26 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.sql.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
|
||||
/**
|
||||
* @author Koen Aers
|
||||
|
@ -19,29 +34,131 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
|
||||
public static <T> EntityValuedPathInterpretation<T> from(
|
||||
SqmEntityValuedSimplePath<T> sqmPath,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
SqmToSqlAstConverter sqlAstCreationState) {
|
||||
final TableGroup tableGroup = sqlAstCreationState
|
||||
.getFromClauseAccess()
|
||||
.findTableGroup( sqmPath.getLhs().getNavigablePath() );
|
||||
final EntityValuedModelPart mapping = (EntityValuedModelPart) tableGroup
|
||||
.getModelPart()
|
||||
final EntityValuedModelPart mapping = (EntityValuedModelPart) tableGroup.getModelPart()
|
||||
.findSubPart( sqmPath.getReferencedPathSource().getPathName(), null );
|
||||
|
||||
SqlTuple sqlExpression = resolveSqlExpression(
|
||||
sqmPath,
|
||||
sqlAstCreationState,
|
||||
tableGroup,
|
||||
mapping
|
||||
);
|
||||
return new EntityValuedPathInterpretation<>(
|
||||
sqlExpression,
|
||||
sqmPath,
|
||||
tableGroup,
|
||||
mapping
|
||||
);
|
||||
}
|
||||
|
||||
private final Expression sqlExpression;
|
||||
|
||||
private EntityValuedPathInterpretation(
|
||||
Expression sqlExpression,
|
||||
SqmEntityValuedSimplePath sqmPath,
|
||||
TableGroup tableGroup,
|
||||
EntityValuedModelPart mapping) {
|
||||
super( sqmPath, mapping, tableGroup );
|
||||
this.sqlExpression = sqlExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
sqlExpression.accept( sqlTreeWalker );
|
||||
}
|
||||
|
||||
private static <T> SqlTuple resolveSqlExpression(
|
||||
SqmEntityValuedSimplePath<T> sqmPath,
|
||||
SqmToSqlAstConverter sqlAstCreationState,
|
||||
TableGroup tableGroup,
|
||||
EntityValuedModelPart mapping) {
|
||||
final List<ColumnReference> columnReferences = new ArrayList<>();
|
||||
|
||||
assert mapping instanceof ToOneAttributeMapping;
|
||||
|
||||
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) mapping;
|
||||
final ModelPart modelPart = getModelPart(
|
||||
sqlAstCreationState,
|
||||
toOneAttributeMapping
|
||||
);
|
||||
|
||||
modelPart.visitColumns(
|
||||
(containingTableExpression, columnExpression, isFormula, customReadExpression, customWriteExpression, jdbcMapping) -> {
|
||||
final TableReference tf;
|
||||
final TableReference tableReference = getTableReference(
|
||||
sqmPath,
|
||||
sqlAstCreationState,
|
||||
tableGroup,
|
||||
toOneAttributeMapping,
|
||||
containingTableExpression
|
||||
);
|
||||
|
||||
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
|
||||
.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
tableReference,
|
||||
columnExpression
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableReference.getIdentificationVariable(),
|
||||
columnExpression,
|
||||
isFormula,
|
||||
customReadExpression,
|
||||
customWriteExpression,
|
||||
jdbcMapping,
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
);
|
||||
|
||||
columnReferences.add( (ColumnReference) columnReference );
|
||||
}
|
||||
);
|
||||
|
||||
SqlTuple sqlExpression = new SqlTuple( columnReferences, mapping );
|
||||
return sqlExpression;
|
||||
}
|
||||
|
||||
private static ModelPart getModelPart(
|
||||
SqmToSqlAstConverter sqlAstCreationState,
|
||||
ToOneAttributeMapping toOneAttributeMapping) {
|
||||
final Clause current = sqlAstCreationState.getCurrentClauseStack()
|
||||
.getCurrent();
|
||||
final ModelPart modelPart;
|
||||
if ( current == Clause.SELECT ) {
|
||||
modelPart = toOneAttributeMapping.getAssociatedEntityMappingType().getIdentifierMapping();
|
||||
}
|
||||
else {
|
||||
modelPart = toOneAttributeMapping.getForeignKeyDescriptor();
|
||||
}
|
||||
return modelPart;
|
||||
}
|
||||
|
||||
private static <T> TableReference getTableReference(
|
||||
SqmEntityValuedSimplePath<T> sqmPath,
|
||||
SqlAstCreationState sqlAstCreationState,
|
||||
TableGroup tableGroup,
|
||||
ToOneAttributeMapping toOneAttributeMapping,
|
||||
String containingTableExpression) {
|
||||
TableReference tableReference = tableGroup.getTableReference( containingTableExpression );
|
||||
if ( tableReference == null ) {
|
||||
final TableGroupJoin tableGroupJoin = toOneAttributeMapping.createTableGroupJoin(
|
||||
sqmPath.getNavigablePath(),
|
||||
tableGroup,
|
||||
null,
|
||||
toOneAttributeMapping.isNullable() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT,
|
||||
LockMode.NONE,
|
||||
sqlAstCreationState
|
||||
);
|
||||
sqlAstCreationState.getFromClauseAccess().registerTableGroup(
|
||||
sqmPath.getNavigablePath(),
|
||||
tableGroupJoin.getJoinedGroup()
|
||||
);
|
||||
return tableGroupJoin.getJoinedGroup().getTableReference( containingTableExpression );
|
||||
}
|
||||
return tableReference;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.sql.internal;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
|
@ -45,8 +46,9 @@ public class PluralValuedSimplePathInterpretation<T> extends AbstractSqmPathInte
|
|||
super(sqmPath, mapping, tableGroup);
|
||||
this.sqlExpression = sqlExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
sqlExpression.accept( sqlTreeWalker );
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.map;
|
||||
package org.hibernate.orm.test.collection.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.map;
|
||||
package org.hibernate.orm.test.collection.map;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
|
@ -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.map;
|
||||
package org.hibernate.orm.test.collection.map;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -17,28 +17,26 @@ import javax.persistence.Id;
|
|||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.Table;
|
||||
|
||||
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.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class MapElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
AnEntity.class
|
||||
};
|
||||
}
|
||||
@DomainModel(
|
||||
annotatedClasses = MapElementNullBasicTest.AnEntity.class
|
||||
)
|
||||
@SessionFactory
|
||||
public class MapElementNullBasicTest {
|
||||
|
||||
@Test
|
||||
public void testPersistNullValue() {
|
||||
int entityId = doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
public void testPersistNullValue(SessionFactoryScope scope) {
|
||||
int entityId = scope.fromTransaction(
|
||||
session -> {
|
||||
AnEntity e = new AnEntity();
|
||||
e.aCollection.put( "null", null );
|
||||
session.persist( e );
|
||||
|
@ -46,49 +44,49 @@ public class MapElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 0, e.aCollection.size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||
session.delete( e );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addNullValue() {
|
||||
int entityId = doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
public void addNullValue(SessionFactoryScope scope) {
|
||||
int entityId = scope.fromTransaction(
|
||||
session -> {
|
||||
AnEntity e = new AnEntity();
|
||||
session.persist( e );
|
||||
return e.id;
|
||||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 0, e.aCollection.size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||
e.aCollection.put( "null", null );
|
||||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 0, e.aCollection.size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||
session.delete( e );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNonNullValueToNull() {
|
||||
int entityId = doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
public void testUpdateNonNullValueToNull(SessionFactoryScope scope) {
|
||||
int entityId = scope.fromTransaction(
|
||||
session -> {
|
||||
AnEntity e = new AnEntity();
|
||||
e.aCollection.put( "abc", "def" );
|
||||
session.persist( e );
|
||||
|
@ -96,29 +94,28 @@ public class MapElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 1, e.aCollection.size() );
|
||||
assertEquals( 1, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
|
||||
e.aCollection.put( "abc", null );
|
||||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 0, e.aCollection.size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||
session.delete( e );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNonNullValueToNullToNonNull() {
|
||||
int entityId = doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
public void testUpdateNonNullValueToNullToNonNull(SessionFactoryScope scope) {
|
||||
int entityId = scope.fromTransaction(
|
||||
session -> {
|
||||
AnEntity e = new AnEntity();
|
||||
e.aCollection.put( "abc", "def" );
|
||||
session.persist( e );
|
||||
|
@ -126,38 +123,38 @@ public class MapElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 1, e.aCollection.size() );
|
||||
assertEquals( 1, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
|
||||
e.aCollection.put( "abc", null );
|
||||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 0, e.aCollection.size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||
e.aCollection.put( "abc", "not null" );
|
||||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
AnEntity e = session.get( AnEntity.class, entityId );
|
||||
assertEquals( 1, e.aCollection.size() );
|
||||
assertEquals( 1, getCollectionElementRows( entityId ).size() );
|
||||
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
|
||||
assertEquals( "not null", e.aCollection.get( "abc" ) );
|
||||
session.delete( e );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private List<?> getCollectionElementRows(int id) {
|
||||
return doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
private List<?> getCollectionElementRows(int id, SessionFactoryScope scope) {
|
||||
return scope.fromTransaction(
|
||||
session -> {
|
||||
return session.createNativeQuery(
|
||||
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
|
||||
).list();
|
||||
|
@ -166,14 +163,14 @@ public class MapElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Entity
|
||||
@Table(name="AnEntity")
|
||||
@Table(name = "AnEntity")
|
||||
public static class AnEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn( name = "AnEntity_id" ) })
|
||||
private Map<String, String> aCollection = new HashMap<String, String>();
|
||||
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn(name = "AnEntity_id") })
|
||||
private Map<String, String> aCollection = new HashMap<>();
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.collection.map">
|
||||
<hibernate-mapping package="org.hibernate.orm.test.collection.map">
|
||||
|
||||
<class name="Parent">
|
||||
<id name="name" column="NAME" type="string" />
|
|
@ -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.map;
|
||||
package org.hibernate.orm.test.collection.map;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
|
@ -1,4 +1,4 @@
|
|||
package org.hibernate.test.collection.map;
|
||||
package org.hibernate.orm.test.collection.map;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
|
@ -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.map;
|
||||
package org.hibernate.orm.test.collection.map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.collection.internal.PersistentMap;
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
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;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Test various situations using a {@link PersistentMap}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@DomainModel(
|
||||
xmlMappings = "org/hibernate/orm/test/collection/map/Mappings.hbm.xml",
|
||||
annotatedClasses = {
|
||||
PersistentMapTest.User.class,
|
||||
PersistentMapTest.UserData.class,
|
||||
MultilingualString.class,
|
||||
MultilingualStringParent.class,
|
||||
PersistentMapTest.Address.class,
|
||||
PersistentMapTest.Detail.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class PersistentMapTest {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void testWriteMethodDirtying(SessionFactoryScope scope) {
|
||||
Parent parent = new Parent( "p1" );
|
||||
Child child = new Child( "c1" );
|
||||
parent.getChildren().put( child.getName(), child );
|
||||
child.setParent( parent );
|
||||
Child otherChild = new Child( "c2" );
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.save( parent );
|
||||
session.flush();
|
||||
// at this point, the map on parent has now been replaced with a PersistentMap...
|
||||
PersistentMap children = (PersistentMap) parent.getChildren();
|
||||
|
||||
Object old = children.put( child.getName(), child );
|
||||
assertTrue( old == child );
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
old = children.remove( otherChild.getName() );
|
||||
assertNull( old );
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
HashMap otherMap = new HashMap();
|
||||
otherMap.put( child.getName(), child );
|
||||
children.putAll( otherMap );
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
otherMap = new HashMap();
|
||||
otherMap.put( otherChild.getName(), otherChild );
|
||||
children.putAll( otherMap );
|
||||
assertTrue( children.isDirty() );
|
||||
|
||||
children.clearDirty();
|
||||
session.delete( child );
|
||||
children.clear();
|
||||
assertTrue( children.isDirty() );
|
||||
session.flush();
|
||||
|
||||
children.clear();
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
session.delete( parent );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAgainstUninitializedMap(SessionFactoryScope scope) {
|
||||
// prepare map owner...
|
||||
Parent p = new Parent( "p1" );
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.save( p );
|
||||
}
|
||||
);
|
||||
|
||||
// Now, reload the parent and test adding children
|
||||
Parent parent = scope.fromTransaction(
|
||||
session -> {
|
||||
Parent p1 = session.get( Parent.class, p.getName() );
|
||||
p1.addChild( "c1" );
|
||||
p1.addChild( "c2" );
|
||||
return p1;
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 2, parent.getChildren().size() );
|
||||
|
||||
scope.inTransaction(
|
||||
session -> session.delete( parent )
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAgainstUninitializedMap(SessionFactoryScope scope) {
|
||||
Parent parent = new Parent( "p1" );
|
||||
Child child = new Child( "c1" );
|
||||
parent.addChild( child );
|
||||
|
||||
scope.inTransaction(
|
||||
session -> session.save( parent )
|
||||
);
|
||||
|
||||
// Now reload the parent and test removing the child
|
||||
Child child2 = scope.fromTransaction(
|
||||
session -> {
|
||||
Parent p = session.get( Parent.class, parent.getName() );
|
||||
Child c2 = (Child) p.getChildren().remove( child.getName() );
|
||||
c2.setParent( null );
|
||||
assertNotNull( c2 );
|
||||
assertTrue( p.getChildren().isEmpty() );
|
||||
return c2;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// Load the parent once again and make sure child is still gone
|
||||
// then cleanup
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Parent p = session.get( Parent.class, parent.getName() );
|
||||
assertTrue( p.getChildren().isEmpty() );
|
||||
session.delete( child2 );
|
||||
session.delete( p );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSelect(SessionFactoryScope scope) {
|
||||
User user = new User();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
UserData userData = new UserData();
|
||||
userData.user = user;
|
||||
user.userDatas.put( "foo", userData );
|
||||
session.persist( user );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query q = session.createQuery( "SELECT d.user FROM " + UserData.class.getName() + " d " );
|
||||
List<User> list = q.list();
|
||||
|
||||
assertEquals( 1, list.size() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-5732")
|
||||
public void testClearMap(SessionFactoryScope scope) {
|
||||
scope.inSession(
|
||||
session -> {
|
||||
session.getTransaction().begin();
|
||||
try {
|
||||
User user = new User();
|
||||
UserData userData = new UserData();
|
||||
userData.user = user;
|
||||
user.userDatas.put( "foo", userData );
|
||||
session.persist( user );
|
||||
session.getTransaction().commit();
|
||||
session.clear();
|
||||
|
||||
session.beginTransaction();
|
||||
|
||||
|
||||
user = session.get( User.class, 1 );
|
||||
user.userDatas.clear();
|
||||
session.update( user );
|
||||
|
||||
Query q = session.createQuery( "DELETE FROM " + UserData.class.getName() + " d WHERE d.user = :user" );
|
||||
q.setParameter( "user", user );
|
||||
q.executeUpdate();
|
||||
|
||||
session.getTransaction().commit();
|
||||
|
||||
session.getTransaction().begin();
|
||||
/*
|
||||
select
|
||||
userdatas0_.userId as userid2_8_0_,
|
||||
userdatas0_.id as id1_8_0_,
|
||||
userdatas0_.name as name3_0_,
|
||||
userdatas0_.id as id1_8_1_,
|
||||
userdatas0_.userId as userid2_8_1_
|
||||
from
|
||||
UserData userdatas0_
|
||||
where
|
||||
userdatas0_.userId=1
|
||||
*/
|
||||
assertEquals( 0, session.get( User.class, user.id ).userDatas.size() );
|
||||
assertEquals( 0, session.createQuery( "FROM " + UserData.class.getName() ).list().size() );
|
||||
session.createQuery( "delete " + User.class.getName() )
|
||||
.executeUpdate();
|
||||
session.getTransaction().commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
if ( session.getTransaction().isActive() ) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-5393")
|
||||
public void testMapKeyColumnInEmbeddableElement(SessionFactoryScope scope) {
|
||||
MultilingualString m = new MultilingualString();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
LocalizedString localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English" );
|
||||
localizedString.setText( "name" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English Pig Latin" );
|
||||
localizedString.setText( "amenay" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
session.persist( m );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
MultilingualString multilingualString = session.get( MultilingualString.class, m.getId() );
|
||||
assertEquals( 2, multilingualString.getMap().size() );
|
||||
LocalizedString localizedString = multilingualString.getMap().get( "English" );
|
||||
assertEquals( "English", localizedString.getLanguage() );
|
||||
assertEquals( "name", localizedString.getText() );
|
||||
localizedString = multilingualString.getMap().get( "English Pig Latin" );
|
||||
assertEquals( "English Pig Latin", localizedString.getLanguage() );
|
||||
assertEquals( "amenay", localizedString.getText() );
|
||||
session.delete( multilingualString );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HQLPARSER-15")
|
||||
public void testJoinFetchElementCollectionWithParentSelect(SessionFactoryScope scope) {
|
||||
MultilingualStringParent parent = new MultilingualStringParent();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
MultilingualString m = new MultilingualString();
|
||||
LocalizedString localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English" );
|
||||
localizedString.setText( "name" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English Pig Latin" );
|
||||
localizedString.setText( "amenay" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
|
||||
parent.setString( m );
|
||||
|
||||
session.persist( m );
|
||||
session.persist( parent );
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
MultilingualString m = session.createQuery(
|
||||
"SELECT s FROM MultilingualStringParent parent " +
|
||||
"JOIN parent.string s " +
|
||||
"JOIN FETCH s.map", MultilingualString.class )
|
||||
.getSingleResult();
|
||||
assertEquals( 2, m.getMap().size() );
|
||||
LocalizedString localizedString = m.getMap().get( "English" );
|
||||
assertEquals( "English", localizedString.getLanguage() );
|
||||
assertEquals( "name", localizedString.getText() );
|
||||
localizedString = m.getMap().get( "English Pig Latin" );
|
||||
assertEquals( "English Pig Latin", localizedString.getLanguage() );
|
||||
assertEquals( "amenay", localizedString.getText() );
|
||||
session.delete( parent );
|
||||
session.delete( m );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11038")
|
||||
public void testMapKeyColumnNonInsertableNonUpdatableBidirOneToMany(SessionFactoryScope scope) {
|
||||
User user = new User();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Address address = new Address();
|
||||
address.addressType = "email";
|
||||
address.addressText = "jane@doe.com";
|
||||
user.addresses.put( address.addressType, address );
|
||||
address.user = user;
|
||||
session.persist( user );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
User u = session.get( User.class, user.id );
|
||||
u.addresses.clear();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
User u = session.get( User.class, user.id );
|
||||
session.delete( u );
|
||||
session.createQuery( "delete from " + User.class.getName() ).executeUpdate();
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11038")
|
||||
public void testMapKeyColumnNonInsertableNonUpdatableUnidirOneToMany(SessionFactoryScope scope) {
|
||||
User user = new User();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Detail detail = new Detail();
|
||||
detail.description = "desc";
|
||||
detail.detailType = "trivial";
|
||||
user.details.put( detail.detailType, detail );
|
||||
session.persist( user );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
User u = session.get( User.class, user.id );
|
||||
u.details.clear();
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
User u = session.get( User.class, user.id );
|
||||
session.delete( u );
|
||||
session.createQuery( "delete from " + User.class.getName() ).executeUpdate();
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "MyUser")
|
||||
static class User implements Serializable {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
|
||||
@MapKeyColumn(name = "name", nullable = true)
|
||||
private Map<String, UserData> userDatas = new HashMap<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
|
||||
@MapKeyColumn(name = "addressType", insertable = false, updatable = false)
|
||||
private Map<String, Address> addresses = new HashMap<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@MapKeyColumn(name = "detailType", insertable = false, updatable = false)
|
||||
@JoinColumn
|
||||
private Map<String, Detail> details = new HashMap<>();
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "UserData")
|
||||
static class UserData {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "userId")
|
||||
private User user;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "Address")
|
||||
static class Address {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "userId")
|
||||
private User user;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String addressType;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String addressText;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "Detail")
|
||||
static class Detail {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String detailType;
|
||||
|
||||
private String description;
|
||||
}
|
||||
}
|
|
@ -1,406 +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;
|
||||
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 java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.collection.internal.PersistentMap;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test various situations using a {@link PersistentMap}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class PersistentMapTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
public String[] getMappings() {
|
||||
return new String[] { "collection/map/Mappings.hbm.xml" };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
User.class,
|
||||
UserData.class,
|
||||
MultilingualString.class,
|
||||
MultilingualStringParent.class,
|
||||
Address.class,
|
||||
Detail.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void testWriteMethodDirtying() {
|
||||
Parent parent = new Parent( "p1" );
|
||||
Child child = new Child( "c1" );
|
||||
parent.getChildren().put( child.getName(), child );
|
||||
child.setParent( parent );
|
||||
Child otherChild = new Child( "c2" );
|
||||
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
session.save( parent );
|
||||
session.flush();
|
||||
// at this point, the map on parent has now been replaced with a PersistentMap...
|
||||
PersistentMap children = ( PersistentMap ) parent.getChildren();
|
||||
|
||||
Object old = children.put( child.getName(), child );
|
||||
assertTrue( old == child );
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
old = children.remove( otherChild.getName() );
|
||||
assertNull( old );
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
HashMap otherMap = new HashMap();
|
||||
otherMap.put( child.getName(), child );
|
||||
children.putAll( otherMap );
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
otherMap = new HashMap();
|
||||
otherMap.put( otherChild.getName(), otherChild );
|
||||
children.putAll( otherMap );
|
||||
assertTrue( children.isDirty() );
|
||||
|
||||
children.clearDirty();
|
||||
session.delete( child );
|
||||
children.clear();
|
||||
assertTrue( children.isDirty() );
|
||||
session.flush();
|
||||
|
||||
children.clear();
|
||||
assertFalse( children.isDirty() );
|
||||
|
||||
session.delete( parent );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAgainstUninitializedMap() {
|
||||
// prepare map owner...
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Parent parent = new Parent( "p1" );
|
||||
session.save( parent );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// Now, reload the parent and test adding children
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
parent = ( Parent ) session.get( Parent.class, parent.getName() );
|
||||
parent.addChild( "c1" );
|
||||
parent.addChild( "c2" );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
assertEquals( 2, parent.getChildren().size() );
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.delete( parent );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAgainstUninitializedMap() {
|
||||
Parent parent = new Parent( "p1" );
|
||||
Child child = new Child( "c1" );
|
||||
parent.addChild( child );
|
||||
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
session.save( parent );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// Now reload the parent and test removing the child
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
parent = ( Parent ) session.get( Parent.class, parent.getName() );
|
||||
Child child2 = ( Child ) parent.getChildren().remove( child.getName() );
|
||||
child2.setParent( null );
|
||||
assertNotNull( child2 );
|
||||
assertTrue( parent.getChildren().isEmpty() );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// Load the parent once again and make sure child is still gone
|
||||
// then cleanup
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
parent = ( Parent ) session.get( Parent.class, parent.getName() );
|
||||
assertTrue( parent.getChildren().isEmpty() );
|
||||
session.delete( child2 );
|
||||
session.delete( parent );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-5732")
|
||||
public void testClearMap() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
|
||||
User user = new User();
|
||||
UserData userData = new UserData();
|
||||
userData.user = user;
|
||||
user.userDatas.put( "foo", userData );
|
||||
s.persist( user );
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.clear();
|
||||
|
||||
s.beginTransaction();
|
||||
|
||||
user = s.get( User.class, 1 );
|
||||
user.userDatas.clear();
|
||||
s.update( user );
|
||||
Query q = s.createQuery( "DELETE FROM " + UserData.class.getName() + " d WHERE d.user = :user" );
|
||||
q.setParameter( "user", user );
|
||||
q.executeUpdate();
|
||||
|
||||
s.getTransaction().commit();
|
||||
|
||||
s.getTransaction().begin();
|
||||
|
||||
assertEquals( s.get( User.class, user.id ).userDatas.size(), 0 );
|
||||
assertEquals( s.createQuery( "FROM " + UserData.class.getName() ).list().size(), 0 );
|
||||
s.createQuery( "delete " + User.class.getName() ).executeUpdate();
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-5393")
|
||||
public void testMapKeyColumnInEmbeddableElement() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
MultilingualString m = new MultilingualString();
|
||||
LocalizedString localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English" );
|
||||
localizedString.setText( "name" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English Pig Latin" );
|
||||
localizedString.setText( "amenay" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
s.persist( m );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
m = s.get( MultilingualString.class, m.getId());
|
||||
assertEquals( 2, m.getMap().size() );
|
||||
localizedString = m.getMap().get( "English" );
|
||||
assertEquals( "English", localizedString.getLanguage() );
|
||||
assertEquals( "name", localizedString.getText() );
|
||||
localizedString = m.getMap().get( "English Pig Latin" );
|
||||
assertEquals( "English Pig Latin", localizedString.getLanguage() );
|
||||
assertEquals( "amenay", localizedString.getText() );
|
||||
s.delete( m );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HQLPARSER-15")
|
||||
public void testJoinFetchElementCollectionWithParentSelect() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
MultilingualString m = new MultilingualString();
|
||||
LocalizedString localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English" );
|
||||
localizedString.setText( "name" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
localizedString = new LocalizedString();
|
||||
localizedString.setLanguage( "English Pig Latin" );
|
||||
localizedString.setText( "amenay" );
|
||||
m.getMap().put( localizedString.getLanguage(), localizedString );
|
||||
|
||||
MultilingualStringParent parent = new MultilingualStringParent();
|
||||
parent.setString( m );
|
||||
|
||||
s.persist( m );
|
||||
s.persist( parent );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
m = s.createQuery(
|
||||
"SELECT s FROM MultilingualStringParent parent " +
|
||||
"JOIN parent.string s " +
|
||||
"JOIN FETCH s.map", MultilingualString.class )
|
||||
.getSingleResult();
|
||||
assertEquals( 2, m.getMap().size() );
|
||||
localizedString = m.getMap().get( "English" );
|
||||
assertEquals( "English", localizedString.getLanguage() );
|
||||
assertEquals( "name", localizedString.getText() );
|
||||
localizedString = m.getMap().get( "English Pig Latin" );
|
||||
assertEquals( "English Pig Latin", localizedString.getLanguage() );
|
||||
assertEquals( "amenay", localizedString.getText() );
|
||||
s.delete( parent );
|
||||
s.delete( m );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-11038" )
|
||||
public void testMapKeyColumnNonInsertableNonUpdatableBidirOneToMany() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
User user = new User();
|
||||
Address address = new Address();
|
||||
address.addressType = "email";
|
||||
address.addressText = "jane@doe.com";
|
||||
user.addresses.put( address.addressType, address );
|
||||
address.user = user;
|
||||
s.persist( user );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
user = s.get( User.class, user.id );
|
||||
user.addresses.clear();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
user = s.get( User.class, user.id );
|
||||
s.delete( user );
|
||||
s.createQuery( "delete from " + User.class.getName() ).executeUpdate();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-11038" )
|
||||
public void testMapKeyColumnNonInsertableNonUpdatableUnidirOneToMany() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
User user = new User();
|
||||
Detail detail = new Detail();
|
||||
detail.description = "desc";
|
||||
detail.detailType = "trivial";
|
||||
user.details.put( detail.detailType, detail );
|
||||
s.persist( user );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
user = s.get( User.class, user.id );
|
||||
user.details.clear();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
user = s.get( User.class, user.id );
|
||||
s.delete( user );
|
||||
s.createQuery( "delete from " + User.class.getName() ).executeUpdate();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "MyUser")
|
||||
private static class User implements Serializable {
|
||||
@Id @GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
|
||||
@MapKeyColumn(name = "name", nullable = true)
|
||||
private Map<String, UserData> userDatas = new HashMap<String, UserData>();
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
|
||||
@MapKeyColumn(name = "addressType", insertable = false, updatable = false)
|
||||
private Map<String, Address> addresses = new HashMap<String, Address>();
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@MapKeyColumn(name = "detailType", insertable = false, updatable = false)
|
||||
@JoinColumn
|
||||
private Map<String, Detail> details = new HashMap<String, Detail>();
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "UserData")
|
||||
private static class UserData {
|
||||
@Id @GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "userId")
|
||||
private User user;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "Address")
|
||||
private static class Address {
|
||||
@Id @GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "userId")
|
||||
private User user;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String addressType;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String addressText;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name="Detail")
|
||||
private static class Detail {
|
||||
@Id @GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String detailType;
|
||||
|
||||
private String description;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue