HHH-2049 : LEFT OUTER JOIN subcriteria filters children (Mattias Jiderhamn)
This commit is contained in:
parent
a6b8d62209
commit
f0c2488d91
|
@ -414,6 +414,7 @@ public class CriteriaImpl implements Criteria, Serializable {
|
||||||
private LockMode lockMode;
|
private LockMode lockMode;
|
||||||
private int joinType;
|
private int joinType;
|
||||||
private Criterion withClause;
|
private Criterion withClause;
|
||||||
|
private boolean hasRestriction;
|
||||||
|
|
||||||
// Constructors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// Constructors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -423,6 +424,7 @@ public class CriteriaImpl implements Criteria, Serializable {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.joinType = joinType;
|
this.joinType = joinType;
|
||||||
this.withClause = withClause;
|
this.withClause = withClause;
|
||||||
|
this.hasRestriction = withClause != null;
|
||||||
CriteriaImpl.this.subcriteriaList.add( this );
|
CriteriaImpl.this.subcriteriaList.add( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,10 +479,14 @@ public class CriteriaImpl implements Criteria, Serializable {
|
||||||
return this.withClause;
|
return this.withClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasRestriction() {
|
||||||
|
return hasRestriction;
|
||||||
|
}
|
||||||
|
|
||||||
// Criteria impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// Criteria impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
public Criteria add(Criterion expression) {
|
public Criteria add(Criterion expression) {
|
||||||
|
hasRestriction = true;
|
||||||
CriteriaImpl.this.add(this, expression);
|
CriteriaImpl.this.add(this, expression);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,10 @@ public class JoinWalker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasRestriction(PropertyPath path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getWithClause(PropertyPath path) {
|
protected String getWithClause(PropertyPath path) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -239,6 +243,7 @@ public class JoinWalker {
|
||||||
subalias,
|
subalias,
|
||||||
joinType,
|
joinType,
|
||||||
getWithClause(path),
|
getWithClause(path),
|
||||||
|
hasRestriction( path ),
|
||||||
getFactory(),
|
getFactory(),
|
||||||
loadQueryInfluencers.getEnabledFilters()
|
loadQueryInfluencers.getEnabledFilters()
|
||||||
);
|
);
|
||||||
|
@ -877,7 +882,9 @@ public class JoinWalker {
|
||||||
Iterator iter = associations.iterator();
|
Iterator iter = associations.iterator();
|
||||||
while ( iter.hasNext() ) {
|
while ( iter.hasNext() ) {
|
||||||
OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();
|
OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();
|
||||||
if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN && oj.getJoinable().isCollection() ) {
|
if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN &&
|
||||||
|
oj.getJoinable().isCollection() &&
|
||||||
|
! oj.hasRestriction() ) {
|
||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1019,7 @@ public class JoinWalker {
|
||||||
else {
|
else {
|
||||||
|
|
||||||
QueryableCollection collPersister = (QueryableCollection) oj.getJoinable();
|
QueryableCollection collPersister = (QueryableCollection) oj.getJoinable();
|
||||||
if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN ) {
|
if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN && ! oj.hasRestriction() ) {
|
||||||
//it must be a collection fetch
|
//it must be a collection fetch
|
||||||
collectionPersisters[j] = collPersister;
|
collectionPersisters[j] = collPersister;
|
||||||
collectionOwners[j] = oj.getOwner(associations);
|
collectionOwners[j] = oj.getOwner(associations);
|
||||||
|
|
|
@ -51,6 +51,7 @@ public final class OuterJoinableAssociation {
|
||||||
private final int joinType;
|
private final int joinType;
|
||||||
private final String on;
|
private final String on;
|
||||||
private final Map enabledFilters;
|
private final Map enabledFilters;
|
||||||
|
private final boolean hasRestriction;
|
||||||
|
|
||||||
public static OuterJoinableAssociation createRoot(
|
public static OuterJoinableAssociation createRoot(
|
||||||
AssociationType joinableType,
|
AssociationType joinableType,
|
||||||
|
@ -64,6 +65,7 @@ public final class OuterJoinableAssociation {
|
||||||
alias,
|
alias,
|
||||||
JoinFragment.LEFT_OUTER_JOIN,
|
JoinFragment.LEFT_OUTER_JOIN,
|
||||||
null,
|
null,
|
||||||
|
false,
|
||||||
factory,
|
factory,
|
||||||
CollectionHelper.EMPTY_MAP
|
CollectionHelper.EMPTY_MAP
|
||||||
);
|
);
|
||||||
|
@ -77,6 +79,7 @@ public final class OuterJoinableAssociation {
|
||||||
String rhsAlias,
|
String rhsAlias,
|
||||||
int joinType,
|
int joinType,
|
||||||
String withClause,
|
String withClause,
|
||||||
|
boolean hasRestriction,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters) throws MappingException {
|
Map enabledFilters) throws MappingException {
|
||||||
this.propertyPath = propertyPath;
|
this.propertyPath = propertyPath;
|
||||||
|
@ -89,6 +92,7 @@ public final class OuterJoinableAssociation {
|
||||||
this.rhsColumns = JoinHelper.getRHSColumnNames(joinableType, factory);
|
this.rhsColumns = JoinHelper.getRHSColumnNames(joinableType, factory);
|
||||||
this.on = joinableType.getOnCondition(rhsAlias, factory, enabledFilters)
|
this.on = joinableType.getOnCondition(rhsAlias, factory, enabledFilters)
|
||||||
+ ( withClause == null || withClause.trim().length() == 0 ? "" : " and ( " + withClause + " )" );
|
+ ( withClause == null || withClause.trim().length() == 0 ? "" : " and ( " + withClause + " )" );
|
||||||
|
this.hasRestriction = hasRestriction;
|
||||||
this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application
|
this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +142,10 @@ public final class OuterJoinableAssociation {
|
||||||
return joinable;
|
return joinable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasRestriction() {
|
||||||
|
return hasRestriction;
|
||||||
|
}
|
||||||
|
|
||||||
public int getOwner(final List associations) {
|
public int getOwner(final List associations) {
|
||||||
if ( isOneToOne() || isCollection() ) {
|
if ( isOneToOne() || isCollection() ) {
|
||||||
return getPosition(lhsAlias, associations);
|
return getPosition(lhsAlias, associations);
|
||||||
|
|
|
@ -278,5 +278,8 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
||||||
protected String getWithClause(PropertyPath path) {
|
protected String getWithClause(PropertyPath path) {
|
||||||
return translator.getWithClause( path.getFullPath() );
|
return translator.getWithClause( path.getFullPath() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasRestriction(PropertyPath path) {
|
||||||
|
return translator.hasRestriction( path.getFullPath() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -674,5 +674,12 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
||||||
final Criterion crit = (Criterion)this.withClauseMap.get(path);
|
final Criterion crit = (Criterion)this.withClauseMap.get(path);
|
||||||
return crit == null ? null : crit.toSqlString(getCriteria(path), this);
|
return crit == null ? null : crit.toSqlString(getCriteria(path), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasRestriction(String path)
|
||||||
|
{
|
||||||
|
final CriteriaImpl.Subcriteria crit = ( CriteriaImpl.Subcriteria ) getCriteria( path );
|
||||||
|
return crit == null ? false : crit.hasRestriction();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.criteria">
|
||||||
|
<class name="Order" table="t_order">
|
||||||
|
<id name="orderId" column="order_id" type="int" unsaved-value="0" access="field" >
|
||||||
|
<generator class="identity" />
|
||||||
|
</id>
|
||||||
|
<set name="orderLines" cascade="all-delete-orphan" access="field" inverse="true" fetch="select">
|
||||||
|
<key column="order_id" />
|
||||||
|
<one-to-many class="OrderLine" />
|
||||||
|
</set>
|
||||||
|
</class>
|
||||||
|
<class name="OrderLine" table="order_line">
|
||||||
|
<id name="lineId" column="order_line_id" type="int" unsaved-value="0" access="field" >
|
||||||
|
<generator class="identity" />
|
||||||
|
</id>
|
||||||
|
<many-to-one name="order" column="order_id" class="Order" />
|
||||||
|
<property name="articleId" column="article_id" type="string" />
|
||||||
|
</class>
|
||||||
|
</hibernate-mapping>
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.criteria;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Order {
|
||||||
|
|
||||||
|
private int orderId;
|
||||||
|
|
||||||
|
public int getOrderId() {
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<OrderLine> orderLines = new HashSet<OrderLine>();
|
||||||
|
|
||||||
|
public Set<OrderLine> getLines() {
|
||||||
|
return Collections.unmodifiableSet(orderLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLine(OrderLine orderLine){
|
||||||
|
orderLine.setOrder(this);
|
||||||
|
this.orderLines.add(orderLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "" + getOrderId() + " - " + getLines();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.criteria;
|
||||||
|
|
||||||
|
public class OrderLine {
|
||||||
|
|
||||||
|
private int lineId = 0;
|
||||||
|
|
||||||
|
private Order order;
|
||||||
|
|
||||||
|
private String articleId;
|
||||||
|
|
||||||
|
|
||||||
|
public int getLineId() {
|
||||||
|
return lineId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getArticleId() {
|
||||||
|
return articleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Order order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArticleId(String articleId) {
|
||||||
|
this.articleId = articleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "[" + getLineId() + ":" + getArticleId() + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,428 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.criteria;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNotSame;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import org.hibernate.Criteria;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
import org.hibernate.sql.JoinFragment;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mattias Jiderhamn
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class OuterJoinCriteriaTest extends BaseCoreFunctionalTestCase {
|
||||||
|
private Order order1;
|
||||||
|
private Order order2;
|
||||||
|
private Order order3;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getMappings() {
|
||||||
|
return new String[] { "criteria/Order.hbm.xml" };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubcriteriaWithNonNullRestrictions() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class );
|
||||||
|
Criteria subCriteria = rootCriteria.createCriteria( "orderLines", JoinFragment.LEFT_OUTER_JOIN );
|
||||||
|
assertNotSame( rootCriteria, subCriteria );
|
||||||
|
|
||||||
|
// add restrictions to subCriteria, ensuring we stay on subCriteria
|
||||||
|
assertSame( subCriteria, subCriteria.add( Restrictions.eq( "articleId", "3000" ) ) );
|
||||||
|
|
||||||
|
List orders = rootCriteria.list();
|
||||||
|
|
||||||
|
// order1 and order3 should be returned because each has articleId == "3000"
|
||||||
|
// both should have their full collection
|
||||||
|
assertEquals( 2, orders.size() );
|
||||||
|
for ( Iterator it = orders.iterator(); it.hasNext(); ) {
|
||||||
|
Order o = (Order) it.next();
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( order1.getLines().size(), o.getLines().size() );
|
||||||
|
}
|
||||||
|
else if ( order3.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( order3.getLines().size(), o.getLines().size() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubcriteriaWithNonNullRestrictionsAliasToEntityMap() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class, "o" );
|
||||||
|
Criteria subCriteria = rootCriteria.createCriteria( "orderLines", "ol", JoinFragment.LEFT_OUTER_JOIN );
|
||||||
|
assertNotSame( rootCriteria, subCriteria );
|
||||||
|
|
||||||
|
// add restriction to subCriteria, ensuring we stay on subCriteria
|
||||||
|
assertSame( subCriteria, subCriteria.add( Restrictions.eq( "articleId", "3000" ) ) );
|
||||||
|
|
||||||
|
List orders = rootCriteria.setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP ).list();
|
||||||
|
|
||||||
|
// order1 and order3 should be returned because each has articleId == "3000";
|
||||||
|
// the orders should both should have their full collection;
|
||||||
|
assertEquals( 2, orders.size() );
|
||||||
|
for ( Iterator it = orders.iterator(); it.hasNext(); ) {
|
||||||
|
Map map = (Map) it.next();
|
||||||
|
Order o = ( Order ) map.get( "o" );
|
||||||
|
// the orderLine returned from the map should have articleId = "3000"
|
||||||
|
OrderLine ol = ( OrderLine ) map.get( "ol" );
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( order1.getLines().size(), o.getLines().size() );
|
||||||
|
assertEquals( "3000", ol.getArticleId() );
|
||||||
|
}
|
||||||
|
else if ( order3.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( order3.getLines().size(), o.getLines().size() );
|
||||||
|
assertEquals( "3000", ol.getArticleId() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubcriteriaWithNullOrNonNullRestrictions() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class );
|
||||||
|
Criteria subCriteria = rootCriteria.createCriteria( "orderLines", JoinFragment.LEFT_OUTER_JOIN );
|
||||||
|
assertNotSame( rootCriteria, subCriteria );
|
||||||
|
|
||||||
|
// add restrictions to subCriteria, ensuring we stay on subCriteria
|
||||||
|
// add restriction to subCriteria, ensuring we stay on subCriteria
|
||||||
|
assertSame(
|
||||||
|
subCriteria,
|
||||||
|
subCriteria.add(
|
||||||
|
Restrictions.or(
|
||||||
|
Restrictions.isNull( "articleId" ), // Allow null
|
||||||
|
Restrictions.eq( "articleId", "1000" )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
List orders = rootCriteria.list();
|
||||||
|
|
||||||
|
// order1 should be returned because it has an orderline with articleId == "1000";
|
||||||
|
// order2 should be returned because it has no orderlines
|
||||||
|
assertEquals( 2, orders.size() );
|
||||||
|
for ( Iterator it = orders.iterator(); it.hasNext(); ) {
|
||||||
|
Order o = ( Order ) it.next();
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
// o.getLines() should contain all of its orderLines
|
||||||
|
assertEquals( order1.getLines().size(), o.getLines().size() );
|
||||||
|
}
|
||||||
|
else if ( order2.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( order2.getLines() , o.getLines() );
|
||||||
|
assertTrue( o.getLines().isEmpty() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubcriteriaWithNullOrNonNullRestrictionsAliasToEntityMap() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class, "o" );
|
||||||
|
Criteria subCriteria = rootCriteria.createCriteria( "orderLines", "ol", JoinFragment.LEFT_OUTER_JOIN );
|
||||||
|
assertNotSame( rootCriteria, subCriteria );
|
||||||
|
|
||||||
|
// add restriction to subCriteria, ensuring we stay on subCriteria
|
||||||
|
assertSame(
|
||||||
|
subCriteria,
|
||||||
|
subCriteria.add(
|
||||||
|
Restrictions.or(
|
||||||
|
Restrictions.isNull( "ol.articleId" ), // Allow null
|
||||||
|
Restrictions.eq( "ol.articleId", "1000" )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
List orders = rootCriteria.setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP ).list();
|
||||||
|
|
||||||
|
// order1 should be returned because it has an orderline with articleId == "1000";
|
||||||
|
// order2 should be returned because it has no orderlines
|
||||||
|
assertEquals( 2, orders.size() );
|
||||||
|
for ( Iterator it = orders.iterator(); it.hasNext(); ) {
|
||||||
|
Map map = (Map) it.next();
|
||||||
|
Order o = ( Order ) map.get( "o" );
|
||||||
|
// the orderLine returned from the map should either be null or have articleId = "1000"
|
||||||
|
OrderLine ol = ( OrderLine ) map.get( "ol" );
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
// o.getLines() should contain all of its orderLines
|
||||||
|
assertEquals( order1.getLines().size(), o.getLines().size() );
|
||||||
|
assertNotNull( ol );
|
||||||
|
assertEquals( "1000", ol.getArticleId() );
|
||||||
|
}
|
||||||
|
else if ( order2.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( order2.getLines() , o.getLines() );
|
||||||
|
assertTrue( o.getLines().isEmpty() );
|
||||||
|
assertNull( ol );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubcriteriaWithClauseAliasToEntityMap() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class, "o" );
|
||||||
|
Criteria subCriteria = rootCriteria.createCriteria(
|
||||||
|
"orderLines",
|
||||||
|
"ol", JoinFragment.LEFT_OUTER_JOIN,
|
||||||
|
Restrictions.or(
|
||||||
|
Restrictions.isNull( "ol.articleId" ), // Allow null
|
||||||
|
Restrictions.eq( "ol.articleId", "1000" )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assertNotSame( rootCriteria, subCriteria );
|
||||||
|
|
||||||
|
List orders = rootCriteria.setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP ).list();
|
||||||
|
|
||||||
|
// all orders should be returned (via map.get( "o" )) with their full collections;
|
||||||
|
assertEquals( 3, orders.size() );
|
||||||
|
for ( Iterator it = orders.iterator(); it.hasNext(); ) {
|
||||||
|
Map map = ( Map ) it.next();
|
||||||
|
Order o = ( Order ) map.get( "o" );
|
||||||
|
// the orderLine returned from the map should either be null or have articleId = "1000"
|
||||||
|
OrderLine ol = ( OrderLine ) map.get( "ol" );
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
// o.getLines() should contain all of its orderLines
|
||||||
|
assertEquals( order1.getLines().size(), o.getLines().size() );
|
||||||
|
assertNotNull( ol );
|
||||||
|
assertEquals( "1000", ol.getArticleId() );
|
||||||
|
}
|
||||||
|
else if ( order2.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertTrue( o.getLines().isEmpty() );
|
||||||
|
assertNull( ol );
|
||||||
|
}
|
||||||
|
else if ( order3.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( order3.getLines().size(), o.getLines().size() );
|
||||||
|
assertNull( ol);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAliasWithNonNullRestrictions() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class );
|
||||||
|
// create alias, ensuring we stay on the root criteria
|
||||||
|
assertSame( rootCriteria, rootCriteria.createAlias( "orderLines", "ol", JoinFragment.LEFT_OUTER_JOIN ) );
|
||||||
|
|
||||||
|
// add restrictions to rootCriteria
|
||||||
|
assertSame( rootCriteria, rootCriteria.add( Restrictions.eq( "ol.articleId", "3000" ) ) );
|
||||||
|
|
||||||
|
List orders = rootCriteria.list();
|
||||||
|
|
||||||
|
// order1 and order3 should be returned because each has articleId == "3000"
|
||||||
|
// the contained collections should only have the orderLine with articleId == "3000"
|
||||||
|
assertEquals( 2, orders.size() );
|
||||||
|
for ( Iterator it = orders.iterator(); it.hasNext(); ) {
|
||||||
|
Order o = (Order) it.next();
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( 1, o.getLines().size() );
|
||||||
|
assertEquals( "3000", ( ( OrderLine ) o.getLines().iterator().next() ).getArticleId() );
|
||||||
|
}
|
||||||
|
else if ( order3.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( 1, o.getLines().size() );
|
||||||
|
assertEquals( "3000", ( ( OrderLine ) o.getLines().iterator().next() ).getArticleId() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAliasWithNullOrNonNullRestrictions() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class );
|
||||||
|
// create alias, ensuring we stay on the root criteria
|
||||||
|
assertSame( rootCriteria, rootCriteria.createAlias( "orderLines", "ol", JoinFragment.LEFT_OUTER_JOIN ) );
|
||||||
|
|
||||||
|
// add restrictions to rootCriteria
|
||||||
|
assertSame(
|
||||||
|
rootCriteria,
|
||||||
|
rootCriteria.add(
|
||||||
|
Restrictions.or(
|
||||||
|
Restrictions.isNull( "ol.articleId" ), // Allow null
|
||||||
|
Restrictions.eq( "ol.articleId", "1000" )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
List orders = rootCriteria.list();
|
||||||
|
|
||||||
|
// order1 should be returned because it has an orderline with articleId == "1000";
|
||||||
|
// the contained collection for order1 should only have the orderLine with articleId == "1000";
|
||||||
|
// order2 should be returned because it has no orderlines
|
||||||
|
assertEquals( 2, orders.size() );
|
||||||
|
for ( Object order : orders ) {
|
||||||
|
Order o = (Order) order;
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( "1000", ( ( OrderLine ) o.getLines().iterator().next() ).getArticleId() );
|
||||||
|
}
|
||||||
|
else if ( order2.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( 0, o.getLines().size() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonNullSubcriteriaRestrictionsOnRootCriteria() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Criteria rootCriteria = s.createCriteria( Order.class );
|
||||||
|
Criteria subCriteria = rootCriteria.createCriteria( "orderLines", "ol", JoinFragment.LEFT_OUTER_JOIN );
|
||||||
|
assertNotSame( rootCriteria, subCriteria );
|
||||||
|
|
||||||
|
// add restriction to rootCriteria (NOT subcriteria)
|
||||||
|
assertSame( rootCriteria, rootCriteria.add( Restrictions.eq( "ol.articleId", "3000" ) ) );
|
||||||
|
|
||||||
|
List orders = rootCriteria.list();
|
||||||
|
|
||||||
|
// results should be the same as testAliasWithNonNullRestrictions() (using Criteria.createAlias())
|
||||||
|
// order1 and order3 should be returned because each has articleId == "3000"
|
||||||
|
// the contained collections should only have the orderLine with articleId == "3000"
|
||||||
|
assertEquals( 2, orders.size() );
|
||||||
|
for ( Iterator it = orders.iterator(); it.hasNext(); ) {
|
||||||
|
Order o = (Order) it.next();
|
||||||
|
if ( order1.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( 1, o.getLines().size() );
|
||||||
|
assertEquals( "3000", ( ( OrderLine ) o.getLines().iterator().next() ).getArticleId() );
|
||||||
|
}
|
||||||
|
else if ( order3.getOrderId() == o.getOrderId() ) {
|
||||||
|
assertEquals( 1, o.getLines().size() );
|
||||||
|
assertEquals( "3000", ( ( OrderLine ) o.getLines().iterator().next() ).getArticleId() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "unknown order" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareTest() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
// Order with one mathing line
|
||||||
|
order1 = new Order();
|
||||||
|
OrderLine line = new OrderLine();
|
||||||
|
line.setArticleId( "1000" );
|
||||||
|
order1.addLine( line );
|
||||||
|
line = new OrderLine();
|
||||||
|
line.setArticleId( "3000" );
|
||||||
|
order1.addLine( line );
|
||||||
|
s.persist( order1 );
|
||||||
|
|
||||||
|
// Order with no lines
|
||||||
|
order2 = new Order();
|
||||||
|
s.persist( order2 );
|
||||||
|
|
||||||
|
// Order with non-matching line
|
||||||
|
order3 = new Order();
|
||||||
|
line = new OrderLine();
|
||||||
|
line.setArticleId( "3000" );
|
||||||
|
order3.addLine( line );
|
||||||
|
s.persist( order3 );
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanupTest() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
s.createQuery( "delete from OrderLine" ).executeUpdate();
|
||||||
|
|
||||||
|
s.createQuery( "delete from Order" ).executeUpdate();
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isBlank(String s) {
|
||||||
|
return s == null || s.trim().length() == 0;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue