Merge remote-tracking branch 'upstream/master' into wip/6.0_merge_26
This commit is contained in:
commit
3476e82122
|
@ -345,6 +345,28 @@ public class H2Dialect extends Dialect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not drop constraints explicitly, just do this by cascading instead.
|
||||||
|
@Override
|
||||||
|
public boolean dropConstraints() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCascadeConstraintsString() {
|
||||||
|
return " CASCADE ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASCADE has to be AFTER IF EXISTS in case it's after the tablename
|
||||||
|
@Override
|
||||||
|
public boolean supportsIfExistsAfterTableName() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsIfExistsBeforeTableName() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||||
return new H2IdentityColumnSupport();
|
return new H2IdentityColumnSupport();
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.hql.internal.ast.tree;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||||
|
import org.hibernate.hql.internal.ast.SqlASTFactory;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.Joinable;
|
||||||
|
import org.hibernate.persister.entity.PropertyMapping;
|
||||||
|
import org.hibernate.type.CollectionType;
|
||||||
|
import org.hibernate.type.CompositeType;
|
||||||
|
import org.hibernate.type.EntityType;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
import antlr.SemanticException;
|
||||||
|
import antlr.collections.AST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CollectionPathNode extends SqlNode {
|
||||||
|
/**
|
||||||
|
* Used to resolve the collection "owner key" columns
|
||||||
|
*/
|
||||||
|
private final FromElement ownerFromElement;
|
||||||
|
|
||||||
|
private final CollectionPersister collectionDescriptor;
|
||||||
|
|
||||||
|
private final String collectionPropertyName;
|
||||||
|
private final String collectionPropertyPath;
|
||||||
|
private final String collectionQueryPath;
|
||||||
|
|
||||||
|
private final HqlSqlWalker walker;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a `CollectionPathNode`
|
||||||
|
*
|
||||||
|
* @see #from(AST, AST, HqlSqlWalker)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public CollectionPathNode(
|
||||||
|
FromElement ownerFromElement,
|
||||||
|
CollectionPersister collectionDescriptor,
|
||||||
|
String collectionPropertyName,
|
||||||
|
String collectionQueryPath,
|
||||||
|
String collectionPropertyPath,
|
||||||
|
HqlSqlWalker walker) {
|
||||||
|
this.ownerFromElement = ownerFromElement;
|
||||||
|
this.collectionDescriptor = collectionDescriptor;
|
||||||
|
this.collectionPropertyName = collectionPropertyName;
|
||||||
|
this.collectionQueryPath = collectionQueryPath;
|
||||||
|
this.collectionPropertyPath = collectionPropertyPath;
|
||||||
|
this.walker = walker;
|
||||||
|
|
||||||
|
walker.addQuerySpaces( collectionDescriptor.getCollectionSpaces() );
|
||||||
|
|
||||||
|
super.setType( SqlASTFactory.COLL_PATH );
|
||||||
|
super.setDataType( collectionDescriptor.getCollectionType() );
|
||||||
|
super.setText( collectionDescriptor.getRole() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for `CollectionPathNode` instances
|
||||||
|
*
|
||||||
|
* @param qualifier The left-hand-side of a dot-ident node - may be null to indicate an ident arg
|
||||||
|
* @param reference The right-hand-side of the dot-ident or the ident that is an unqualified reference
|
||||||
|
*/
|
||||||
|
public static CollectionPathNode from(
|
||||||
|
AST qualifier,
|
||||||
|
AST reference,
|
||||||
|
HqlSqlWalker walker) {
|
||||||
|
|
||||||
|
final String referenceName = reference.getText();
|
||||||
|
final String referenceQueryPath;
|
||||||
|
|
||||||
|
if ( qualifier == null ) {
|
||||||
|
// If there is no qualifier it means the argument to `size()` was a simple IDENT node as opposed to a DOT-IDENT
|
||||||
|
// node. In this case, `reference` could technically be a join alias. This is not JPA
|
||||||
|
// compliant, but is a Hibernate-specific extension
|
||||||
|
|
||||||
|
referenceQueryPath = referenceName;
|
||||||
|
|
||||||
|
final FromElement byAlias = walker.getCurrentFromClause().getFromElement( referenceName );
|
||||||
|
|
||||||
|
if ( byAlias != null ) {
|
||||||
|
final FromElement ownerRef = byAlias.getOrigin();
|
||||||
|
final QueryableCollection collectionDescriptor = byAlias.getQueryableCollection();
|
||||||
|
|
||||||
|
return new CollectionPathNode(
|
||||||
|
ownerRef,
|
||||||
|
collectionDescriptor,
|
||||||
|
referenceName,
|
||||||
|
referenceQueryPath,
|
||||||
|
referenceName,
|
||||||
|
walker
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we (should) have an unqualified plural-attribute name - look through all of the defined from-elements
|
||||||
|
// and look for one that exposes that property
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
final List<FromElement> fromElements = walker.getCurrentFromClause().getExplicitFromElements();
|
||||||
|
|
||||||
|
if ( fromElements.size() == 1 ) {
|
||||||
|
final FromElement ownerRef = fromElements.get( 0 );
|
||||||
|
|
||||||
|
final PropertyMapping collectionPropertyMapping = ownerRef.getPropertyMapping( referenceName );
|
||||||
|
|
||||||
|
//noinspection RedundantClassCall
|
||||||
|
if ( ! CollectionType.class.isInstance( collectionPropertyMapping.getType() ) ) {
|
||||||
|
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
||||||
|
}
|
||||||
|
|
||||||
|
final CollectionType collectionType = (CollectionType) collectionPropertyMapping.getType();
|
||||||
|
|
||||||
|
return new CollectionPathNode(
|
||||||
|
ownerRef,
|
||||||
|
walker.getSessionFactoryHelper().requireQueryableCollection( collectionType.getRole() ),
|
||||||
|
referenceName,
|
||||||
|
referenceQueryPath,
|
||||||
|
referenceName,
|
||||||
|
walker
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FromElement discoveredQualifier = null;
|
||||||
|
|
||||||
|
//noinspection ForLoopReplaceableByForEach
|
||||||
|
for ( int i = 0; i < fromElements.size(); i++ ) {
|
||||||
|
final FromElement fromElement = fromElements.get( i );
|
||||||
|
try {
|
||||||
|
final PropertyMapping propertyMapping = fromElement.getPropertyMapping( referenceName );
|
||||||
|
//noinspection RedundantClassCall
|
||||||
|
if ( ! CollectionType.class.isInstance( propertyMapping.getType() ) ) {
|
||||||
|
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
||||||
|
}
|
||||||
|
|
||||||
|
discoveredQualifier = fromElement;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
// try the next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( discoveredQualifier == null ) {
|
||||||
|
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
||||||
|
}
|
||||||
|
|
||||||
|
final FromElement ownerRef = discoveredQualifier;
|
||||||
|
|
||||||
|
final PropertyMapping collectionPropertyMapping = ownerRef.getPropertyMapping( referenceName );
|
||||||
|
|
||||||
|
//noinspection RedundantClassCall
|
||||||
|
if ( ! CollectionType.class.isInstance( collectionPropertyMapping.getType() ) ) {
|
||||||
|
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
||||||
|
}
|
||||||
|
|
||||||
|
final CollectionType collectionType = (CollectionType) collectionPropertyMapping.getType();
|
||||||
|
|
||||||
|
return new CollectionPathNode(
|
||||||
|
ownerRef,
|
||||||
|
walker.getSessionFactoryHelper().requireQueryableCollection( collectionType.getRole() ),
|
||||||
|
referenceName,
|
||||||
|
referenceQueryPath,
|
||||||
|
referenceName,
|
||||||
|
walker
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we have a dot-ident structure
|
||||||
|
final FromReferenceNode qualifierFromReferenceNode = (FromReferenceNode) qualifier;
|
||||||
|
|
||||||
|
final String qualifierQueryPath = ( (FromReferenceNode) qualifier ).getPath();
|
||||||
|
referenceQueryPath = qualifierQueryPath + "." + reference;
|
||||||
|
|
||||||
|
try {
|
||||||
|
qualifierFromReferenceNode.resolve( false, false );
|
||||||
|
}
|
||||||
|
catch (SemanticException e) {
|
||||||
|
throw new QueryException( "Unable to resolve collection-path qualifier : " + qualifierQueryPath, e );
|
||||||
|
}
|
||||||
|
|
||||||
|
final Type qualifierType = qualifierFromReferenceNode.getDataType();
|
||||||
|
final FromElement ownerRef = ( (FromReferenceNode) qualifier ).getFromElement();
|
||||||
|
|
||||||
|
final CollectionType collectionType;
|
||||||
|
final String referenceMappedPath;
|
||||||
|
|
||||||
|
if ( qualifierType instanceof CompositeType ) {
|
||||||
|
final CompositeType qualifierCompositeType = (CompositeType) qualifierType;
|
||||||
|
final int collectionPropertyIndex = (qualifierCompositeType).getPropertyIndex( referenceName );
|
||||||
|
collectionType = (CollectionType) qualifierCompositeType.getSubtypes()[collectionPropertyIndex];
|
||||||
|
|
||||||
|
if ( ownerRef instanceof ComponentJoin ) {
|
||||||
|
referenceMappedPath = ( (ComponentJoin) ownerRef ).getComponentPath() + "." + referenceName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
referenceMappedPath = qualifierQueryPath.substring( qualifierQueryPath.indexOf( "." ) + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( qualifierType instanceof EntityType ) {
|
||||||
|
final EntityType qualifierEntityType = (EntityType) qualifierType;
|
||||||
|
final String entityName = qualifierEntityType.getAssociatedEntityName();
|
||||||
|
final EntityPersister entityPersister = walker.getSessionFactoryHelper().findEntityPersisterByName( entityName );
|
||||||
|
final int propertyIndex = entityPersister.getEntityMetamodel().getPropertyIndex( referenceName );
|
||||||
|
collectionType = (CollectionType) entityPersister.getPropertyTypes()[ propertyIndex ];
|
||||||
|
referenceMappedPath = referenceName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new QueryException( "Unexpected collection-path reference qualifier type : " + qualifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CollectionPathNode(
|
||||||
|
( (FromReferenceNode) qualifier ).getFromElement(),
|
||||||
|
walker.getSessionFactoryHelper().requireQueryableCollection( collectionType.getRole() ),
|
||||||
|
referenceName,
|
||||||
|
referenceQueryPath,
|
||||||
|
referenceMappedPath,
|
||||||
|
walker
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public FromElement getCollectionOwnerFromElement() {
|
||||||
|
return ownerFromElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public CollectionPersister getCollectionDescriptor() {
|
||||||
|
return collectionDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the collection property - e.g. `theCollection`
|
||||||
|
*/
|
||||||
|
public String getCollectionPropertyName() {
|
||||||
|
return collectionPropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The collection property path relative to the "owning entity" in the mapping model - e.g. `theCollection`
|
||||||
|
* or `someEmbeddable.theCollection`.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public String getCollectionPropertyPath() {
|
||||||
|
return collectionPropertyPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "full" path. E.g. `a.theCollection` or `a.someEmbeddable.theCollection`
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public String getCollectionQueryPath() {
|
||||||
|
return collectionQueryPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public String[] resolveOwnerKeyColumnExpressions() {
|
||||||
|
final AST ast = walker.getAST();
|
||||||
|
final String ownerTableAlias;
|
||||||
|
if ( ast instanceof DeleteStatement || ast instanceof UpdateStatement ) {
|
||||||
|
ownerTableAlias = ownerFromElement.getTableName();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ownerTableAlias = ownerFromElement.getTableAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
final String lhsPropertyName = collectionDescriptor.getCollectionType().getLHSPropertyName();
|
||||||
|
if ( lhsPropertyName == null ) {
|
||||||
|
return StringHelper.qualify(
|
||||||
|
ownerTableAlias,
|
||||||
|
( (Joinable) collectionDescriptor.getOwnerEntityPersister() ).getKeyColumnNames()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ownerFromElement.toColumns( ownerTableAlias, lhsPropertyName, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.hql.internal.ast.tree;
|
||||||
|
|
||||||
|
import org.hibernate.AssertionFailure;
|
||||||
|
import org.hibernate.hql.internal.NameGenerator;
|
||||||
|
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.persister.collection.CollectionPropertyMapping;
|
||||||
|
import org.hibernate.persister.collection.CollectionPropertyNames;
|
||||||
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CollectionSizeNode extends SqlNode implements SelectExpression {
|
||||||
|
private static final Logger log = Logger.getLogger( CollectionSizeNode.class );
|
||||||
|
|
||||||
|
private final CollectionPathNode collectionPathNode;
|
||||||
|
private final CollectionPropertyMapping collectionPropertyMapping;
|
||||||
|
|
||||||
|
private String alias;
|
||||||
|
|
||||||
|
public CollectionSizeNode(CollectionPathNode collectionPathNode) {
|
||||||
|
this.collectionPathNode = collectionPathNode;
|
||||||
|
this.collectionPropertyMapping = new CollectionPropertyMapping( (QueryableCollection) collectionPathNode.getCollectionDescriptor() );
|
||||||
|
|
||||||
|
setType( HqlSqlTokenTypes.COLL_SIZE );
|
||||||
|
setDataType( StandardBasicTypes.INTEGER );
|
||||||
|
setText( "collection-size" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public CollectionPathNode getCollectionPathNode() {
|
||||||
|
return collectionPathNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toSqlExpression() {
|
||||||
|
final FromElement collectionOwnerFromElement = collectionPathNode.getCollectionOwnerFromElement();
|
||||||
|
final QueryableCollection collectionDescriptor = (QueryableCollection) collectionPathNode.getCollectionDescriptor();
|
||||||
|
|
||||||
|
// generate subquery in the form:
|
||||||
|
//
|
||||||
|
// select count( alias_.<collection-key-column> )
|
||||||
|
// from <collection-table> as alias_
|
||||||
|
// where <owner-key-column> = alias_.<collection-key-column>
|
||||||
|
|
||||||
|
// Note that `collectionPropertyMapping.toColumns(.., COLLECTION_SIZE)` returns the complete `count(...)` SQL
|
||||||
|
// expression, hence he expectation for a single expression regardless of the number of columns in the key.
|
||||||
|
|
||||||
|
final String collectionTableAlias = collectionOwnerFromElement.getFromClause()
|
||||||
|
.getAliasGenerator()
|
||||||
|
.createName( collectionPathNode.getCollectionPropertyName() );
|
||||||
|
|
||||||
|
final String[] ownerKeyColumns = collectionPathNode.resolveOwnerKeyColumnExpressions();
|
||||||
|
final String[] collectionKeyColumns = StringHelper.qualify( collectionTableAlias, collectionDescriptor.getKeyColumnNames() );
|
||||||
|
|
||||||
|
if ( collectionKeyColumns.length != ownerKeyColumns.length ) {
|
||||||
|
throw new AssertionFailure( "Mismatch between collection key columns" );
|
||||||
|
}
|
||||||
|
|
||||||
|
final String[] sizeColumns = this.collectionPropertyMapping.toColumns(
|
||||||
|
collectionTableAlias,
|
||||||
|
CollectionPropertyNames.COLLECTION_SIZE
|
||||||
|
);
|
||||||
|
assert sizeColumns.length == 1;
|
||||||
|
final String sizeColumn = sizeColumns[0];
|
||||||
|
|
||||||
|
final StringBuilder buffer = new StringBuilder( "(select " ).append( sizeColumn );
|
||||||
|
buffer.append( " from " ).append( collectionDescriptor.getTableName() ).append( " " ).append( collectionTableAlias );
|
||||||
|
buffer.append( " where " );
|
||||||
|
|
||||||
|
boolean firstPass = true;
|
||||||
|
for ( int i = 0; i < ownerKeyColumns.length; i++ ) {
|
||||||
|
if ( firstPass ) {
|
||||||
|
firstPass = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer.append( " and " );
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append( ownerKeyColumns[i] ).append( " = " ).append( collectionKeyColumns[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append( ")" );
|
||||||
|
|
||||||
|
if ( scalarName != null ) {
|
||||||
|
buffer.append( " as " ).append( scalarName );
|
||||||
|
}
|
||||||
|
|
||||||
|
final String subQuery = buffer.toString();
|
||||||
|
|
||||||
|
log.debugf(
|
||||||
|
"toSqlExpression( size(%s) ) -> %s",
|
||||||
|
collectionPathNode.getCollectionQueryPath(),
|
||||||
|
subQuery
|
||||||
|
);
|
||||||
|
|
||||||
|
return subQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// SelectExpression
|
||||||
|
|
||||||
|
private String scalarName;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScalarColumnText(int i) {
|
||||||
|
log.debugf( "setScalarColumnText(%s)", i );
|
||||||
|
scalarName = NameGenerator.scalarName( i, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScalarColumn(int i) {
|
||||||
|
log.debugf( "setScalarColumn(%s)", i );
|
||||||
|
setScalarColumnText( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getScalarColumnIndex() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FromElement getFromElement() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConstructor() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReturnableEntity() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isScalar() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.transaction.TransactionUtil;
|
import org.hibernate.testing.transaction.TransactionUtil;
|
||||||
|
import org.hibernate.testing.transaction.TransactionUtil2;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
@ -96,6 +97,18 @@ public class ComponentInWhereClauseTest extends BaseEntityManagerFunctionalTestC
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeExpressionForTheOneToManyPropertyOfAComponentHql() {
|
||||||
|
TransactionUtil2.inTransaction(
|
||||||
|
entityManagerFactory(),
|
||||||
|
session -> {
|
||||||
|
final String hql = "from Employee e where size( e.projects.previousProjects ) = 2";
|
||||||
|
final List resultsList = session.createQuery( hql ).list();
|
||||||
|
assertThat( resultsList.size(), is( 1 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSizeExpressionForTheElementCollectionPropertyOfAComponent() {
|
public void testSizeExpressionForTheElementCollectionPropertyOfAComponent() {
|
||||||
TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> {
|
TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
|
|
@ -0,0 +1,384 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.test.hql.size;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
|
||||||
|
@TestForIssue( jiraKey = "HHH-13619" )
|
||||||
|
public class ManyToManySizeTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsRestriction() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select c.id from Company c where size( c.customers ) = 0"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
assertThat( results.get( 0 ), is( 0 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsCompoundSelectExpression() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select c.id, c.name, size( c.customers )" +
|
||||||
|
" from Company c" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 3 ) );
|
||||||
|
|
||||||
|
final Object[] first = (Object[]) results.get( 0 );
|
||||||
|
assertThat( first[ 0 ], is( 0 ) );
|
||||||
|
assertThat( first[ 2 ], is( 0 ) );
|
||||||
|
|
||||||
|
final Object[] second = (Object[]) results.get( 1 );
|
||||||
|
assertThat( second[ 0 ], is( 1 ) );
|
||||||
|
assertThat( second[ 2 ], is( 1 ) );
|
||||||
|
|
||||||
|
final Object[] third = (Object[]) results.get( 2 );
|
||||||
|
assertThat( third[ 0 ], is( 2 ) );
|
||||||
|
assertThat( third[ 2 ], is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsCtorSelectExpression() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 3 ) );
|
||||||
|
final CompanyDto companyDto0 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto0.getId(), is( 0 ) );
|
||||||
|
assertThat( companyDto0.getName(), is( "Company 0") );
|
||||||
|
assertThat( companyDto0.getSizeCustomer(), is( 0 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 2 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionWithLeftJoin() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c left join c.customers cu" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 3 ) );
|
||||||
|
final CompanyDto companyDto0 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto0.getId(), is( 0 ) );
|
||||||
|
assertThat( companyDto0.getName(), is( "Company 0") );
|
||||||
|
assertThat( companyDto0.getSizeCustomer(), is( 0 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 2 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionWithInnerJoin() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c inner join c.customers cu" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionOfAliasWithInnerJoin() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( cu ) )" +
|
||||||
|
" from Company c inner join c.customers cu" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionExcludeEmptyCollection() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.ManyToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c" +
|
||||||
|
" where c.id != 0" +
|
||||||
|
" group by c.id, c.name order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsConditionalExpressionExcludeEmptyCollection() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List<Company> results = session.createQuery(
|
||||||
|
"from Company c" +
|
||||||
|
" where size( c.customers ) > 0" +
|
||||||
|
" group by c.id, c.name order by c.id",
|
||||||
|
Company.class
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final Company company1 = results.get( 0 );
|
||||||
|
assertThat( company1.id, is( 1 ) );
|
||||||
|
assertThat( company1.name, is( "Company 1") );
|
||||||
|
assertThat( Hibernate.isInitialized( company1.customers ), is( true ) );
|
||||||
|
assertThat( company1.customers.size(), is( 1 ) );
|
||||||
|
final Company company2 = results.get( 1 );
|
||||||
|
assertThat( company2.id, is( 2 ) );
|
||||||
|
assertThat( company2.name, is( "Company 2") );
|
||||||
|
assertThat( Hibernate.isInitialized( company2.customers ), is( true ) );
|
||||||
|
assertThat( company2.customers.size(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsConditionalExpressionIncludeEmptyCollection() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List<Company> results = session.createQuery(
|
||||||
|
"from Company c" +
|
||||||
|
" where size( c.customers ) > -1" +
|
||||||
|
" group by c.id, c.name order by c.id",
|
||||||
|
Company.class
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 3 ) );
|
||||||
|
final Company company0 = results.get( 0 );
|
||||||
|
assertThat( company0.id, is( 0 ) );
|
||||||
|
assertThat( company0.name, is( "Company 0") );
|
||||||
|
assertThat( Hibernate.isInitialized(company0.customers), is( true ) );
|
||||||
|
assertThat( company0.customers.size(), is( 0 ) );
|
||||||
|
final Company company1 = results.get( 1 );
|
||||||
|
assertThat( company1.id, is( 1 ) );
|
||||||
|
assertThat( company1.name, is( "Company 1") );
|
||||||
|
assertThat( Hibernate.isInitialized(company1.customers), is( true ) );
|
||||||
|
assertThat( company1.customers.size(), is( 1 ) );
|
||||||
|
final Company company2 = results.get( 2 );
|
||||||
|
assertThat( company2.id, is( 2 ) );
|
||||||
|
assertThat( company2.name, is( "Company 2") );
|
||||||
|
assertThat( Hibernate.isInitialized(company2.customers), is( true ) );
|
||||||
|
assertThat( company2.customers.size(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initDataBase(){
|
||||||
|
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
// Add a company with no customers
|
||||||
|
final Company companyWithNoCustomers = new Company( 0 );
|
||||||
|
companyWithNoCustomers.name = "Company 0";
|
||||||
|
session.persist( companyWithNoCustomers );
|
||||||
|
int k = 0;
|
||||||
|
for ( int i = 1; i <= 2; i++ ) {
|
||||||
|
final Company company = new Company( i );
|
||||||
|
company.name = "Company " + i;
|
||||||
|
|
||||||
|
for ( int j = 1; j <= i; j++ ) {
|
||||||
|
final Customer customer = new Customer( k );
|
||||||
|
customer.name = "Customer " + k;
|
||||||
|
company.customers.add( customer );
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
session.persist( company );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanupDatabase() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
for ( Company company : session.createQuery( "from Company", Company.class ).list() ) {
|
||||||
|
session.delete( company );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Company.class, Customer.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name ="Company")
|
||||||
|
public static class Company {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
|
||||||
|
private List<Customer> customers = new ArrayList<>();
|
||||||
|
|
||||||
|
public Company() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Customer")
|
||||||
|
public static class Customer {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CompanyDto {
|
||||||
|
|
||||||
|
public int id;
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
public int sizeCustomer;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSizeCustomer() {
|
||||||
|
return sizeCustomer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSizeCustomer(int sizeCustomer) {
|
||||||
|
this.sizeCustomer = sizeCustomer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyDto(){}
|
||||||
|
|
||||||
|
public CompanyDto(int id, String name, int sizeCustomer){
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.sizeCustomer = sizeCustomer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,344 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.test.hql.size;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
|
||||||
|
@TestForIssue( jiraKey = "HHH-13619" )
|
||||||
|
public class OneToManySizeTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpression() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.OneToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 3 ) );
|
||||||
|
final CompanyDto companyDto0 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto0.getId(), is( 0 ) );
|
||||||
|
assertThat( companyDto0.getName(), is( "Company 0") );
|
||||||
|
assertThat( companyDto0.getSizeCustomer(), is( 0 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 2 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionWithLeftJoin() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.OneToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c left join c.customers cu" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 3 ) );
|
||||||
|
final CompanyDto companyDto0 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto0.getId(), is( 0 ) );
|
||||||
|
assertThat( companyDto0.getName(), is( "Company 0") );
|
||||||
|
assertThat( companyDto0.getSizeCustomer(), is( 0 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 2 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionWithInnerJoin() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.OneToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c inner join c.customers cu" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionOfAliasWithInnerJoin() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.OneToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( cu ) )" +
|
||||||
|
" from Company c inner join c.customers cu" +
|
||||||
|
" group by c.id, c.name" +
|
||||||
|
" order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsSelectExpressionExcludeEmptyCollection() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List results = session.createQuery(
|
||||||
|
"select new org.hibernate.test.hql.size.OneToManySizeTest$CompanyDto(" +
|
||||||
|
" c.id, c.name, size( c.customers ) )" +
|
||||||
|
" from Company c" +
|
||||||
|
" where c.id != 0" +
|
||||||
|
" group by c.id, c.name order by c.id"
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final CompanyDto companyDto1 = (CompanyDto) results.get( 0 );
|
||||||
|
assertThat( companyDto1.getId(), is( 1 ) );
|
||||||
|
assertThat( companyDto1.getName(), is( "Company 1") );
|
||||||
|
assertThat( companyDto1.getSizeCustomer(), is( 1 ) );
|
||||||
|
final CompanyDto companyDto2 = (CompanyDto) results.get( 1 );
|
||||||
|
assertThat( companyDto2.getId(), is( 2 ) );
|
||||||
|
assertThat( companyDto2.getName(), is( "Company 2") );
|
||||||
|
assertThat( companyDto2.getSizeCustomer(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsConditionalExpressionExcludeEmptyCollection() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List<Company> results = session.createQuery(
|
||||||
|
"from Company c" +
|
||||||
|
" where size( c.customers ) > 0" +
|
||||||
|
" group by c.id, c.name order by c.id",
|
||||||
|
Company.class
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 2 ) );
|
||||||
|
final Company company1 = results.get( 0 );
|
||||||
|
assertThat( company1.id, is( 1 ) );
|
||||||
|
assertThat( company1.name, is( "Company 1") );
|
||||||
|
assertThat( Hibernate.isInitialized( company1.customers ), is( true ) );
|
||||||
|
assertThat( company1.customers.size(), is( 1 ) );
|
||||||
|
final Company company2 = results.get( 1 );
|
||||||
|
assertThat( company2.id, is( 2 ) );
|
||||||
|
assertThat( company2.name, is( "Company 2") );
|
||||||
|
assertThat( Hibernate.isInitialized( company2.customers ), is( true ) );
|
||||||
|
assertThat( company2.customers.size(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeAsConditionalExpressionIncludeEmptyCollection() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final List<Company> results = session.createQuery(
|
||||||
|
"from Company c" +
|
||||||
|
" where size( c.customers ) > -1" +
|
||||||
|
" group by c.id, c.name order by c.id",
|
||||||
|
Company.class
|
||||||
|
).list();
|
||||||
|
assertThat( results.size(), is( 3 ) );
|
||||||
|
final Company company0 = results.get( 0 );
|
||||||
|
assertThat( company0.id, is( 0 ) );
|
||||||
|
assertThat( company0.name, is( "Company 0") );
|
||||||
|
assertThat( Hibernate.isInitialized(company0.customers), is( true ) );
|
||||||
|
assertThat( company0.customers.size(), is( 0 ) );
|
||||||
|
final Company company1 = results.get( 1 );
|
||||||
|
assertThat( company1.id, is( 1 ) );
|
||||||
|
assertThat( company1.name, is( "Company 1") );
|
||||||
|
assertThat( Hibernate.isInitialized(company1.customers), is( true ) );
|
||||||
|
assertThat( company1.customers.size(), is( 1 ) );
|
||||||
|
final Company company2 = results.get( 2 );
|
||||||
|
assertThat( company2.id, is( 2 ) );
|
||||||
|
assertThat( company2.name, is( "Company 2") );
|
||||||
|
assertThat( Hibernate.isInitialized(company2.customers), is( true ) );
|
||||||
|
assertThat( company2.customers.size(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initDataBase(){
|
||||||
|
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
// Add a company with no customers
|
||||||
|
final Company companyWithNoCustomers = new Company( 0 );
|
||||||
|
companyWithNoCustomers.name = "Company 0";
|
||||||
|
session.persist( companyWithNoCustomers );
|
||||||
|
int k = 0;
|
||||||
|
for ( int i = 1; i <= 2; i++ ) {
|
||||||
|
final Company company = new Company( i );
|
||||||
|
company.name = "Company " + i;
|
||||||
|
|
||||||
|
for ( int j = 1; j <= i; j++ ) {
|
||||||
|
final Customer customer = new Customer( k );
|
||||||
|
customer.name = "Customer " + k;
|
||||||
|
company.customers.add( customer );
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
session.persist( company );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanupDatabase() {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
for ( Company company : session.createQuery( "from Company", Company.class ).list() ) {
|
||||||
|
session.delete( company );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Company.class, Customer.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name ="Company")
|
||||||
|
public static class Company {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
|
||||||
|
@JoinColumn
|
||||||
|
private List<Customer> customers = new ArrayList<>();
|
||||||
|
|
||||||
|
public Company() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Customer")
|
||||||
|
public static class Customer {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CompanyDto {
|
||||||
|
|
||||||
|
public int id;
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
public int sizeCustomer;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSizeCustomer() {
|
||||||
|
return sizeCustomer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSizeCustomer(int sizeCustomer) {
|
||||||
|
this.sizeCustomer = sizeCustomer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyDto(){}
|
||||||
|
|
||||||
|
public CompanyDto(int id, String name, int sizeCustomer){
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.sizeCustomer = sizeCustomer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue