HHH-11896 Support 'on-clause' criterion when traversing audit query relations
This commit is contained in:
parent
e07a8c3bd5
commit
3e3d227c9a
|
@ -13,6 +13,7 @@ import jakarta.persistence.criteria.JoinType;
|
|||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.query.criteria.AuditCriterion;
|
||||
|
@ -21,7 +22,6 @@ import org.hibernate.envers.query.projection.AuditProjection;
|
|||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @see org.hibernate.Criteria
|
||||
*/
|
||||
public interface AuditQuery {
|
||||
List getResultList() throws AuditException;
|
||||
|
@ -30,9 +30,18 @@ public interface AuditQuery {
|
|||
|
||||
AuditAssociationQuery<? extends AuditQuery> traverseRelation(String associationName, JoinType joinType);
|
||||
|
||||
AuditAssociationQuery<? extends AuditQuery> traverseRelation(String associationName, JoinType joinType,
|
||||
AuditAssociationQuery<? extends AuditQuery> traverseRelation(
|
||||
String associationName,
|
||||
JoinType joinType,
|
||||
String alias);
|
||||
|
||||
@Incubating
|
||||
AuditAssociationQuery<? extends AuditQuery> traverseRelation(
|
||||
String associationName,
|
||||
JoinType joinType,
|
||||
String alias,
|
||||
AuditCriterion onClauseCriterion);
|
||||
|
||||
AuditQuery add(AuditCriterion criterion);
|
||||
|
||||
AuditQuery addProjection(AuditProjection projection);
|
||||
|
|
|
@ -59,7 +59,6 @@ public abstract class AbstractAuditQuery implements AuditQueryImplementor {
|
|||
protected final AuditReaderImplementor versionsReader;
|
||||
|
||||
protected final List<AuditAssociationQueryImpl<?>> associationQueries = new ArrayList<>();
|
||||
protected final Map<String, AuditAssociationQueryImpl<AuditQueryImplementor>> associationQueryMap = new HashMap<>();
|
||||
protected final List<Pair<String, AuditProjection>> projections = new ArrayList<>();
|
||||
|
||||
protected AbstractAuditQuery(
|
||||
|
@ -196,9 +195,20 @@ public abstract class AbstractAuditQuery implements AuditQueryImplementor {
|
|||
|
||||
@Override
|
||||
public AuditAssociationQuery<? extends AuditQuery> traverseRelation(String associationName, JoinType joinType, String alias) {
|
||||
AuditAssociationQueryImpl<AuditQueryImplementor> result = associationQueryMap.get( associationName );
|
||||
if (result == null) {
|
||||
result = new AuditAssociationQueryImpl<>(
|
||||
return traverseRelation(
|
||||
associationName,
|
||||
joinType,
|
||||
alias,
|
||||
null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuditAssociationQuery<? extends AuditQuery> traverseRelation(
|
||||
String associationName,
|
||||
JoinType joinType,
|
||||
String alias,
|
||||
AuditCriterion onClause) {
|
||||
AuditAssociationQueryImpl<AbstractAuditQuery> result = new AuditAssociationQueryImpl<>(
|
||||
enversService,
|
||||
versionsReader,
|
||||
this,
|
||||
|
@ -208,11 +218,10 @@ public abstract class AbstractAuditQuery implements AuditQueryImplementor {
|
|||
aliasToEntityNameMap,
|
||||
aliasToComponentPropertyNameMap,
|
||||
REFERENCED_ENTITY_ALIAS,
|
||||
alias
|
||||
alias,
|
||||
onClause
|
||||
);
|
||||
associationQueries.add( result );
|
||||
associationQueryMap.put( associationName, result );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.envers.query.internal.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -60,9 +59,9 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
private final Map<String, String> aliasToEntityNameMap;
|
||||
private final Map<String, String> aliasToComponentPropertyNameMap;
|
||||
private final List<AuditCriterion> criterions = new ArrayList<>();
|
||||
private final AuditCriterion onClauseCriterion;
|
||||
private final Parameters parameters;
|
||||
private final List<AuditAssociationQueryImpl<?>> associationQueries = new ArrayList<>();
|
||||
private final Map<String, AuditAssociationQueryImpl<AuditAssociationQueryImpl<Q>>> associationQueryMap = new HashMap<>();
|
||||
|
||||
public AuditAssociationQueryImpl(
|
||||
final EnversService enversService,
|
||||
|
@ -74,7 +73,8 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
final Map<String, String> aliasToEntityNameMap,
|
||||
final Map<String, String> aliasToComponentPropertyNameMap,
|
||||
final String ownerAlias,
|
||||
final String userSuppliedAlias) {
|
||||
final String userSuppliedAlias,
|
||||
final AuditCriterion onClauseCriterion) {
|
||||
this.enversService = enversService;
|
||||
this.auditReader = auditReader;
|
||||
this.parent = parent;
|
||||
|
@ -123,6 +123,7 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
this.aliasToEntityNameMap = aliasToEntityNameMap;
|
||||
this.aliasToComponentPropertyNameMap = aliasToComponentPropertyNameMap;
|
||||
parameters = queryBuilder.addParameters( this.alias );
|
||||
this.onClauseCriterion = onClauseCriterion;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -156,9 +157,21 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
String associationName,
|
||||
JoinType joinType,
|
||||
String alias) {
|
||||
AuditAssociationQueryImpl<AuditAssociationQueryImpl<Q>> result = associationQueryMap.get( associationName );
|
||||
if ( result == null ) {
|
||||
result = new AuditAssociationQueryImpl<>(
|
||||
return traverseRelation(
|
||||
associationName,
|
||||
joinType,
|
||||
alias,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuditAssociationQueryImpl<AuditAssociationQueryImpl<Q>> traverseRelation(
|
||||
String associationName,
|
||||
JoinType joinType,
|
||||
String alias,
|
||||
AuditCriterion onClause) {
|
||||
AuditAssociationQueryImpl<AuditAssociationQueryImpl<Q>> result = new AuditAssociationQueryImpl<>(
|
||||
enversService,
|
||||
auditReader,
|
||||
this,
|
||||
|
@ -168,11 +181,10 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
aliasToEntityNameMap,
|
||||
aliasToComponentPropertyNameMap,
|
||||
this.alias,
|
||||
alias
|
||||
alias,
|
||||
onClause
|
||||
);
|
||||
associationQueries.add( result );
|
||||
associationQueryMap.put( associationName, result );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -283,11 +295,24 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
}
|
||||
|
||||
protected void addCriterionsToQuery(AuditReaderImplementor versionsReader) {
|
||||
Parameters onClauseParameters;
|
||||
if ( relationDescription != null ) {
|
||||
createEntityJoin( enversService.getConfig() );
|
||||
onClauseParameters = createEntityJoin( enversService.getConfig() );
|
||||
}
|
||||
else {
|
||||
createComponentJoin( enversService.getConfig() );
|
||||
onClauseParameters = createComponentJoin( enversService.getConfig() );
|
||||
}
|
||||
|
||||
if ( onClauseCriterion != null ) {
|
||||
onClauseCriterion.addToQuery(
|
||||
enversService,
|
||||
versionsReader,
|
||||
aliasToEntityNameMap,
|
||||
aliasToComponentPropertyNameMap,
|
||||
alias,
|
||||
queryBuilder,
|
||||
onClauseParameters
|
||||
);
|
||||
}
|
||||
|
||||
for ( AuditCriterion criterion : criterions ) {
|
||||
|
@ -307,7 +332,7 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
}
|
||||
}
|
||||
|
||||
private void createEntityJoin(Configuration configuration) {
|
||||
private Parameters createEntityJoin(Configuration configuration) {
|
||||
boolean targetIsAudited = enversService.getEntitiesConfigurations().isVersioned( entityName );
|
||||
String targetEntityName = entityName;
|
||||
if ( targetIsAudited ) {
|
||||
|
@ -316,8 +341,10 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
String originalIdPropertyName = configuration.getOriginalIdPropertyName();
|
||||
String revisionPropertyPath = configuration.getRevisionNumberPath();
|
||||
|
||||
Parameters onClauseParameters;
|
||||
if ( relationDescription.getRelationType() == RelationType.TO_ONE ) {
|
||||
Parameters joinConditionParameters = queryBuilder.addJoin( joinType, targetEntityName, alias, false );
|
||||
onClauseParameters = joinConditionParameters;
|
||||
|
||||
// owner.reference_id = target.originalId.id
|
||||
IdMapper idMapperTarget;
|
||||
|
@ -350,6 +377,7 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
);
|
||||
}
|
||||
Parameters joinConditionParameters = queryBuilder.addJoin( joinType, targetEntityName, alias, false );
|
||||
onClauseParameters = joinConditionParameters;
|
||||
|
||||
// owner.originalId.id = target.reference_id
|
||||
IdMapper idMapperOwner = enversService.getEntitiesConfigurations().get( ownerEntityName ).getIdMapper();
|
||||
|
@ -384,6 +412,7 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
|
||||
// join target_entity
|
||||
Parameters joinConditionParametersTarget = queryBuilder.addJoin( joinType, targetEntityName, alias, false );
|
||||
onClauseParameters = joinConditionParametersTarget;
|
||||
|
||||
Parameters middleParameters = queryBuilder.addParameters( middleEntityAlias );
|
||||
String middleOriginalIdPropertyPath = middleEntityAlias + "." + originalIdPropertyName;
|
||||
|
@ -481,11 +510,13 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
true
|
||||
);
|
||||
}
|
||||
return onClauseParameters;
|
||||
}
|
||||
|
||||
private void createComponentJoin(Configuration configuration) {
|
||||
private Parameters createComponentJoin(Configuration configuration) {
|
||||
String originalIdPropertyName = configuration.getOriginalIdPropertyName();
|
||||
String revisionPropertyPath = configuration.getRevisionNumberPath();
|
||||
Parameters onClauseParameters;
|
||||
if ( componentDescription.getType() == ComponentType.MANY ) {
|
||||
// join middle_entity
|
||||
Parameters joinConditionParameters = queryBuilder.addJoin(
|
||||
|
@ -494,8 +525,10 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
alias,
|
||||
false
|
||||
);
|
||||
onClauseParameters = joinConditionParameters;
|
||||
|
||||
String middleOriginalIdPropertyPath = alias + "." + originalIdPropertyName;
|
||||
|
||||
// join condition: owner.reference_id = middle.id_ref_ing
|
||||
String ownerPrefix = ownerAlias + "." + originalIdPropertyName;
|
||||
MiddleIdData middleIdData = componentDescription.getMiddleIdData();
|
||||
|
@ -550,6 +583,7 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
*/
|
||||
String targetEntityName = configuration.getAuditEntityName( entityName );
|
||||
Parameters joinConditionParameters = queryBuilder.addJoin( joinType, targetEntityName, alias, false );
|
||||
onClauseParameters = joinConditionParameters;
|
||||
|
||||
// join condition: owner.reference_id = middle.id_reference_id
|
||||
String ownerPrefix = ownerAlias + "." + originalIdPropertyName;
|
||||
|
@ -560,6 +594,7 @@ public class AuditAssociationQueryImpl<Q extends AuditQueryImplementor>
|
|||
// join condition: owner.rev=middle.rev
|
||||
joinConditionParameters.addWhere( ownerAlias, revisionPropertyPath, "=", alias, revisionPropertyPath );
|
||||
}
|
||||
return onClauseParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.envers.integration.query;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.query.AuditEntity;
|
||||
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.orm.test.envers.Priority;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Felix Feisst (feisst dot felix at gmail dot com)
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-11896")
|
||||
public class AssociationQueryWithOnClauseTest extends BaseEnversJPAFunctionalTestCase {
|
||||
|
||||
private EntityA a1;
|
||||
private EntityA a2;
|
||||
private EntityA a3;
|
||||
|
||||
@Entity(name = "EntityA")
|
||||
@Audited
|
||||
public static class EntityA {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
private EntityB bManyToOne;
|
||||
|
||||
@OneToMany
|
||||
@AuditJoinTable(name = "entitya_onetomany_entityb_aud")
|
||||
private Set<EntityB> bOneToMany = new HashSet<>();
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "entitya_manytomany_entityb")
|
||||
private Set<EntityB> bManyToMany = new HashSet<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public EntityB getbManyToOne() {
|
||||
return bManyToOne;
|
||||
}
|
||||
|
||||
public void setbManyToOne(EntityB bManyToOne) {
|
||||
this.bManyToOne = bManyToOne;
|
||||
}
|
||||
|
||||
public Set<EntityB> getbOneToMany() {
|
||||
return bOneToMany;
|
||||
}
|
||||
|
||||
public void setbOneToMany(Set<EntityB> bOneToMany) {
|
||||
this.bOneToMany = bOneToMany;
|
||||
}
|
||||
|
||||
public Set<EntityB> getbManyToMany() {
|
||||
return bManyToMany;
|
||||
}
|
||||
|
||||
public void setbManyToMany(Set<EntityB> bManyToMany) {
|
||||
this.bManyToMany = bManyToMany;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "EntityB")
|
||||
@Audited
|
||||
public static class EntityB {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String type;
|
||||
|
||||
private int number;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[]{ EntityA.class, EntityB.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
@Priority(10)
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
em.getTransaction().begin();
|
||||
final EntityB b1t1 = new EntityB();
|
||||
b1t1.setId( 21L );
|
||||
b1t1.setType( "T1" );
|
||||
b1t1.setNumber( 1 );
|
||||
em.persist( b1t1 );
|
||||
final EntityB b2t2 = new EntityB();
|
||||
b2t2.setId( 22L );
|
||||
b2t2.setType( "T2" );
|
||||
b2t2.setNumber( 2 );
|
||||
em.persist( b2t2 );
|
||||
final EntityB b3t1 = new EntityB();
|
||||
b3t1.setId( 23L );
|
||||
b3t1.setType( "T1" );
|
||||
b3t1.setNumber( 3 );
|
||||
em.persist( b3t1 );
|
||||
|
||||
a1 = new EntityA();
|
||||
a1.setId( 1L );
|
||||
a1.setbManyToOne( b1t1 );
|
||||
a1.getbOneToMany().add( b1t1 );
|
||||
a1.getbOneToMany().add( b2t2 );
|
||||
a1.getbManyToMany().add( b1t1 );
|
||||
a1.getbManyToMany().add( b2t2 );
|
||||
em.persist( a1 );
|
||||
a2 = new EntityA();
|
||||
a2.setId( 2L );
|
||||
a2.setbManyToOne( b2t2 );
|
||||
a2.getbManyToMany().add( b3t1 );
|
||||
em.persist( a2 );
|
||||
a3 = new EntityA();
|
||||
a3.setId( 3L );
|
||||
a3.setbManyToOne( b3t1 );
|
||||
a3.getbOneToMany().add( b3t1 );
|
||||
a3.getbManyToMany().add( b3t1 );
|
||||
em.persist( a3 );
|
||||
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManyToOne() {
|
||||
List list = getAuditReader().createQuery()
|
||||
.forEntitiesAtRevision( EntityA.class, 1 )
|
||||
.traverseRelation( "bManyToOne", JoinType.LEFT, "b", AuditEntity.property( "b", "type" ).eq( "T1" ) )
|
||||
.addOrder( AuditEntity.property( "b", "number" ).asc() )
|
||||
.up()
|
||||
.addProjection( AuditEntity.id() )
|
||||
.addProjection( AuditEntity.property( "b", "number" ) )
|
||||
.getResultList();
|
||||
assertArrayListEquals( list, tuple( a2.getId(), null ), tuple( a1.getId(), 1 ), tuple( a3.getId(), 3 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneToMany() {
|
||||
List list = getAuditReader().createQuery().forEntitiesAtRevision( EntityA.class, 1 )
|
||||
.traverseRelation( "bOneToMany", JoinType.LEFT, "b", AuditEntity.property( "b", "type" ).eq( "T1" ) )
|
||||
.addOrder( AuditEntity.property( "b", "number" ).asc() )
|
||||
.up()
|
||||
.addOrder( AuditEntity.id().asc() )
|
||||
.addProjection( AuditEntity.id() )
|
||||
.addProjection( AuditEntity.property( "b", "number" ) )
|
||||
.getResultList();
|
||||
assertArrayListEquals( list, tuple( a1.getId(), null ), tuple( a2.getId(), null ), tuple( a1.getId(), 1 ), tuple( a3.getId(), 3 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManyToMany() {
|
||||
List list = getAuditReader().createQuery()
|
||||
.forEntitiesAtRevision( EntityA.class, 1 )
|
||||
.traverseRelation( "bManyToMany", JoinType.LEFT, "b", AuditEntity.property( "b", "type" ).eq( "T1" ) )
|
||||
.addOrder( AuditEntity.property( "b", "number" ).asc() )
|
||||
.up()
|
||||
.addOrder( AuditEntity.id().asc() ).addProjection( AuditEntity.id() )
|
||||
.addProjection( AuditEntity.property( "b", "number" ) )
|
||||
.getResultList();
|
||||
assertArrayListEquals( list, tuple( a1.getId(), null ), tuple( a1.getId(), 1 ), tuple( a2.getId(), 3 ), tuple( a3.getId(), 3 ) );
|
||||
}
|
||||
|
||||
private Object[] tuple(final Long id, final Integer number) {
|
||||
return new Object[]{ id, number };
|
||||
}
|
||||
|
||||
private void assertArrayListEquals(final List actual, final Object[]... expected) {
|
||||
assertEquals( "Unexpected number of results", expected.length, actual.size() );
|
||||
for ( int i = 0; i < expected.length; i++ ) {
|
||||
final Object[] exp = expected[i];
|
||||
final Object[] act = (Object[]) actual.get( i );
|
||||
assertArrayEquals( exp, act );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -334,4 +334,35 @@ public class ComponentQueryTest extends BaseEnversJPAFunctionalTestCase {
|
|||
assertEquals( "Expecte the symbol identfier of asset2 concatenated with 'Z'", Collections.singletonList( "XZ" ), actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11896")
|
||||
public void testOnClauseOnSingleSymbol() {
|
||||
List actual = getAuditReader().createQuery()
|
||||
.forEntitiesAtRevision( Asset.class, 1 )
|
||||
.addProjection( AuditEntity.id() )
|
||||
.traverseRelation( "singleSymbol", JoinType.LEFT, "s", AuditEntity.property( "s", "type" ).eq( type1 ) )
|
||||
.addOrder( AuditEntity.property( "s", "identifier" ).asc() )
|
||||
.up()
|
||||
.addOrder( AuditEntity.id().asc() )
|
||||
.getResultList();
|
||||
final List<Integer> expected = new ArrayList<>();
|
||||
Collections.addAll( expected, asset1.getId(), asset3.getId(), asset2.getId() );
|
||||
assertEquals( "Expected the correct ordering. Assets which do not have a symbol of type1 should come first (null first)", expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11896")
|
||||
public void testOnClauseOnMultiSymbol() {
|
||||
List actual = getAuditReader().createQuery()
|
||||
.forEntitiesAtRevision( Asset.class, 1 )
|
||||
.addProjection( AuditEntity.id() )
|
||||
.traverseRelation( "multiSymbols", JoinType.LEFT, "s", AuditEntity.property( "s", "type" ).eq( type1 ) )
|
||||
.addOrder( AuditEntity.property( "s", "identifier" ).asc() )
|
||||
.up()
|
||||
.addOrder( AuditEntity.id().asc() )
|
||||
.getResultList();
|
||||
final List<Integer> expected = new ArrayList<>();
|
||||
Collections.addAll( expected, asset1.getId(), asset2.getId(), asset3.getId() );
|
||||
assertEquals( "Expected the correct ordering. Assets which do not have a symbol of type1 should come first (null first)", expected, actual );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue