Merge branch 'main' into wip/6.0
This commit is contained in:
commit
74a395d744
|
@ -743,4 +743,20 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
JpaOrder desc(Expression<?> x);
|
JpaOrder desc(Expression<?> x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an ordering by the ascending value of the expression.
|
||||||
|
* @param x expression used to define the ordering
|
||||||
|
* @param nullsFirst Whether <code>null</code> should be sorted first
|
||||||
|
* @return ascending ordering corresponding to the expression
|
||||||
|
*/
|
||||||
|
JpaOrder asc(Expression<?> x, boolean nullsFirst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an ordering by the descending value of the expression.
|
||||||
|
* @param x expression used to define the ordering
|
||||||
|
* @param nullsFirst Whether <code>null</code> should be sorted first
|
||||||
|
* @return descending ordering corresponding to the expression
|
||||||
|
*/
|
||||||
|
JpaOrder desc(Expression<?> x, boolean nullsFirst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ import org.hibernate.query.criteria.JpaCoalesce;
|
||||||
import org.hibernate.query.criteria.JpaCompoundSelection;
|
import org.hibernate.query.criteria.JpaCompoundSelection;
|
||||||
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||||
import org.hibernate.query.criteria.JpaExpression;
|
import org.hibernate.query.criteria.JpaExpression;
|
||||||
|
import org.hibernate.query.criteria.JpaOrder;
|
||||||
import org.hibernate.query.criteria.JpaParameterExpression;
|
import org.hibernate.query.criteria.JpaParameterExpression;
|
||||||
import org.hibernate.query.criteria.JpaSelection;
|
import org.hibernate.query.criteria.JpaSelection;
|
||||||
import org.hibernate.query.criteria.ValueHandlingMode;
|
import org.hibernate.query.criteria.ValueHandlingMode;
|
||||||
|
@ -397,6 +398,24 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
return new SqmSortSpecification( (SqmExpression<?>) x, SortOrder.DESCENDING );
|
return new SqmSortSpecification( (SqmExpression<?>) x, SortOrder.DESCENDING );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JpaOrder asc(Expression<?> x, boolean nullsFirst) {
|
||||||
|
return new SqmSortSpecification(
|
||||||
|
(SqmExpression<?>) x,
|
||||||
|
SortOrder.ASCENDING,
|
||||||
|
nullsFirst ? NullPrecedence.FIRST : NullPrecedence.LAST
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JpaOrder desc(Expression<?> x, boolean nullsFirst) {
|
||||||
|
return new SqmSortSpecification(
|
||||||
|
(SqmExpression<?>) x,
|
||||||
|
SortOrder.DESCENDING,
|
||||||
|
nullsFirst ? NullPrecedence.FIRST : NullPrecedence.LAST
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JpaCompoundSelection<Tuple> tuple(Selection<?>[] selections) {
|
public JpaCompoundSelection<Tuple> tuple(Selection<?>[] selections) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package org.hibernate.query.criteria.internal;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Jpa;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.TypedQuery;
|
||||||
|
import jakarta.persistence.criteria.CriteriaQuery;
|
||||||
|
import jakarta.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-14897")
|
||||||
|
@Jpa(
|
||||||
|
annotatedClasses = { NullPrecedenceTest.Foo.class }
|
||||||
|
)
|
||||||
|
public class NullPrecedenceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNullPrecedence(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( entityManager -> {
|
||||||
|
entityManager.persist( new Foo( 1L, null ) );
|
||||||
|
entityManager.persist( new Foo( 2L, "ABC" ) );
|
||||||
|
entityManager.persist( new Foo( 3L, "DEF" ) );
|
||||||
|
entityManager.persist( new Foo( 4L, "DEF" ) );
|
||||||
|
final HibernateCriteriaBuilder cb = (HibernateCriteriaBuilder) entityManager.getCriteriaBuilder();
|
||||||
|
|
||||||
|
final CriteriaQuery<Foo> cq = cb.createQuery( Foo.class );
|
||||||
|
final Root<Foo> foo = cq.from( Foo.class );
|
||||||
|
|
||||||
|
cq.orderBy(
|
||||||
|
cb.desc( foo.get( "bar" ), true ),
|
||||||
|
cb.desc( foo.get( "id" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
final TypedQuery<Foo> tq = entityManager.createQuery( cq );
|
||||||
|
|
||||||
|
final List<Foo> resultList = tq.getResultList();
|
||||||
|
assertEquals( 4, resultList.size() );
|
||||||
|
assertEquals( 1L, resultList.get( 0 ).getId() );
|
||||||
|
assertEquals( 4L, resultList.get( 1 ).getId() );
|
||||||
|
assertEquals( 3L, resultList.get( 2 ).getId() );
|
||||||
|
assertEquals( 2L, resultList.get( 3 ).getId() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Foo")
|
||||||
|
public static class Foo {
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
private String bar;
|
||||||
|
|
||||||
|
public Foo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Foo(long id, String bar) {
|
||||||
|
this.id = id;
|
||||||
|
this.bar = bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
public long getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBar() {
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBar(String bar) {
|
||||||
|
this.bar = bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue