diff --git a/hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlParser.g4 b/hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlParser.g4 index 7798205b24..c50258de74 100644 --- a/hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlParser.g4 +++ b/hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlParser.g4 @@ -391,7 +391,7 @@ comparisonOperator inList : ELEMENTS? LEFT_PAREN dotIdentifierSequence RIGHT_PAREN # PersistentCollectionReferenceInList | LEFT_PAREN expression (COMMA expression)* RIGHT_PAREN # ExplicitTupleInList - | expression # SubQueryInList + | expression # SubQueryOrParamInList ; likeEscape diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java index cef77b343a..8e61a6928e 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -273,10 +273,10 @@ public class Column implements Selectable, Serializable, Cloneable { Type type = getValue().getType(); if ( type instanceof EntityType ) { - type = getTypeForEntityValue( mapping, type ); + type = getTypeForEntityValue( mapping, type, getTypeIndex() ); } if ( type instanceof ComponentType ) { - type = getTypeForComponentValue( mapping, type ); + type = getTypeForComponentValue( mapping, type, getTypeIndex() ); } return dialect.getDefaultSizeStrategy().resolveDefaultSize( ( (JdbcMapping) type ).getSqlTypeDescriptor(), @@ -284,20 +284,42 @@ public class Column implements Selectable, Serializable, Cloneable { ); } - private Type getTypeForComponentValue(Mapping mapping, Type type) { - type = ( (ComponentType) type ).getSubtypes()[getTypeIndex()]; - if ( type instanceof EntityType ) { - type = getTypeForEntityValue( mapping, type ); + private Type getTypeForComponentValue(Mapping mapping, Type type, int typeIndex) { + final Type[] subtypes = ( (ComponentType) type ).getSubtypes(); + int currentSubtypesColumnSpans = 0; + for ( int i = 0; i <= subtypes.length; i++ ) { + Type subtype = subtypes[i]; + int subtypeColumnSpan = subtype.getColumnSpan( mapping ); + currentSubtypesColumnSpans += subtypeColumnSpan; + if ( currentSubtypesColumnSpans - 1 >= typeIndex ) { + if ( subtype instanceof EntityType ) { + return getTypeForEntityValue( mapping, subtype, subtypeColumnSpan - i ); + } + if ( subtype instanceof ComponentType ) { + return getTypeForComponentValue( mapping, subtype, subtypeColumnSpan - i ); + } + if ( i == typeIndex ) { + return subtype; + } + } } - return type; + + throw new HibernateException( + String.format( + Locale.ROOT, + "Unable to resolve org.hibernate.type.Type for column `%s.%s`", + getValue().getTable().getName(), + getName() + ) + ); } - private Type getTypeForEntityValue(Mapping mapping, Type type) { + private Type getTypeForEntityValue(Mapping mapping, Type type, int typeIndex) { while ( !( type instanceof JdbcMapping ) ) { //ManyToOneType doesn't implement JdbcMapping type = mapping.getIdentifierType( ( (EntityType) type ).getAssociatedEntityName() ); if ( type instanceof ComponentType ) { - type = ( (ComponentType) type ).getSubtypes()[getTypeIndex()]; + type = ( (ComponentType) type ).getSubtypes()[typeIndex]; } } return type; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java index 45fb80fedc..77bb97f364 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java @@ -383,6 +383,56 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model throw new UnsupportedOperationException(); } + @Override + public DomainResult createDomainResult( + NavigablePath navigablePath, + TableGroup tableGroup, + String resultVariable, + DomainResultCreationState creationState) { + //noinspection unchecked + final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); + final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); + final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable ); + final String identificationVariable = tableReference.getIdentificationVariable(); + int size = keyColumnExpressions.size(); + List sqlSelections = new ArrayList<>(size); + for ( int i = 0; i < size; i++ ) { + final String columnExpression = keyColumnExpressions.get( i ); + final JdbcMapping jdbcMapping = jdbcMappings.get( i ); + final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( + sqlExpressionResolver.resolveSqlExpression( + SqlExpressionResolver.createColumnReferenceKey( + tableReference, + columnExpression + ), + s -> + new ColumnReference( + identificationVariable, + columnExpression, + false, + null, + null, + jdbcMapping, + creationState.getSqlAstCreationState() + .getCreationContext() + .getSessionFactory() + ) + ), + jdbcMapping.getJavaTypeDescriptor(), + sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration() + ); + sqlSelections.add( sqlSelection ); + } + + return new EmbeddableForeignKeyResultImpl( + sqlSelections, + navigablePath, + mappingType, + resultVariable, + creationState + ); + } + @Override public EntityMappingType findContainingEntityMapping() { throw new UnsupportedOperationException(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java index 0856cb3091..8ca48bf75b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java @@ -928,7 +928,7 @@ public class MappingModelCreationHelper { } else { throw new NotYetImplementedFor6Exception( - "Support for composite foreign keys not yet implemented: " + bootValueMapping.getRole() + "Support for " + fkTarget.getClass() + " foreign keys not yet implemented: " + bootValueMapping.getRole() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java index 41927e7d30..142b7849fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java @@ -51,7 +51,7 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif Component bootCidDescriptor, Component bootIdClassDescriptor, MappingModelCreationProcess creationProcess) { - // todo (6.0) : handle MapsId and IdClass + // todo (6.0) : handle MapsId super( attributeMetadataAccess, embeddableDescriptor, diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index d2cbc1e3c2..0ba045cd1f 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -5924,15 +5924,7 @@ public abstract class AbstractEntityPersister accessOptimizer = null; } - if ( isMultiTable() ) { - sqmMultiTableMutationStrategy = interpretSqmMultiTableStrategy( - this, - creationProcess - ); - } - else { - sqmMultiTableMutationStrategy = null; - } + // register a callback for after all `#prepareMappingModel` calls have finished. here we want to delay the // generation of `staticFetchableList` because we need to wait until after all sub-classes have had their @@ -5946,6 +5938,26 @@ public abstract class AbstractEntityPersister return true; } ); + + if ( isMultiTable() ) { + creationProcess.registerInitializationCallback( + "Entity(" + getEntityName() + ") `sqmMultiTableMutationStrategy` interpretation", + () -> { + sqmMultiTableMutationStrategy = interpretSqmMultiTableStrategy( + this, + creationProcess + ); + if ( sqmMultiTableMutationStrategy == null ) { + return false; + } + return true; + } + ); + + } + else { + sqmMultiTableMutationStrategy = null; + } } private void prepareMappingModel(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) { @@ -6026,8 +6038,13 @@ public abstract class AbstractEntityPersister MappingModelCreationProcess creationProcess) { assert entityMappingDescriptor.isMultiTable(); - if ( entityMappingDescriptor.getSuperMappingType() != null ) { - return entityMappingDescriptor.getSuperMappingType().getSqmMultiTableMutationStrategy(); + EntityMappingType superMappingType = entityMappingDescriptor.getSuperMappingType(); + if ( superMappingType != null ) { + SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy = superMappingType + .getSqmMultiTableMutationStrategy(); + if ( sqmMultiTableMutationStrategy != null ) { + return sqmMultiTableMutationStrategy; + } } // we need the boot model so we can have access to the Table diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index a204f7b236..3e5a3388e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -1407,8 +1407,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre final List> listExpressions = new ArrayList<>( expressionContexts.size() ); for ( HqlParser.ExpressionContext expressionContext : expressionContexts ) { final Map, Enum> possibleEnumValues; - if ( isEnum && (possibleEnumValues = getPossibleEnumValues( expressionContext )) != null ) { - listExpressions.add( resolveEnumShorthandLiteral( expressionContext, possibleEnumValues, testExpression.getJavaType() ) ); + if ( isEnum && ( possibleEnumValues = getPossibleEnumValues( expressionContext ) ) != null ) { + listExpressions.add( resolveEnumShorthandLiteral( + expressionContext, + possibleEnumValues, + testExpression.getJavaType() + ) ); } else { listExpressions.add( (SqmExpression) expressionContext.accept( this ) ); @@ -1427,21 +1431,33 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre parameterDeclarationContextStack.pop(); } } - else if ( inListContext instanceof HqlParser.SubQueryInListContext ) { - final HqlParser.SubQueryInListContext subQueryContext = (HqlParser.SubQueryInListContext) inListContext; - final SqmExpression subQueryExpression = (SqmExpression) subQueryContext.expression().accept( this ); + else if ( inListContext instanceof HqlParser.SubQueryOrParamInListContext ) { + final HqlParser.SubQueryOrParamInListContext subQueryOrParamInListContext = (HqlParser.SubQueryOrParamInListContext) inListContext; + final SqmExpression sqmExpression = (SqmExpression) subQueryOrParamInListContext.expression().accept( this ); - if ( !(subQueryExpression instanceof SqmSubQuery) ) { + if ( !( sqmExpression instanceof SqmSubQuery ) ) { + if ( sqmExpression instanceof SqmParameter ) { + final List> listExpressions = new ArrayList<>( 1 ); + listExpressions.add( sqmExpression ); + + return new SqmInListPredicate( + testExpression, + listExpressions, + ctx.NOT() != null, + creationContext.getNodeBuilder() + ); + } throw new ParsingException( - "Was expecting a SubQueryExpression, but found " + subQueryExpression.getClass().getSimpleName() - + " : " + subQueryContext.expression().toString() + "Was expecting a SubQueryExpression or a SqmParameter, but found " + sqmExpression.getClass() + .getSimpleName() + + " : " + subQueryOrParamInListContext.expression().toString() ); } //noinspection unchecked return new SqmInSubQueryPredicate( testExpression, - (SqmSubQuery) subQueryExpression, + (SqmSubQuery) sqmExpression, ctx.NOT() != null, creationContext.getNodeBuilder() ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmEnumLiteral.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmEnumLiteral.java index af6b78d10a..f35bfe9c01 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmEnumLiteral.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmEnumLiteral.java @@ -8,22 +8,16 @@ package org.hibernate.query.sqm.tree.expression; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.Collection; -import java.util.List; import java.util.Locale; -import javax.persistence.criteria.Expression; import org.hibernate.query.SemanticException; -import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SqmExpressable; import org.hibernate.query.sqm.tree.domain.SqmPath; -import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * Specialized SQM literal defined by an enum reference. E.g. @@ -31,7 +25,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; * * @author Steve Ebersole */ -public class SqmEnumLiteral> extends AbstractSqmExpression implements SqmExpression, SqmExpressable, SemanticPathPart { +public class SqmEnumLiteral> extends AbstractSqmExpression implements SqmExpressable, SemanticPathPart { private final E enumValue; private final EnumJavaTypeDescriptor referencedEnumTypeDescriptor; private final String enumValueName; diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java index 3805e787b4..8c427c3a5b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmLiteral.java @@ -23,7 +23,7 @@ import org.hibernate.query.sqm.sql.internal.DomainResultProducer; */ public class SqmLiteral extends AbstractSqmExpression - implements SqmExpression, DomainResultProducer { + implements DomainResultProducer { private final T value; public SqmLiteral(T value, SqmExpressable inherentType, NodeBuilder nodeBuilder) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmSelfRenderingExpression.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmSelfRenderingExpression.java index 33ecb69e73..ffe19738b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmSelfRenderingExpression.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmSelfRenderingExpression.java @@ -16,7 +16,7 @@ import org.hibernate.sql.ast.tree.expression.Expression; /** * @author Steve Ebersole */ -public class SqmSelfRenderingExpression extends AbstractSqmExpression implements SqmExpression { +public class SqmSelfRenderingExpression extends AbstractSqmExpression { private final Function renderer; public SqmSelfRenderingExpression( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java index 00dcfa33e6..47388967e3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java @@ -7,6 +7,7 @@ package org.hibernate.query.sqm.tree.predicate; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import javax.persistence.criteria.Expression; @@ -71,6 +72,12 @@ public class SqmInListPredicate extends AbstractNegatableSqmPredicate impleme @Override public SqmInPredicate value(Object value) { + if ( value instanceof Collection ) { + ( (Collection) value ).forEach( + v -> addExpression( nodeBuilder().literal( v ) ) + ); + return this; + } addExpression( nodeBuilder().literal( value ) ); return this; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/A.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/A.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/A.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/A.java index 9a846bebba..2e26a234eb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/A.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/A.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; import javax.persistence.EmbeddedId; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/AId.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/AId.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/AId.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/AId.java index e3154c83d6..eb287b80ff 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/AId.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/AId.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; import javax.persistence.Embeddable; import javax.persistence.JoinColumn; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/B.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/B.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/B.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/B.java index e2100f3734..e241e68c3b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/B.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/B.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/C.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/C.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/C.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/C.java index b71c7df9eb..0f932a839f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/C.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/C.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Channel.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Channel.java similarity index 90% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Channel.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Channel.java index b16e052f43..945a740076 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Channel.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Channel.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Child.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Child.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Child.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Child.java index a02398bf8d..5a5985f19f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Child.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Child.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.AttributeOverride; import javax.persistence.Column; import javax.persistence.EmbeddedId; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ChildPk.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/ChildPk.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ChildPk.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/ChildPk.java index 7e4f065bd4..24af85be96 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ChildPk.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/ChildPk.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; import javax.persistence.Embeddable; import javax.persistence.JoinColumn; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/CompositeIdIdentityTest.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdIdentityTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/CompositeIdIdentityTest.java index 04aeff7b49..a1db39236b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/CompositeIdIdentityTest.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/CompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/CompositeIdTest.java new file mode 100644 index 0000000000..642f25beeb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/CompositeIdTest.java @@ -0,0 +1,541 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.annotations.cid; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.hibernate.Session; +import org.hibernate.query.Query; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.FailureExpected; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +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.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * test some composite id functionalities + * + * @author Emmanuel Bernard + */ +@DomainModel( + annotatedClasses = { + Parent.class, + Child.class, + Channel.class, + TvMagazin.class, + TvProgramIdClass.class, + TvProgram.class, + Presenter.class, + Order.class, + Product.class, + OrderLine.class, + OrderLinePk.class, + LittleGenius.class, + A.class, + B.class, + C.class, + SomeEntity.class + } +) +@SessionFactory +public class CompositeIdTest { + + @AfterEach + public void tearDown(SessionFactoryScope scope){ + scope.inTransaction( + session -> { + session.createQuery( "delete from LittleGenius" ).executeUpdate(); + session.createQuery( "delete from Child" ).executeUpdate(); + session.createQuery( "delete from Parent" ).executeUpdate(); + session.createQuery( "delete from SomeEntity" ).executeUpdate(); + session.createQuery( "delete from TvProgram" ).executeUpdate(); + session.createQuery( "delete from TvProgramIdClass" ).executeUpdate(); + session.createQuery( "delete from TvMagazin" ).executeUpdate(); + session.createQuery( "delete from Presenter" ).executeUpdate(); + session.createQuery( "delete from Channel" ).executeUpdate(); + session.createQuery( "delete from A" ).executeUpdate(); + session.createQuery( "delete from B" ).executeUpdate(); + session.createQuery( "delete from C" ).executeUpdate(); + session.createQuery( "delete from OrderLine" ).executeUpdate(); + session.createQuery( "delete from Product" ).executeUpdate(); + session.createQuery( "delete from Order" ).executeUpdate(); + } + ); + } + + @Test + public void testOneToOneInCompositePk(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + B b = new B(); + C c = new C(); + session.persist( b ); + session.persist( c ); + A a = new A(); + a.setAId( new AId() ); + a.getAId().setB( b ); + a.getAId().setC( c ); + session.persist( a ); + session.flush(); + session.clear(); + + a = session.get( A.class, a.getAId() ); + assertEquals( b.getId(), a.getAId().getB().getId() ); + } + ); + } + + + /** + * This feature is not supported by the EJB3 + * this is an hibernate extension + */ + @Test + public void testManyToOneInCompositePk(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + ParentPk ppk = new ParentPk(); + ppk.setFirstName( "Emmanuel" ); + ppk.setLastName( "Bernard" ); + Parent p = new Parent(); + p.id = ppk; + session.persist( p ); + ChildPk cpk = new ChildPk(); + cpk.parent = p; + cpk.nthChild = 1; + Child c = new Child(); + c.id = cpk; + session.persist( c ); + } + ); + + scope.inTransaction( + session -> { + Query q = session.createQuery( "select c from Child c where c.id.nthChild = :nth" ); + q.setParameter( "nth", 1 ); + List results = q.list(); + assertEquals( 1, results.size() ); + Child c = (Child) results.get( 0 ); + assertNotNull( c ); + assertNotNull( c.id.parent ); + //FIXME mke it work in unambigious cases + // assertNotNull(c.id.parent.id); + // assertEquals(p.id.getFirstName(), c.id.parent.id.getFirstName()); + session.delete( c ); + session.delete( c.id.parent ); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-10476") + public void testManyToOneInCompositePkInPC(SessionFactoryScope scope) { + ParentPk ppk = new ParentPk(); + ChildPk cpk = new ChildPk(); + scope.inTransaction( + session -> { + ppk.setFirstName( "Emmanuel" ); + ppk.setLastName( "Bernard" ); + Parent p = new Parent(); + p.id = ppk; + session.persist( p ); + cpk.parent = p; + cpk.nthChild = 1; + Child c = new Child(); + c.id = cpk; + session.persist( c ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, ppk ); + // p.id should be ppk. + assertSame( ppk, p.id ); + } + ); + + scope.inTransaction( + session -> { + Child c = session.get( Child.class, cpk ); + // c.id should be cpk + assertSame( cpk, c.id ); + // only Child should be in PC (c.id.parent should not be in PC) + assertTrue( session.getPersistenceContext().isEntryFor( c ) ); + assertFalse( session.getPersistenceContext().isEntryFor( c.id.parent ) ); + + } + ); + } + + /** + * This feature is not supported by the EJB3 + * this is an hibernate extension + */ + @Test + public void testManyToOneInCompositePkAndSubclass(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + ParentPk ppk = new ParentPk(); + ppk.setFirstName( "Emmanuel" ); + ppk.setLastName( "Bernard" ); + Parent p = new Parent(); + p.id = ppk; + session.persist( p ); + ChildPk cpk = new ChildPk(); + cpk.parent = p; + cpk.nthChild = 1; + LittleGenius c = new LittleGenius(); + c.particularSkill = "Human Annotation parser"; + c.id = cpk; + session.persist( c ); + } + ); + + scope.inTransaction( + session -> { + Query q = session.createQuery( "select c from Child c where c.id.nthChild = :nth" ); + q.setParameter( "nth", 1 ); + List results = q.list(); + assertEquals( 1, results.size() ); + Child c = (LittleGenius) results.get( 0 ); + assertNotNull( c ); + assertNotNull( c.id.parent ); + //FIXME mke it work in unambigious cases +// assertNotNull(c.id.parent.id); +// assertEquals(p.id.getFirstName(), c.id.parent.id.getFirstName()); + session.delete( c ); + session.delete( c.id.parent ); + } + ); + } + + @Test + public void testManyToOneInCompositeId(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Channel channel = new Channel(); + session.persist( channel ); + Presenter pres = new Presenter(); + pres.name = "Casimir"; + session.persist( pres ); + TvMagazinPk pk = new TvMagazinPk(); + TvMagazin mag = new TvMagazin(); + mag.time = new Date(); + mag.id = pk; + pk.channel = channel; + pk.presenter = pres; + session.persist( mag ); + session.getTransaction().commit(); + session.clear(); + session.beginTransaction(); + mag = (TvMagazin) session.createQuery( "from TvMagazin mag" ).uniqueResult(); + assertNotNull( mag.id ); + assertNotNull( mag.id.channel ); + assertEquals( channel.id, mag.id.channel.id ); + assertNotNull( mag.id.presenter ); + assertEquals( pres.name, mag.id.presenter.name ); + session.delete( mag ); + session.delete( mag.id.channel ); + session.delete( mag.id.presenter ); + } + ); + } + + @Test + public void testManyToOneInCompositeIdClass(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Order order = new Order(); + session.persist( order ); + Product product = new Product(); + product.name = "small car"; + session.persist( product ); + OrderLine orderLine = new OrderLine(); + orderLine.order = order; + orderLine.product = product; + session.persist( orderLine ); + session.flush(); + session.clear(); + + orderLine = (OrderLine) session.createQuery( "select ol from OrderLine ol" ).uniqueResult(); + assertNotNull( orderLine.order ); + assertEquals( order.id, orderLine.order.id ); + assertNotNull( orderLine.product ); + assertEquals( product.name, orderLine.product.name ); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-10476") + public void testManyToOneInCompositeIdClassInPC(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Order order = new Order(); + session.persist( order ); + Product product = new Product(); + product.name = "small car"; + session.persist( product ); + OrderLine orderLine = new OrderLine(); + orderLine.order = order; + orderLine.product = product; + session.persist( orderLine ); + session.flush(); + session.clear(); + + session.clear(); + OrderLinePk orderLinePK = new OrderLinePk(); + orderLinePK.order = orderLine.order; + orderLinePK.product = orderLine.product; + orderLine = session.get( OrderLine.class, orderLinePK ); + assertTrue( orderLine.order != orderLinePK.order ); + assertTrue( orderLine.product != orderLinePK.product ); + assertTrue( session.getPersistenceContext().isEntryFor( orderLine ) ); + assertTrue( session.getPersistenceContext().isEntryFor( orderLine.order ) ); + assertTrue( session.getPersistenceContext().isEntryFor( orderLine.product ) ); + assertFalse( session.getPersistenceContext().isEntryFor( orderLinePK.order ) ); + assertFalse( session.getPersistenceContext().isEntryFor( orderLinePK.product ) ); + + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-10476") + public void testGetWithUpdatedDetachedEntityInCompositeID(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Channel channel = new Channel(); + Presenter presenter = new Presenter(); + presenter.name = "Jane"; + TvMagazin tvMagazin = new TvMagazin(); + tvMagazin.id = new TvMagazinPk(); + tvMagazin.id.channel = channel; + tvMagazin.id.presenter = presenter; + session.persist( channel ); + session.persist( presenter ); + session.persist( tvMagazin ); + session.flush(); + + session.clear(); + // update channel + channel.name = "chnl"; + TvMagazinPk pkNew = new TvMagazinPk(); + // set pkNew.channel to the unmerged copy. + pkNew.channel = channel; + pkNew.presenter = presenter; + // the following fails because there is already a managed channel + tvMagazin = session.get( TvMagazin.class, pkNew ); + channel = session.get( Channel.class, channel.id ); + assertNull( channel.name ); + session.flush(); + session.clear(); + + // make sure that channel.name is still null + channel = session.get( Channel.class, channel.id ); + assertNull( channel.name ); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-10476") + public void testGetWithDetachedEntityInCompositeIDWithManagedCopy(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Channel channel = new Channel(); + Presenter presenter = new Presenter(); + presenter.name = "Jane"; + TvMagazin tvMagazin = new TvMagazin(); + tvMagazin.id = new TvMagazinPk(); + tvMagazin.id.channel = channel; + tvMagazin.id.presenter = presenter; + session.persist( channel ); + session.persist( presenter ); + session.persist( tvMagazin ); + session.flush(); + + session.clear(); + // merge channel to put channel back in PersistenceContext + session.merge( channel ); + TvMagazinPk pkNew = new TvMagazinPk(); + // set pkNew.channel to the unmerged copy. + pkNew.channel = channel; + pkNew.presenter = presenter; + // the following fails because there is already a managed channel + tvMagazin = session.get( TvMagazin.class, pkNew ); + } + ); + } + + @Test + public void testSecondaryTableWithCompositeId(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Channel channel = new Channel(); + session.persist( channel ); + Presenter pres = new Presenter(); + pres.name = "Tim Russet"; + session.persist( pres ); + TvMagazinPk pk = new TvMagazinPk(); + TvProgram program = new TvProgram(); + program.time = new Date(); + program.id = pk; + program.text = "Award Winning Programming"; + pk.channel = channel; + pk.presenter = pres; + session.persist( program ); + session.getTransaction().commit(); + session.clear(); + session.beginTransaction(); + program = (TvProgram) session.createQuery( "from TvProgram pr" ).uniqueResult(); + assertNotNull( program.id ); + assertNotNull( program.id.channel ); + assertEquals( channel.id, program.id.channel.id ); + assertNotNull( program.id.presenter ); + assertNotNull( program.text ); + assertEquals( pres.name, program.id.presenter.name ); + session.delete( program ); + session.delete( program.id.channel ); + session.delete( program.id.presenter ); + } + ); + } + + @Test + public void testSecondaryTableWithIdClass(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Channel channel = new Channel(); + session.persist( channel ); + Presenter pres = new Presenter(); + pres.name = "Bob"; + session.persist( pres ); + TvProgramIdClass program = new TvProgramIdClass(); + program.time = new Date(); + program.channel = channel; + program.presenter = pres; + program.text = "Jump the shark programming"; + session.persist( program ); + session.getTransaction().commit(); + session.clear(); + session.beginTransaction(); + program = (TvProgramIdClass) session.createQuery( "from TvProgramIdClass pr" ).uniqueResult(); + assertNotNull( program.channel ); + assertEquals( channel.id, program.channel.id ); + assertNotNull( program.presenter ); + assertNotNull( program.text ); + assertEquals( pres.name, program.presenter.name ); + session.delete( program ); + session.delete( program.channel ); + session.delete( program.presenter ); + } + ); + } + + @Test + @FailureExpected(reason = "Criteria add IdClass id as predicate value has not yet been implemented") + public void testQueryInAndComposite(SessionFactoryScope scope) { + + scope.inTransaction( + s -> { + createData( s ); + s.flush(); + List ids = new ArrayList( 2 ); + ids.add( new SomeEntityId( 1, 12 ) ); + ids.add( new SomeEntityId( 10, 23 ) ); + + CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder(); + CriteriaQuery criteria = criteriaBuilder.createQuery( SomeEntity.class ); + Root root = criteria.from( SomeEntity.class ); + CriteriaBuilder.In inPredicate = criteriaBuilder.in( root.get( "id" ) ); + criteria.where( criteriaBuilder.or( inPredicate.value( ids ) ) ); + List list = s.createQuery( criteria ).list(); + +// Criteria criteria = s.createCriteria( SomeEntity.class ); +// Disjunction disjunction = Restrictions.disjunction(); +// +// disjunction.add( Restrictions.in( "id", ids ) ); +// criteria.add( disjunction ); +// +// List list = criteria.list(); + assertEquals( 2, list.size() ); + } + ); + } + + @Test + public void testQueryInAndCompositeWithHQL(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + createData( session ); + session.flush(); + List ids = new ArrayList<>( 2 ); + ids.add( new SomeEntityId( 1, 12 ) ); + ids.add( new SomeEntityId( 10, 23 ) ); + ids.add( new SomeEntityId( 10, 22 ) ); + Query query = session.createQuery( "from SomeEntity e where e.id in (:idList)" ); + query.setParameterList( "idList", ids ); + List list = query.list(); + assertEquals( 3, list.size() ); + } + ); + } + + private void createData(Session s) { + SomeEntity someEntity = new SomeEntity(); + someEntity.setId( new SomeEntityId() ); + someEntity.getId().setId( 1 ); + someEntity.getId().setVersion( 11 ); + someEntity.setProp( "aa" ); + s.persist( someEntity ); + + someEntity = new SomeEntity(); + someEntity.setId( new SomeEntityId() ); + someEntity.getId().setId( 1 ); + someEntity.getId().setVersion( 12 ); + someEntity.setProp( "bb" ); + s.persist( someEntity ); + + someEntity = new SomeEntity(); + someEntity.setId( new SomeEntityId() ); + someEntity.getId().setId( 10 ); + someEntity.getId().setVersion( 21 ); + someEntity.setProp( "cc1" ); + s.persist( someEntity ); + + someEntity = new SomeEntity(); + someEntity.setId( new SomeEntityId() ); + someEntity.getId().setId( 10 ); + someEntity.getId().setVersion( 22 ); + someEntity.setProp( "cc2" ); + s.persist( someEntity ); + + someEntity = new SomeEntity(); + someEntity.setId( new SomeEntityId() ); + someEntity.getId().setId( 10 ); + someEntity.getId().setVersion( 23 ); + someEntity.setProp( "cc3" ); + s.persist( someEntity ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/LittleGenius.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/LittleGenius.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/LittleGenius.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/LittleGenius.java index 40183c43e6..5f3d5b3db3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/LittleGenius.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/LittleGenius.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.PrimaryKeyJoinColumns; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Order.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Order.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Order.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Order.java index d836face56..3d4093e7ad 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Order.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Order.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLine.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/OrderLine.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLine.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/OrderLine.java index aa1a9fa29c..9fdd5b29d6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLine.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/OrderLine.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLinePk.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/OrderLinePk.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLinePk.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/OrderLinePk.java index 86df0251eb..e0d0d3ad0b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLinePk.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/OrderLinePk.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Parent.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Parent.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Parent.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Parent.java index 499002b08a..f274152eb3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Parent.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Parent.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.EmbeddedId; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/ParentPk.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/ParentPk.java index 16c1fc47a2..a3885dc196 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/ParentPk.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; import javax.persistence.Column; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Presenter.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Presenter.java similarity index 89% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Presenter.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Presenter.java index f7d3a30f44..2fdb682360 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Presenter.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Presenter.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Product.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Product.java similarity index 89% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Product.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Product.java index 5406087499..092a8ef071 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/Product.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/Product.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/SomeEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/SomeEntity.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/SomeEntity.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/SomeEntity.java index 3d8b4dd898..637327430d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/SomeEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/SomeEntity.java @@ -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 . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/SomeEntityId.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/SomeEntityId.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/SomeEntityId.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/SomeEntityId.java index d4fc2839da..ca6530f649 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/SomeEntityId.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/SomeEntityId.java @@ -4,7 +4,8 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; + import java.io.Serializable; import javax.persistence.Embeddable; @@ -27,10 +28,6 @@ public class SomeEntityId implements Serializable { super(); } - /** - * @param i - * @param j - */ public SomeEntityId(int id, int version) { super(); this.id = id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvMagazin.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvMagazin.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvMagazin.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvMagazin.java index ce914faeab..d20d8c33c9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvMagazin.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvMagazin.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.util.Date; import javax.persistence.AssociationOverride; import javax.persistence.AssociationOverrides; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvMagazinPk.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvMagazinPk.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvMagazinPk.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvMagazinPk.java index 48142f1288..1206dfc448 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvMagazinPk.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvMagazinPk.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.io.Serializable; import javax.persistence.Embeddable; import javax.persistence.JoinColumn; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgram.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvProgram.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgram.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvProgram.java index 3435ebe838..25b406599a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgram.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvProgram.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.util.Date; import javax.persistence.AssociationOverride; import javax.persistence.AssociationOverrides; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgramIdClass.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvProgramIdClass.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgramIdClass.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvProgramIdClass.java index 8fc0baf394..f58b401504 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgramIdClass.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cid/TvProgramIdClass.java @@ -6,7 +6,7 @@ */ //$Id$ -package org.hibernate.test.annotations.cid; +package org.hibernate.orm.test.annotations.cid; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java deleted file mode 100644 index 470461bf2d..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java +++ /dev/null @@ -1,526 +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 . - */ -package org.hibernate.test.annotations.cid; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; - -import org.junit.Test; - -import org.hibernate.query.Query; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -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.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * test some composite id functionalities - * - * @author Emmanuel Bernard - */ -public class CompositeIdTest extends BaseCoreFunctionalTestCase { - @Test - public void testOneToOneInCompositePk() throws Exception { - Session s; - Transaction tx; - s = openSession(); - tx = s.beginTransaction(); - B b = new B(); - C c = new C(); - s.persist( b ); - s.persist( c ); - A a = new A(); - a.setAId( new AId() ); - a.getAId().setB( b ); - a.getAId().setC( c ); - s.persist( a ); - s.flush(); - s.clear(); - - a = (A) s.get(A.class, a.getAId() ); - assertEquals( b.getId(), a.getAId().getB().getId() ); - - tx.rollback(); - s.close(); - } - - - /** - * This feature is not supported by the EJB3 - * this is an hibernate extension - */ - @Test - public void testManyToOneInCompositePk() throws Exception { - Session s; - Transaction tx; - s = openSession(); - tx = s.beginTransaction(); - ParentPk ppk = new ParentPk(); - ppk.setFirstName( "Emmanuel" ); - ppk.setLastName( "Bernard" ); - Parent p = new Parent(); - p.id = ppk; - s.persist( p ); - ChildPk cpk = new ChildPk(); - cpk.parent = p; - cpk.nthChild = 1; - Child c = new Child(); - c.id = cpk; - s.persist( c ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - Query q = s.createQuery( "select c from Child c where c.id.nthChild = :nth" ); - q.setParameter( "nth", 1 ); - List results = q.list(); - assertEquals( 1, results.size() ); - c = (Child) results.get( 0 ); - assertNotNull( c ); - assertNotNull( c.id.parent ); - //FIXME mke it work in unambigious cases - // assertNotNull(c.id.parent.id); - // assertEquals(p.id.getFirstName(), c.id.parent.id.getFirstName()); - s.delete( c ); - s.delete( c.id.parent ); - tx.commit(); - s.close(); - } - - @Test - @TestForIssue( jiraKey = "HHH-10476") - public void testManyToOneInCompositePkInPC() throws Exception { - Session s; - Transaction tx; - s = openSession(); - tx = s.beginTransaction(); - ParentPk ppk = new ParentPk(); - ppk.setFirstName( "Emmanuel" ); - ppk.setLastName( "Bernard" ); - Parent p = new Parent(); - p.id = ppk; - s.persist( p ); - ChildPk cpk = new ChildPk(); - cpk.parent = p; - cpk.nthChild = 1; - Child c = new Child(); - c.id = cpk; - s.persist( c ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - p = (Parent) s.get( Parent.class, ppk); - // p.id should be ppk. - assertSame( ppk, p.id ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - c = (Child) s.get( Child.class, cpk ); - // c.id should be cpk - assertSame( cpk, c.id ); - // only Child should be in PC (c.id.parent should not be in PC) - SessionImplementor sessionImplementor = (SessionImplementor) s; - assertTrue( sessionImplementor.getPersistenceContext().isEntryFor( c ) ); - assertFalse( sessionImplementor.getPersistenceContext().isEntryFor( c.id.parent ) ); - tx.commit(); - s.close(); - } - - /** - * This feature is not supported by the EJB3 - * this is an hibernate extension - */ - @Test - public void testManyToOneInCompositePkAndSubclass() throws Exception { - Session s; - Transaction tx; - s = openSession(); - tx = s.beginTransaction(); - ParentPk ppk = new ParentPk(); - ppk.setFirstName( "Emmanuel" ); - ppk.setLastName( "Bernard" ); - Parent p = new Parent(); - p.id = ppk; - s.persist( p ); - ChildPk cpk = new ChildPk(); - cpk.parent = p; - cpk.nthChild = 1; - LittleGenius c = new LittleGenius(); - c.particularSkill = "Human Annotation parser"; - c.id = cpk; - s.persist( c ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - Query q = s.createQuery( "select c from Child c where c.id.nthChild = :nth" ); - q.setParameter( "nth", 1 ); - List results = q.list(); - assertEquals( 1, results.size() ); - c = (LittleGenius) results.get( 0 ); - assertNotNull( c ); - assertNotNull( c.id.parent ); - //FIXME mke it work in unambigious cases -// assertNotNull(c.id.parent.id); -// assertEquals(p.id.getFirstName(), c.id.parent.id.getFirstName()); - s.delete( c ); - s.delete( c.id.parent ); - tx.commit(); - s.close(); - } - - @Test - public void testManyToOneInCompositeId() throws Exception { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Channel channel = new Channel(); - s.persist( channel ); - Presenter pres = new Presenter(); - pres.name = "Casimir"; - s.persist( pres ); - TvMagazinPk pk = new TvMagazinPk(); - TvMagazin mag = new TvMagazin(); - mag.time = new Date(); - mag.id = pk; - pk.channel = channel; - pk.presenter = pres; - s.persist( mag ); - tx.commit(); - s.clear(); - tx = s.beginTransaction(); - mag = (TvMagazin) s.createQuery( "from TvMagazin mag" ).uniqueResult(); - assertNotNull( mag.id ); - assertNotNull( mag.id.channel ); - assertEquals( channel.id, mag.id.channel.id ); - assertNotNull( mag.id.presenter ); - assertEquals( pres.name, mag.id.presenter.name ); - s.delete( mag ); - s.delete( mag.id.channel ); - s.delete( mag.id.presenter ); - tx.commit(); - s.close(); - } - - @Test - public void testManyToOneInCompositeIdClass() throws Exception { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Order order = new Order(); - s.persist( order ); - Product product = new Product(); - product.name = "small car"; - s.persist( product ); - OrderLine orderLine = new OrderLine(); - orderLine.order = order; - orderLine.product = product; - s.persist( orderLine ); - s.flush(); - s.clear(); - - orderLine = (OrderLine) s.createQuery( "select ol from OrderLine ol" ).uniqueResult(); - assertNotNull( orderLine.order ); - assertEquals( order.id, orderLine.order.id ); - assertNotNull( orderLine.product ); - assertEquals( product.name, orderLine.product.name ); - - tx.rollback(); - s.close(); - } - - @Test - @TestForIssue(jiraKey = "HHH-10476") - public void testManyToOneInCompositeIdClassInPC() throws Exception { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Order order = new Order(); - s.persist( order ); - Product product = new Product(); - product.name = "small car"; - s.persist( product ); - OrderLine orderLine = new OrderLine(); - orderLine.order = order; - orderLine.product = product; - s.persist( orderLine ); - s.flush(); - s.clear(); - - s.clear(); - OrderLinePk orderLinePK = new OrderLinePk(); - orderLinePK.order = orderLine.order; - orderLinePK.product = orderLine.product; - orderLine = (OrderLine) s.get( OrderLine.class, orderLinePK ); - assertTrue( orderLine.order != orderLinePK.order ); - assertTrue( orderLine.product != orderLinePK.product ); - SessionImplementor sessionImplementor = (SessionImplementor) s; - assertTrue( sessionImplementor.getPersistenceContext().isEntryFor( orderLine ) ); - assertTrue( sessionImplementor.getPersistenceContext().isEntryFor( orderLine.order ) ); - assertTrue( sessionImplementor.getPersistenceContext().isEntryFor( orderLine.product ) ); - assertFalse( sessionImplementor.getPersistenceContext().isEntryFor( orderLinePK.order ) ); - assertFalse( sessionImplementor.getPersistenceContext().isEntryFor( orderLinePK.product ) ); - tx.rollback(); - s.close(); - } - - @Test - @TestForIssue(jiraKey = "HHH-10476") - public void testGetWithUpdatedDetachedEntityInCompositeID() throws Exception { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Channel channel = new Channel(); - Presenter presenter = new Presenter(); - presenter.name = "Jane"; - TvMagazin tvMagazin = new TvMagazin(); - tvMagazin.id = new TvMagazinPk(); - tvMagazin.id.channel = channel; - tvMagazin.id.presenter = presenter; - s.persist( channel ); - s.persist( presenter ); - s.persist( tvMagazin ); - s.flush(); - - s.clear(); - // update channel - channel.name = "chnl"; - TvMagazinPk pkNew = new TvMagazinPk(); - // set pkNew.channel to the unmerged copy. - pkNew.channel = channel; - pkNew.presenter = presenter; - // the following fails because there is already a managed channel - tvMagazin = s.get( TvMagazin.class, pkNew ); - channel = s.get( Channel.class, channel.id ); - assertNull( channel.name ); - s.flush(); - s.clear(); - - // make sure that channel.name is still null - channel = s.get( Channel.class, channel.id ); - assertNull( channel.name ); - - tx.rollback(); - s.close(); - } - - @Test - @TestForIssue(jiraKey = "HHH-10476") - public void testGetWithDetachedEntityInCompositeIDWithManagedCopy() throws Exception { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Channel channel = new Channel(); - Presenter presenter = new Presenter(); - presenter.name = "Jane"; - TvMagazin tvMagazin = new TvMagazin(); - tvMagazin.id = new TvMagazinPk(); - tvMagazin.id.channel = channel; - tvMagazin.id.presenter = presenter; - s.persist( channel ); - s.persist( presenter ); - s.persist( tvMagazin ); - s.flush(); - - s.clear(); - // merge channel to put channel back in PersistenceContext - s.merge( channel ); - TvMagazinPk pkNew = new TvMagazinPk(); - // set pkNew.channel to the unmerged copy. - pkNew.channel = channel; - pkNew.presenter = presenter; - // the following fails because there is already a managed channel - tvMagazin = s.get( TvMagazin.class, pkNew ); - tx.rollback(); - s.close(); - } - - @Test - public void testSecondaryTableWithCompositeId() throws Exception { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Channel channel = new Channel(); - s.persist( channel ); - Presenter pres = new Presenter(); - pres.name = "Tim Russet"; - s.persist( pres ); - TvMagazinPk pk = new TvMagazinPk(); - TvProgram program = new TvProgram(); - program.time = new Date(); - program.id = pk; - program.text = "Award Winning Programming"; - pk.channel = channel; - pk.presenter = pres; - s.persist( program ); - tx.commit(); - s.clear(); - tx = s.beginTransaction(); - program = (TvProgram) s.createQuery( "from TvProgram pr" ).uniqueResult(); - assertNotNull( program.id ); - assertNotNull( program.id.channel ); - assertEquals( channel.id, program.id.channel.id ); - assertNotNull( program.id.presenter ); - assertNotNull( program.text ); - assertEquals( pres.name, program.id.presenter.name ); - s.delete( program ); - s.delete( program.id.channel ); - s.delete( program.id.presenter ); - tx.commit(); - s.close(); - } - - @Test - public void testSecondaryTableWithIdClass() throws Exception { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Channel channel = new Channel(); - s.persist( channel ); - Presenter pres = new Presenter(); - pres.name = "Bob"; - s.persist( pres ); - TvProgramIdClass program = new TvProgramIdClass(); - program.time = new Date(); - program.channel = channel; - program.presenter = pres; - program.text = "Jump the shark programming"; - s.persist( program ); - tx.commit(); - s.clear(); - tx = s.beginTransaction(); - program = (TvProgramIdClass) s.createQuery( "from TvProgramIdClass pr" ).uniqueResult(); - assertNotNull( program.channel ); - assertEquals( channel.id, program.channel.id ); - assertNotNull( program.presenter ); - assertNotNull( program.text ); - assertEquals( pres.name, program.presenter.name ); - s.delete( program ); - s.delete( program.channel ); - s.delete( program.presenter ); - tx.commit(); - s.close(); - } - - @Test - public void testQueryInAndComposite() { - - inTransaction( - s -> { - createData( s ); - s.flush(); - List ids = new ArrayList(2); - ids.add( new SomeEntityId(1,12) ); - ids.add( new SomeEntityId(10,23) ); - - CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder(); - CriteriaQuery criteria = criteriaBuilder.createQuery( SomeEntity.class ); - Root root = criteria.from( SomeEntity.class ); - criteria.where( criteriaBuilder.or( criteriaBuilder.in( root.get( "id" )).value( ids) ) ); - List list = s.createQuery( criteria ).list(); - -// Criteria criteria = s.createCriteria( SomeEntity.class ); -// Disjunction disjunction = Restrictions.disjunction(); -// -// disjunction.add( Restrictions.in( "id", ids ) ); -// criteria.add( disjunction ); -// -// List list = criteria.list(); - assertEquals( 2, list.size() ); - } - ); - } - - @Test - public void testQueryInAndCompositeWithHQL() { - Session s = openSession( ); - Transaction transaction = s.beginTransaction(); - createData( s ); - s.flush(); - List ids = new ArrayList(2); - ids.add( new SomeEntityId(1,12) ); - ids.add( new SomeEntityId(10,23) ); - ids.add( new SomeEntityId(10,22) ); - Query query=s.createQuery( "from SomeEntity e where e.id in :idList" ); - query.setParameterList( "idList", ids ); - List list=query.list(); - assertEquals( 3, list.size() ); - transaction.rollback(); - s.close(); - } - - private void createData(Session s){ - SomeEntity someEntity = new SomeEntity(); - someEntity.setId( new SomeEntityId( ) ); - someEntity.getId().setId( 1 ); - someEntity.getId().setVersion( 11 ); - someEntity.setProp( "aa" ); - s.persist( someEntity ); - - someEntity = new SomeEntity(); - someEntity.setId( new SomeEntityId( ) ); - someEntity.getId().setId( 1 ); - someEntity.getId().setVersion( 12 ); - someEntity.setProp( "bb" ); - s.persist( someEntity ); - - someEntity = new SomeEntity(); - someEntity.setId( new SomeEntityId( ) ); - someEntity.getId().setId( 10 ); - someEntity.getId().setVersion( 21 ); - someEntity.setProp( "cc1" ); - s.persist( someEntity ); - - someEntity = new SomeEntity(); - someEntity.setId( new SomeEntityId( ) ); - someEntity.getId().setId( 10 ); - someEntity.getId().setVersion( 22 ); - someEntity.setProp( "cc2" ); - s.persist( someEntity ); - - someEntity = new SomeEntity(); - someEntity.setId( new SomeEntityId( ) ); - someEntity.getId().setId( 10 ); - someEntity.getId().setVersion( 23 ); - someEntity.setProp( "cc3" ); - s.persist( someEntity ); - } - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { - Parent.class, - Child.class, - Channel.class, - TvMagazin.class, - TvProgramIdClass.class, - TvProgram.class, - Presenter.class, - Order.class, - Product.class, - OrderLine.class, - OrderLinePk.class, - LittleGenius.class, - A.class, - B.class, - C.class, - SomeEntity.class - }; - } -}