Skip to content

Commit 1fe1110

Browse files
committed
HHH-15106 - fk() SQM function
1 parent 415b28f commit 1fe1110

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,12 @@ default <T> JpaCriteriaQuery<T> except(CriteriaQuery<? extends T> query1, Criter
103103

104104
<T> JpaCriteriaQuery<T> except(boolean all, CriteriaQuery<? extends T> query1, CriteriaQuery<?>... queries);
105105

106+
106107
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
107108
// Paths
108109

110+
<P, F> JpaExpression<F> fk(Path<P> path);
111+
109112
@Override
110113
<X, T extends X> JpaPath<T> treat(Path<X> path, Class<T> type);
111114

hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.hibernate.query.criteria.JpaCompoundSelection;
2424
import org.hibernate.query.criteria.JpaExpression;
2525
import org.hibernate.query.criteria.JpaParameterExpression;
26+
import org.hibernate.query.criteria.JpaPath;
2627
import org.hibernate.query.criteria.JpaSearchedCase;
2728
import org.hibernate.query.criteria.JpaSelection;
2829
import org.hibernate.query.criteria.JpaSimpleCase;
@@ -146,6 +147,9 @@ <R> SqmTuple<R> tuple(
146147
@Override
147148
SqmPredicate wrap(Expression<Boolean>... expressions);
148149

150+
@Override
151+
<P, F> SqmExpression<F> fk(Path<P> path);
152+
149153
@Override
150154
<X, T extends X> SqmPath<T> treat(Path<X> path, Class<T> type);
151155

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
4040
import org.hibernate.query.ReturnableType;
4141
import org.hibernate.query.BindableType;
42+
import org.hibernate.query.SemanticException;
4243
import org.hibernate.query.sqm.BinaryArithmeticOperator;
4344
import org.hibernate.query.sqm.ComparisonOperator;
4445
import org.hibernate.query.sqm.NullPrecedence;
@@ -64,6 +65,8 @@
6465
import org.hibernate.query.sqm.tree.SqmTypedNode;
6566
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
6667
import org.hibernate.query.sqm.tree.domain.SqmBagJoin;
68+
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
69+
import org.hibernate.query.sqm.tree.domain.SqmFkExpression;
6770
import org.hibernate.query.sqm.tree.domain.SqmListJoin;
6871
import org.hibernate.query.sqm.tree.domain.SqmMapJoin;
6972
import org.hibernate.query.sqm.tree.domain.SqmPath;
@@ -132,6 +135,7 @@
132135
import jakarta.persistence.criteria.Selection;
133136
import jakarta.persistence.criteria.SetJoin;
134137
import jakarta.persistence.criteria.Subquery;
138+
import jakarta.persistence.metamodel.Bindable;
135139

136140
import static java.util.Arrays.asList;
137141
import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType;
@@ -342,6 +346,19 @@ public final SqmPredicate wrap(Expression<Boolean>... expressions) {
342346
return new SqmJunctionPredicate( Predicate.BooleanOperator.AND, predicates, this );
343347
}
344348

349+
@Override
350+
public <P, F> SqmExpression<F> fk(Path<P> path) {
351+
if ( path.getModel().getBindableType() != Bindable.BindableType.SINGULAR_ATTRIBUTE ) {
352+
throw new SemanticException( "Path should refer to a to-one attribute : " + path );
353+
}
354+
355+
if ( ! ( path instanceof SqmEntityValuedSimplePath ) ) {
356+
throw new SemanticException( "Path should refer to a to-one attribute : " + path );
357+
}
358+
359+
return new SqmFkExpression<>( (SqmEntityValuedSimplePath) path, this );
360+
}
361+
345362
@Override
346363
public <X, T extends X> SqmPath<T> treat(Path<X> path, Class<T> type) {
347364
return ( (SqmPath<X>) path ).treatAs( type );
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.orm.test.query.criteria;
8+
9+
import org.hibernate.testing.orm.domain.StandardDomainModel;
10+
import org.hibernate.testing.orm.junit.DomainModel;
11+
import org.hibernate.testing.orm.junit.SessionFactory;
12+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
13+
import org.junit.jupiter.api.Test;
14+
15+
/**
16+
* Simple {@link org.hibernate.query.sqm.NodeBuilder} tests
17+
*
18+
* @author Steve Ebersole
19+
*/
20+
@DomainModel( standardModels = StandardDomainModel.RETAIL )
21+
@SessionFactory
22+
public class NodeBuilderTests {
23+
@Test
24+
public void testFkExpression(SessionFactoryScope scope) {
25+
scope.inTransaction( (session) -> {
26+
final String hql = "from Order o where fk(o.salesAssociate) = 1";
27+
session.createSelectionQuery( hql ).getResultList();
28+
} );
29+
}
30+
}

0 commit comments

Comments
 (0)