From 8db97094082e7d20303408e3d9ecb6a0ab02ca1d Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 28 Jul 2020 18:32:34 +0100 Subject: [PATCH] Fix @ElementCollection + @OrderBy with Inheritance --- .../AbstractCompositeIdentifierMapping.java | 5 - .../internal/EntityCollectionPart.java | 7 + .../mapping/ordering/ast/ColumnReference.java | 39 +- .../ordering/ast/PluralAttributePath.java | 17 +- .../entity/AbstractEntityPersister.java | 8 + .../entity/JoinedSubclassEntityPersister.java | 58 +-- .../AbstractEmbeddableInitializer.java | 38 +- .../DefaultNamingCollectionElementTest.java | 345 ++++++++---------- .../OrderByColumnNameTest.java | 147 ++++++++ .../collectionelement/OrderByTest.java | 152 ++++---- .../collectionelement/Products.java | 1 - .../collectionelement/Widgets.java | 15 + .../withcustomenumdef/TestBasicOps.java | 65 ++-- 13 files changed, 512 insertions(+), 385 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByColumnNameTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java index f0d6f3d35d..7754cacc51 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java @@ -211,11 +211,6 @@ public Object instantiate() { return getEntityMapping().getRepresentationStrategy().getInstantiator().instantiate( sessionFactory ); } - @Override - public SingularAttributeMapping getParentInjectionAttributeMapping() { - return null; - } - @Override public EntityMappingType findContainingEntityMapping() { return entityMapping; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java index 8e908ba534..7307ae78d3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java @@ -13,6 +13,7 @@ import org.hibernate.mapping.Collection; import org.hibernate.mapping.Value; import org.hibernate.metamodel.mapping.CollectionPart; +import org.hibernate.metamodel.mapping.ColumnConsumer; import org.hibernate.metamodel.mapping.EntityAssociationMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; @@ -168,6 +169,12 @@ public DomainResult createDomainResult( throw new NotYetImplementedFor6Exception( getClass() ); } + + @Override + public void visitColumns(ColumnConsumer consumer) { + entityMappingType.visitColumns( consumer ); + } + @Override public void applySqlSelections( NavigablePath navigablePath, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/ColumnReference.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/ColumnReference.java index 7fe73a0754..5b0d336653 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/ColumnReference.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/ColumnReference.java @@ -7,18 +7,24 @@ package org.hibernate.metamodel.mapping.ordering.ast; import org.hibernate.SortOrder; +import org.hibernate.metamodel.mapping.MappingType; +import org.hibernate.metamodel.mapping.ModelPartContainer; +import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.ordering.TranslationContext; +import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.query.NavigablePath; import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableReference; +import org.hibernate.sql.ast.tree.from.TableReferenceJoin; import org.hibernate.sql.ast.tree.select.QuerySpec; import org.hibernate.sql.ast.tree.select.SortSpecification; /** * Represents a column-reference used in an order-by fragment * + * @author Steve Ebersole * @apiNote This is Hibernate-specific feature. For {@link javax.persistence.OrderBy} (JPA) * all path references are expected to be domain paths (attributes). * @@ -58,16 +64,18 @@ public void apply( String collation, SortOrder sortOrder, SqlAstCreationState creationState) { - final TableReference primaryTableReference = tableGroup.getPrimaryTableReference(); + TableReference tableReference; + + tableReference = getTableReference( tableGroup ); final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver(); ast.addSortSpecification( new SortSpecification( sqlExpressionResolver.resolveSqlExpression( - SqlExpressionResolver.createColumnReferenceKey( primaryTableReference, columnExpression ), + SqlExpressionResolver.createColumnReferenceKey( tableReference, columnExpression ), sqlAstProcessingState -> new org.hibernate.sql.ast.tree.expression.ColumnReference( - tableGroup.getPrimaryTableReference(), + tableReference, columnExpression, isColumnExpressionFormula, // because these ordering fragments are only ever part of the order-by clause, there @@ -81,4 +89,29 @@ public void apply( ) ); } + + TableReference getTableReference(TableGroup tableGroup) { + ModelPartContainer modelPart = tableGroup.getModelPart(); + if ( modelPart instanceof PluralAttributeMapping ) { + MappingType partMappingType = ( (PluralAttributeMapping) modelPart ).getElementDescriptor() + .getPartMappingType(); + if ( partMappingType instanceof AbstractEntityPersister ) { + AbstractEntityPersister abstractEntityPersister = (AbstractEntityPersister) partMappingType; + int i = abstractEntityPersister.determineTableNumberForColumn( columnExpression ); + String tableName = abstractEntityPersister.getTableName( i ); + for ( TableReferenceJoin tableReferenceJoin : tableGroup.getTableReferenceJoins() ) { + final TableReference joinedTableReference = tableReferenceJoin.getJoinedTableReference(); + if ( joinedTableReference.getTableExpression() + .equals( tableName ) ) { + return joinedTableReference; + } + } + } + else { + return tableGroup.getPrimaryTableReference(); + } + } + return null; + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/PluralAttributePath.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/PluralAttributePath.java index 08c90be6e0..6917d83e0e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/PluralAttributePath.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/PluralAttributePath.java @@ -52,8 +52,21 @@ public DomainPath resolvePathPart( final ModelPart subPart = pluralAttributeMapping.findSubPart( name, null ); if ( subPart != null ) { - assert subPart instanceof CollectionPart; - return new CollectionPartPath( this, (CollectionPart) subPart ); + if ( subPart instanceof CollectionPart ) { + return new CollectionPartPath( this, (CollectionPart) subPart ); + } + else if ( !( subPart instanceof EmbeddableValuedModelPart ) ) { + final CollectionPartPath elementPath = new CollectionPartPath( + this, + pluralAttributeMapping.getElementDescriptor() + ); + + return new DomainPathContinuation( + elementPath.getNavigablePath().append( name ), + this, + pluralAttributeMapping.getElementDescriptor() + ); + } } // the above checks for explicit element or index descriptor references 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 bbc22e6c11..b64aa3fe99 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 @@ -133,6 +133,7 @@ import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMetadata; import org.hibernate.metamodel.mapping.AttributeMetadataAccess; +import org.hibernate.metamodel.mapping.ColumnConsumer; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -6441,6 +6442,13 @@ public void visitSuperTypeAttributeMappings(Consumer action) { } } + @Override + public void visitColumns(ColumnConsumer consumer) { + getAttributeMappings().forEach( + attributeMapping -> attributeMapping.visitColumns( consumer ) + ); + } + @Override public void visitSubTypeAttributeMappings(Consumer action) { if ( subclassMappingTypes != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 7d96c2e0ac..64d1fccbff 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -1241,7 +1241,7 @@ public TableGroup createRootTableGroup( @Override public EntityDiscriminatorMapping getDiscriminatorMapping(TableGroup tableGroup) { - if(hasSubclasses()) { + if ( hasSubclasses() ) { if ( explicitDiscriminatorColumnName == null ) { CaseSearchedExpressionInfo info = getCaseSearchedExpression( tableGroup ); return new JoinedSubclassDiscriminatorMappingImpl( @@ -1291,34 +1291,38 @@ private CaseSearchedExpressionInfo getCaseSearchedExpression(TableGroup entityTa final BasicType discriminatorType = (BasicType) getDiscriminatorType(); final CaseSearchedExpression caseSearchedExpression = new CaseSearchedExpression( discriminatorType ); - discriminatorValuesByTableName.forEach( - (tableName, discriminatorValue) -> { - if ( ! primaryTableReference.getTableExpression().equals( tableName ) ) { - TableReference tableReference = entityTableGroup.getTableReference( tableName ); - if ( tableReference == null ) { - // we have not yet created a TableReference for this sub-class table, but we need to because - // it has a discriminator value associated with it - tableReference = entityTableGroup.resolveTableReference( tableName ); - } - - final ColumnReference identifierColumnReference = getIdentifierColumnReference( tableReference ); - info.columnReferences.add( identifierColumnReference ); - addWhen( - caseSearchedExpression, - tableReference, - identifierColumnReference, - discriminatorType - ); - } + Boolean addPrimaryTableCaseAsLastCaseExpression = false; + for ( String tableName : discriminatorValuesByTableName.keySet() ) { + if ( !primaryTableReference.getTableExpression().equals( tableName ) ) { + TableReference tableReference = entityTableGroup.getTableReference( tableName ); + if ( tableReference == null ) { + // we have not yet created a TableReference for this sub-class table, but we need to because + // it has a discriminator value associated with it + tableReference = entityTableGroup.resolveTableReference( tableName ); } - ); - addWhen( - caseSearchedExpression, - primaryTableReference, - getIdentifierColumnReference( primaryTableReference ), - discriminatorType - ); + final ColumnReference identifierColumnReference = getIdentifierColumnReference( tableReference ); + info.columnReferences.add( identifierColumnReference ); + addWhen( + caseSearchedExpression, + tableReference, + identifierColumnReference, + discriminatorType + ); + } + else { + addPrimaryTableCaseAsLastCaseExpression = true; + } + } + + if ( addPrimaryTableCaseAsLastCaseExpression ) { + addWhen( + caseSearchedExpression, + primaryTableReference, + getIdentifierColumnReference( primaryTableReference ), + discriminatorType + ); + } info.caseSearchedExpression = caseSearchedExpression; return info; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java index eaf86e5a57..df8a0663df 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java @@ -93,29 +93,25 @@ public Object getCompositeInstance() { @Override public void resolveKey(RowProcessingState rowProcessingState) { - // todo (6.0) : register "parent resolution listener" if the composite is defined for `@Parent` - // something like: - final PropertyAccess parentInjectionPropertyAccess = embeddedModelPartDescriptor.getParentInjectionAttributePropertyAccess(); - if ( parentInjectionPropertyAccess != null ) { - if ( getFetchParentAccess() != null ) { - getFetchParentAccess().findFirstEntityDescriptorAccess().registerResolutionListener( - // todo (6.0) : this is the legacy behavior - // - the first entity is injected as the parent, even if the composite - // is defined on another composite - owner -> { - if ( compositeInstance == null ) { - return; - } - parentInjectionPropertyAccess.getSetter().set( - compositeInstance, - owner, - rowProcessingState.getSession().getFactory() - ); + final FetchParentAccess fetchParentAccess = getFetchParentAccess(); + if ( parentInjectionPropertyAccess != null && fetchParentAccess != null ) { + fetchParentAccess.findFirstEntityDescriptorAccess().registerResolutionListener( + // todo (6.0) : this is the legacy behavior + // - the first entity is injected as the parent, even if the composite + // is defined on another composite + owner -> { + if ( compositeInstance == null ) { + return; } - ); - } + parentInjectionPropertyAccess.getSetter().set( + compositeInstance, + owner, + rowProcessingState.getSession().getFactory() + ); + } + ); } } @@ -137,7 +133,7 @@ public void initializeInstance(RowProcessingState rowProcessingState) { final PropertyAccess parentInjectionPropertyAccess = embeddedModelPartDescriptor.getParentInjectionAttributePropertyAccess(); - if ( parentInjectionPropertyAccess != null && getFetchParentAccess() == null ) { + if ( parentInjectionPropertyAccess != null ) { Initializer initializer = rowProcessingState.resolveInitializer( navigablePath.getParent() ); final Object owner; if ( initializer instanceof CollectionInitializer ) { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/DefaultNamingCollectionElementTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/DefaultNamingCollectionElementTest.java index 6936bc2f6e..8e53b365ab 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/DefaultNamingCollectionElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/DefaultNamingCollectionElementTest.java @@ -12,7 +12,6 @@ import java.util.Locale; import org.hibernate.Filter; -import org.hibernate.Transaction; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.cfg.AvailableSettings; import org.hibernate.mapping.Collection; @@ -65,144 +64,114 @@ public void testSimpleElement(SessionFactoryScope scope) { scope.getMetadataImplementor().getCollectionBinding( Boy.class.getName() + '.' + "favoriteNumbers" ) .getCollectionTable().getName() ); - scope.inSession( + + scope.inTransaction( session -> { - Transaction transaction = session.getTransaction(); - try { - transaction.begin(); - - Boy boy = new Boy(); - boy.setFirstName( "John" ); - boy.setLastName( "Doe" ); - boy.getNickNames().add( "Johnny" ); - boy.getNickNames().add( "Thing" ); - boy.getScorePerNickName().put( "Johnny", 3 ); - boy.getScorePerNickName().put( "Thing", 5 ); - int[] favNbrs = new int[4]; - for ( int index = 0; index < favNbrs.length - 1; index++ ) { - favNbrs[index] = index * 3; - } - boy.setFavoriteNumbers( favNbrs ); - boy.getCharacters().add( Character.GENTLE ); - boy.getCharacters().add( Character.CRAFTY ); - - HashMap foods = new HashMap<>(); - foods.put( "breakfast", FavoriteFood.PIZZA ); - foods.put( "lunch", FavoriteFood.KUNGPAOCHICKEN ); - foods.put( "dinner", FavoriteFood.SUSHI ); - boy.setFavoriteFood( foods ); - session.persist( boy ); - transaction.commit(); - - session.clear(); - transaction = session.beginTransaction(); - boy = session.get( Boy.class, boy.getId() ); - assertNotNull( boy.getNickNames() ); - assertTrue( boy.getNickNames().contains( "Thing" ) ); - assertNotNull( boy.getScorePerNickName() ); - assertTrue( boy.getScorePerNickName().containsKey( "Thing" ) ); - assertEquals( Integer.valueOf( 5 ), boy.getScorePerNickName().get( "Thing" ) ); - assertNotNull( boy.getFavoriteNumbers() ); - assertEquals( 3, boy.getFavoriteNumbers()[1] ); - assertTrue( boy.getCharacters().contains( Character.CRAFTY ) ); - assertTrue( boy.getFavoriteFood().get( "dinner" ).equals( FavoriteFood.SUSHI ) ); - assertTrue( boy.getFavoriteFood().get( "lunch" ).equals( FavoriteFood.KUNGPAOCHICKEN ) ); - assertTrue( boy.getFavoriteFood().get( "breakfast" ).equals( FavoriteFood.PIZZA ) ); - List result = session.createQuery( - "select boy from Boy boy join boy.nickNames names where names = :name" ) - .setParameter( "name", "Thing" ).list(); - assertEquals( 1, result.size() ); - session.delete( boy ); - - transaction.commit(); - } - finally { - if ( transaction.isActive() ) { - transaction.rollback(); - } + Boy boy = new Boy(); + boy.setFirstName( "John" ); + boy.setLastName( "Doe" ); + boy.getNickNames().add( "Johnny" ); + boy.getNickNames().add( "Thing" ); + boy.getScorePerNickName().put( "Johnny", 3 ); + boy.getScorePerNickName().put( "Thing", 5 ); + int[] favNbrs = new int[4]; + for ( int index = 0; index < favNbrs.length - 1; index++ ) { + favNbrs[index] = index * 3; } + boy.setFavoriteNumbers( favNbrs ); + boy.getCharacters().add( Character.GENTLE ); + boy.getCharacters().add( Character.CRAFTY ); + + HashMap foods = new HashMap<>(); + foods.put( "breakfast", FavoriteFood.PIZZA ); + foods.put( "lunch", FavoriteFood.KUNGPAOCHICKEN ); + foods.put( "dinner", FavoriteFood.SUSHI ); + boy.setFavoriteFood( foods ); + session.persist( boy ); + + session.getTransaction().commit(); + + session.clear(); + + session.beginTransaction(); + boy = session.get( Boy.class, boy.getId() ); + assertNotNull( boy.getNickNames() ); + assertTrue( boy.getNickNames().contains( "Thing" ) ); + assertNotNull( boy.getScorePerNickName() ); + assertTrue( boy.getScorePerNickName().containsKey( "Thing" ) ); + assertEquals( Integer.valueOf( 5 ), boy.getScorePerNickName().get( "Thing" ) ); + assertNotNull( boy.getFavoriteNumbers() ); + assertEquals( 3, boy.getFavoriteNumbers()[1] ); + assertTrue( boy.getCharacters().contains( Character.CRAFTY ) ); + assertTrue( boy.getFavoriteFood().get( "dinner" ).equals( FavoriteFood.SUSHI ) ); + assertTrue( boy.getFavoriteFood().get( "lunch" ).equals( FavoriteFood.KUNGPAOCHICKEN ) ); + assertTrue( boy.getFavoriteFood().get( "breakfast" ).equals( FavoriteFood.PIZZA ) ); + List result = session.createQuery( + "select boy from Boy boy join boy.nickNames names where names = :name" ) + .setParameter( "name", "Thing" ).list(); + assertEquals( 1, result.size() ); + session.delete( boy ); } ); } @Test public void testCompositeElement(SessionFactoryScope scope) { - scope.inSession( + scope.inTransaction( session -> { - Transaction transaction = session.getTransaction(); - try { - transaction.begin(); + Boy boy = new Boy(); + boy.setFirstName( "John" ); + boy.setLastName( "Doe" ); + Toy toy = new Toy(); + toy.setName( "Balloon" ); + toy.setSerial( "serial001" ); + toy.setBrand( new Brand() ); + toy.getBrand().setName( "Bandai" ); + boy.getFavoriteToys().add( toy ); + session.persist( boy ); + session.getTransaction().commit(); - Boy boy = new Boy(); - boy.setFirstName( "John" ); - boy.setLastName( "Doe" ); - Toy toy = new Toy(); - toy.setName( "Balloon" ); - toy.setSerial( "serial001" ); - toy.setBrand( new Brand() ); - toy.getBrand().setName( "Bandai" ); - boy.getFavoriteToys().add( toy ); - session.persist( boy ); - transaction.commit(); + session.clear(); - session.clear(); - - transaction = session.beginTransaction(); - boy = session.get( Boy.class, boy.getId() ); - assertNotNull( boy ); - assertNotNull( boy.getFavoriteToys() ); - assertTrue( boy.getFavoriteToys().contains( toy ) ); - Toy next = boy.getFavoriteToys().iterator().next(); - assertEquals( boy, next.getOwner(), "@Parent is failing" ); - session.delete( boy ); - transaction.commit(); - } - finally { - if ( transaction.isActive() ) { - transaction.rollback(); - } - } + session.beginTransaction(); + boy = session.get( Boy.class, boy.getId() ); + assertNotNull( boy ); + assertNotNull( boy.getFavoriteToys() ); + assertTrue( boy.getFavoriteToys().contains( toy ) ); + Toy next = boy.getFavoriteToys().iterator().next(); + assertEquals( boy, next.getOwner(), "@Parent is failing" ); + session.delete( boy ); } ); } @Test public void testAttributedJoin(SessionFactoryScope scope) { - scope.inSession( + scope.inTransaction( session -> { - Transaction transaction = session.getTransaction(); - try { - transaction.begin(); - Country country = new Country(); - country.setName( "Australia" ); - session.persist( country ); + Country country = new Country(); + country.setName( "Australia" ); + session.persist( country ); - Boy boy = new Boy(); - boy.setFirstName( "John" ); - boy.setLastName( "Doe" ); - CountryAttitude attitude = new CountryAttitude(); - // TODO: doesn't work - attitude.setBoy( boy ); - attitude.setCountry( country ); - attitude.setLikes( true ); - boy.getCountryAttitudes().add( attitude ); - session.persist( boy ); - transaction.commit(); + Boy boy = new Boy(); + boy.setFirstName( "John" ); + boy.setLastName( "Doe" ); + CountryAttitude attitude = new CountryAttitude(); + // TODO: doesn't work + attitude.setBoy( boy ); + attitude.setCountry( country ); + attitude.setLikes( true ); + boy.getCountryAttitudes().add( attitude ); + session.persist( boy ); + session.getTransaction().commit(); - session.clear(); + session.clear(); - transaction = session.beginTransaction(); - boy = session.get( Boy.class, boy.getId() ); - assertTrue( boy.getCountryAttitudes().contains( attitude ) ); - session.delete( boy ); - session.delete( session.get( Country.class, country.getId() ) ); - transaction.commit(); - } - finally { - if ( transaction.isActive() ) { - transaction.rollback(); - } - } + session.beginTransaction(); + boy = session.get( Boy.class, boy.getId() ); + assertTrue( boy.getCountryAttitudes().contains( attitude ) ); + session.delete( boy ); + session.delete( session.get( Country.class, country.getId() ) ); } ); } @@ -214,113 +183,85 @@ public void testLazyCollectionofElements(SessionFactoryScope scope) { scope.getMetadataImplementor().getCollectionBinding( Boy.class.getName() + '.' + "favoriteNumbers" ) .getCollectionTable().getName() ); - scope.inSession( + + scope.inTransaction( session -> { - Transaction transaction = session.getTransaction(); - try { - transaction.begin(); - Boy boy = new Boy(); - boy.setFirstName( "John" ); - boy.setLastName( "Doe" ); - boy.getNickNames().add( "Johnny" ); - boy.getNickNames().add( "Thing" ); - boy.getScorePerNickName().put( "Johnny", 3 ); - boy.getScorePerNickName().put( "Thing", 5 ); - int[] favNbrs = new int[4]; - for ( int index = 0; index < favNbrs.length - 1; index++ ) { - favNbrs[index] = index * 3; - } - boy.setFavoriteNumbers( favNbrs ); - boy.getCharacters().add( Character.GENTLE ); - boy.getCharacters().add( Character.CRAFTY ); - session.persist( boy ); - transaction.commit(); - - session.clear(); - - transaction = session.beginTransaction(); - boy = session.get( Boy.class, boy.getId() ); - assertNotNull( boy.getNickNames() ); - assertTrue( boy.getNickNames().contains( "Thing" ) ); - assertNotNull( boy.getScorePerNickName() ); - assertTrue( boy.getScorePerNickName().containsKey( "Thing" ) ); - assertEquals( new Integer( 5 ), boy.getScorePerNickName().get( "Thing" ) ); - assertNotNull( boy.getFavoriteNumbers() ); - assertEquals( 3, boy.getFavoriteNumbers()[1] ); - assertTrue( boy.getCharacters().contains( Character.CRAFTY ) ); - List result = session.createQuery( - "select boy from Boy boy join boy.nickNames names where names = :name" ) - .setParameter( "name", "Thing" ).list(); - assertEquals( 1, result.size() ); - session.delete( boy ); - transaction.commit(); - } - finally { - if ( transaction.isActive() ) { - transaction.rollback(); - } + Boy boy = new Boy(); + boy.setFirstName( "John" ); + boy.setLastName( "Doe" ); + boy.getNickNames().add( "Johnny" ); + boy.getNickNames().add( "Thing" ); + boy.getScorePerNickName().put( "Johnny", 3 ); + boy.getScorePerNickName().put( "Thing", 5 ); + int[] favNbrs = new int[4]; + for ( int index = 0; index < favNbrs.length - 1; index++ ) { + favNbrs[index] = index * 3; } + boy.setFavoriteNumbers( favNbrs ); + boy.getCharacters().add( Character.GENTLE ); + boy.getCharacters().add( Character.CRAFTY ); + session.persist( boy ); + session.getTransaction().commit(); + + session.clear(); + + session.beginTransaction(); + boy = session.get( Boy.class, boy.getId() ); + assertNotNull( boy.getNickNames() ); + assertTrue( boy.getNickNames().contains( "Thing" ) ); + assertNotNull( boy.getScorePerNickName() ); + assertTrue( boy.getScorePerNickName().containsKey( "Thing" ) ); + assertEquals( new Integer( 5 ), boy.getScorePerNickName().get( "Thing" ) ); + assertNotNull( boy.getFavoriteNumbers() ); + assertEquals( 3, boy.getFavoriteNumbers()[1] ); + assertTrue( boy.getCharacters().contains( Character.CRAFTY ) ); + List result = session.createQuery( + "select boy from Boy boy join boy.nickNames names where names = :name" ) + .setParameter( "name", "Thing" ).list(); + assertEquals( 1, result.size() ); + session.delete( boy ); } ); } @Test public void testFetchEagerAndFilter(SessionFactoryScope scope) { - scope.inSession( + scope.inTransaction( session -> { - Transaction tx = session.beginTransaction(); - try { - TestCourse test = new TestCourse(); + TestCourse test = new TestCourse(); - LocalizedString title = new LocalizedString( "title in english" ); - title.getVariations().put( Locale.FRENCH.getLanguage(), "title en francais" ); - test.setTitle( title ); - session.save( test ); + LocalizedString title = new LocalizedString( "title in english" ); + title.getVariations().put( Locale.FRENCH.getLanguage(), "title en francais" ); + test.setTitle( title ); + session.save( test ); - session.flush(); - session.clear(); + session.flush(); + session.clear(); - Filter filter = session.enableFilter( "selectedLocale" ); - filter.setParameter( "param", "fr" ); + Filter filter = session.enableFilter( "selectedLocale" ); + filter.setParameter( "param", "fr" ); - Query q = session.createQuery( "from TestCourse t" ); - List l = q.list(); - assertEquals( 1, l.size() ); + Query q = session.createQuery( "from TestCourse t" ); + List l = q.list(); + assertEquals( 1, l.size() ); - TestCourse t = session.get( TestCourse.class, test.getTestCourseId() ); - assertEquals( 1, t.getTitle().getVariations().size() ); - - tx.rollback(); - } - finally { - if ( tx.isActive() ) { - tx.rollback(); - } - } + TestCourse t = session.get( TestCourse.class, test.getTestCourseId() ); + assertEquals( 1, t.getTitle().getVariations().size() ); } ); } @Test public void testMapKeyType(SessionFactoryScope scope) { - - scope.inSession( + scope.inTransaction( session -> { Matrix m = new Matrix(); m.getMvalues().put( 1, 1.1f ); - Transaction tx = session.beginTransaction(); - try { - session.persist( m ); - session.flush(); - session.clear(); - m = session.get( Matrix.class, m.getId() ); - assertEquals( 1.1f, m.getMvalues().get( 1 ), 0.01f ); - } - finally { - if ( tx.isActive() ) { - tx.rollback(); - } - } + session.persist( m ); + session.flush(); + session.clear(); + m = session.get( Matrix.class, m.getId() ); + assertEquals( 1.1f, m.getMvalues().get( 1 ), 0.01f ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByColumnNameTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByColumnNameTest.java new file mode 100644 index 0000000000..15228c579f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByColumnNameTest.java @@ -0,0 +1,147 @@ +/* + * 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.collectionelement; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.OrderBy; + +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.assertTrue; + + +@DomainModel( + annotatedClasses = { + org.hibernate.orm.test.annotations.collectionelement.OrderByColumnNameTest.Product.class, + org.hibernate.orm.test.annotations.collectionelement.OrderByColumnNameTest.Widgets.class, + org.hibernate.orm.test.annotations.collectionelement.OrderByColumnNameTest.Widget1.class, + org.hibernate.orm.test.annotations.collectionelement.OrderByColumnNameTest.Widget2.class, + } +) +@SessionFactory +public class OrderByColumnNameTest { + + @Test + public void testOrderByName(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Product p = new Product(); + HashSet set = new HashSet<>(); + + Widgets widget = new Widgets(); + widget.setName( "hammer" ); + set.add( widget ); + session.persist( widget ); + + widget = new Widgets(); + widget.setName( "axel" ); + set.add( widget ); + session.persist( widget ); + + widget = new Widgets(); + widget.setName( "screwdriver" ); + set.add( widget ); + session.persist( widget ); + + p.setWidgets( set ); + session.persist( p ); + session.getTransaction().commit(); + + session.beginTransaction(); + session.clear(); + p = session.get( Product.class, p.getId() ); + assertTrue( p.getWidgets().size() == 3, "has three Widgets" ); + Iterator iter = p.getWidgets().iterator(); + assertEquals( "axel", ( (Widgets) iter.next() ).getName() ); + assertEquals( "hammer", ( (Widgets) iter.next() ).getName() ); + assertEquals( "screwdriver", ( (Widgets) iter.next() ).getName() ); + } + ); + } + + @Entity + public static class Product { + @Id + @GeneratedValue + private Integer id; + + @ElementCollection + @OrderBy("name_1 ASC") + private Set widgets; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Set getWidgets() { + return widgets; + } + + public void setWidgets(Set widgets) { + this.widgets = widgets; + } + } + + @Entity + @Inheritance(strategy = InheritanceType.JOINED) + public static class Widgets { + private String name; + private int id; + + public Widgets() { + + } + + @Column(name = "name_1") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Id + @GeneratedValue + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + } + + @Entity + public static class Widget1 extends org.hibernate.orm.test.annotations.collectionelement.Widgets { + private String name1; + } + + @Entity + public static class Widget2 extends org.hibernate.orm.test.annotations.collectionelement.Widgets { + private String name2; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByTest.java index 839dd3ffea..32410633c9 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/OrderByTest.java @@ -9,7 +9,6 @@ import java.util.HashSet; import java.util.Iterator; -import org.hibernate.Transaction; import org.hibernate.dialect.TeradataDialect; import org.hibernate.testing.orm.junit.DomainModel; @@ -26,6 +25,8 @@ annotatedClasses = { Products.class, Widgets.class, + Widgets.Widget1.class, + Widgets.Widget2.class, BugSystem.class } ) @@ -34,49 +35,38 @@ public class OrderByTest { @Test public void testOrderByName(SessionFactoryScope scope) { - scope.inSession( + scope.inTransaction( session -> { - Transaction tx = session.beginTransaction(); - try { + Products p = new Products(); + HashSet set = new HashSet<>(); - Products p = new Products(); - HashSet set = new HashSet<>(); + Widgets widget = new Widgets(); + widget.setName( "hammer" ); + set.add( widget ); + session.persist( widget ); - Widgets widget = new Widgets(); - widget.setName( "hammer" ); - set.add( widget ); - session.persist( widget ); + widget = new Widgets(); + widget.setName( "axel" ); + set.add( widget ); + session.persist( widget ); - widget = new Widgets(); - widget.setName( "axel" ); - set.add( widget ); - session.persist( widget ); + widget = new Widgets(); + widget.setName( "screwdriver" ); + set.add( widget ); + session.persist( widget ); - widget = new Widgets(); - widget.setName( "screwdriver" ); - set.add( widget ); - session.persist( widget ); + p.setWidgets( set ); + session.persist( p ); + session.getTransaction().commit(); - p.setWidgets( set ); - session.persist( p ); - tx.commit(); - - tx = session.beginTransaction(); - session.clear(); - p = session.get( Products.class, p.getId() ); - assertTrue( p.getWidgets().size() == 3, "has three Widgets" ); - Iterator iter = p.getWidgets().iterator(); - assertEquals( "axel", ( (Widgets) iter.next() ).getName() ); - assertEquals( "hammer", ( (Widgets) iter.next() ).getName() ); - assertEquals( "screwdriver", ( (Widgets) iter.next() ).getName() ); - tx.commit(); - } - catch (Exception e) { - if ( tx.isActive() ) { - tx.rollback(); - } - throw e; - } + session.beginTransaction(); + session.clear(); + p = session.get( Products.class, p.getId() ); + assertTrue( p.getWidgets().size() == 3, "has three Widgets" ); + Iterator iter = p.getWidgets().iterator(); + assertEquals( "axel", ( (Widgets) iter.next() ).getName() ); + assertEquals( "hammer", ( (Widgets) iter.next() ).getName() ); + assertEquals( "screwdriver", ( (Widgets) iter.next() ).getName() ); } ); } @@ -88,60 +78,50 @@ public void testOrderByName(SessionFactoryScope scope) { reason = "HHH-8190, uses Teradata reserved word - summary" ) public void testOrderByWithDottedNotation(SessionFactoryScope scope) { - scope.inSession( + scope.inTransaction( session -> { - Transaction tx = session.beginTransaction(); - try { - BugSystem bs = new BugSystem(); - HashSet set = new HashSet<>(); + BugSystem bs = new BugSystem(); + HashSet set = new HashSet<>(); - Bug bug = new Bug(); - bug.setDescription( "JPA-2 locking" ); - bug.setSummary( "JPA-2 impl locking" ); - Person p = new Person(); - p.setFirstName( "Scott" ); - p.setLastName( "Marlow" ); - bug.setReportedBy( p ); - set.add( bug ); + Bug bug = new Bug(); + bug.setDescription( "JPA-2 locking" ); + bug.setSummary( "JPA-2 impl locking" ); + Person p = new Person(); + p.setFirstName( "Scott" ); + p.setLastName( "Marlow" ); + bug.setReportedBy( p ); + set.add( bug ); - bug = new Bug(); - bug.setDescription( "JPA-2 annotations" ); - bug.setSummary( "JPA-2 impl annotations" ); - p = new Person(); - p.setFirstName( "Emmanuel" ); - p.setLastName( "Bernard" ); - bug.setReportedBy( p ); - set.add( bug ); + bug = new Bug(); + bug.setDescription( "JPA-2 annotations" ); + bug.setSummary( "JPA-2 impl annotations" ); + p = new Person(); + p.setFirstName( "Emmanuel" ); + p.setLastName( "Bernard" ); + bug.setReportedBy( p ); + set.add( bug ); - bug = new Bug(); - bug.setDescription( "Implement JPA-2 criteria" ); - bug.setSummary( "JPA-2 impl criteria" ); - p = new Person(); - p.setFirstName( "Steve" ); - p.setLastName( "Ebersole" ); - bug.setReportedBy( p ); - set.add( bug ); + bug = new Bug(); + bug.setDescription( "Implement JPA-2 criteria" ); + bug.setSummary( "JPA-2 impl criteria" ); + p = new Person(); + p.setFirstName( "Steve" ); + p.setLastName( "Ebersole" ); + bug.setReportedBy( p ); + set.add( bug ); - bs.setBugs( set ); - session.persist( bs ); - tx.commit(); + bs.setBugs( set ); + session.persist( bs ); + session.getTransaction().commit(); - tx = session.beginTransaction(); - session.clear(); - bs = session.get( BugSystem.class, bs.getId() ); - assertTrue( bs.getBugs().size() == 3, "has three bugs" ); - Iterator iter = bs.getBugs().iterator(); - assertEquals( "Emmanuel", ( (Bug) iter.next() ).getReportedBy().getFirstName() ); - assertEquals( "Steve", ( (Bug) iter.next() ).getReportedBy().getFirstName() ); - assertEquals( "Scott", ( (Bug) iter.next() ).getReportedBy().getFirstName() ); - tx.commit(); - } - catch (Exception e) { - if ( tx.isActive() ) { - tx.rollback(); - } - throw e; - } + session.beginTransaction(); + session.clear(); + bs = session.get( BugSystem.class, bs.getId() ); + assertTrue( bs.getBugs().size() == 3, "has three bugs" ); + Iterator iter = bs.getBugs().iterator(); + assertEquals( "Emmanuel", ( (Bug) iter.next() ).getReportedBy().getFirstName() ); + assertEquals( "Steve", ( (Bug) iter.next() ).getReportedBy().getFirstName() ); + assertEquals( "Scott", ( (Bug) iter.next() ).getReportedBy().getFirstName() ); } ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Products.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Products.java index 5bb5fbe8a0..be28d4b1eb 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Products.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Products.java @@ -39,5 +39,4 @@ public Set getWidgets() { public void setWidgets(Set widgets) { this.widgets = widgets; } - } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Widgets.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Widgets.java index 4209b57caa..73841ab2ec 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Widgets.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/Widgets.java @@ -5,11 +5,15 @@ * See the lgpl.txt file in the root directory or . */ package org.hibernate.orm.test.annotations.collectionelement; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; @Entity +@Inheritance(strategy = InheritanceType.JOINED) public class Widgets { private String name; private int id; @@ -18,6 +22,7 @@ public Widgets() { } + @Column(name = "name_1") public String getName() { return name; } @@ -36,4 +41,14 @@ public void setId(int id) { this.id = id; } + @Entity + public static class Widget1 extends Widgets{ + private String name1; + } + + @Entity + public static class Widget2 extends Widgets{ + private String name2; + } } + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java index cbb1b7a152..b914af1aa6 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java @@ -33,9 +33,8 @@ public class TestBasicOps { public void testLoadAndStore(SessionFactoryScope scope) { Query q = new Query( new Location( "first", Location.Type.COUNTY ) ); scope.inTransaction( - session -> { - session.save( q ); - } + session -> + session.save( q ) ); scope.inTransaction( @@ -52,47 +51,37 @@ public void testLoadAndStore(SessionFactoryScope scope) { @Test @TestForIssue(jiraKey = "HHH-7072") public void testEmbeddableWithNullables(SessionFactoryScope scope) { - scope.inSession( + scope.inTransaction( session -> { + Query q = new Query( new Location( null, Location.Type.COMMUNE ) ); + session.save( q ); + session.getTransaction().commit(); + session.clear(); + Transaction transaction = session.beginTransaction(); - try { - Query q = new Query( new Location( null, Location.Type.COMMUNE ) ); - session.save( q ); - transaction.commit(); - session.clear(); + q.getIncludedLocations().add( new Location( null, Location.Type.COUNTY ) ); + session.update( q ); + transaction.commit(); + session.clear(); - transaction = session.beginTransaction(); - q.getIncludedLocations().add( new Location( null, Location.Type.COUNTY ) ); - session.update( q ); - transaction.commit(); - session.clear(); - - transaction = session.beginTransaction(); - q = (Query) session.get( Query.class, q.getId() ); + transaction = session.beginTransaction(); + q = session.get( Query.class, q.getId() ); // assertEquals( 2, q.getIncludedLocations().size() ); - transaction.commit(); - session.clear(); + transaction.commit(); + session.clear(); - transaction = session.beginTransaction(); - Iterator itr = q.getIncludedLocations().iterator(); - itr.next(); - itr.remove(); - session.update( q ); - transaction.commit(); - session.clear(); + transaction = session.beginTransaction(); + Iterator itr = q.getIncludedLocations().iterator(); + itr.next(); + itr.remove(); + session.update( q ); + transaction.commit(); + session.clear(); - transaction = session.beginTransaction(); - q = (Query) session.get( Query.class, q.getId() ); - assertEquals( 1, q.getIncludedLocations().size() ); - session.delete( q ); - transaction.commit(); - } - catch (Exception e) { - if ( transaction.isActive() ) { - transaction.rollback(); - } - throw e; - } + session.beginTransaction(); + q = session.get( Query.class, q.getId() ); + assertEquals( 1, q.getIncludedLocations().size() ); + session.delete( q ); } ); }