HHH-17377 - Migrate to JPA 3.2

https://hibernate.atlassian.net/browse/HHH-17377
This commit is contained in:
Steve Ebersole 2023-10-31 21:02:26 -05:00
parent ab4439622b
commit 3c6e5c45c4
85 changed files with 1278 additions and 335 deletions

View File

@ -9,18 +9,20 @@ package org.hibernate;
import java.util.List;
import java.util.function.Consumer;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.LockModeType;
import jakarta.persistence.PessimisticLockScope;
import org.hibernate.graph.RootGraph;
import org.hibernate.jdbc.Work;
import org.hibernate.query.Query;
import org.hibernate.stat.SessionStatistics;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.ConnectionConsumer;
import jakarta.persistence.ConnectionFunction;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.EntityManager;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.PessimisticLockScope;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
@ -1599,4 +1601,32 @@ public interface Session extends SharedSessionContract, EntityManager {
*/
@Override @Deprecated(since = "6.0") @SuppressWarnings("rawtypes")
Query createQuery(CriteriaUpdate updateQuery);
@Override
default <C> void runWithConnection(ConnectionConsumer<C> action) {
doWork( connection -> {
try {
//noinspection unchecked
action.accept( (C) connection );
}
catch (Exception e) {
throw new RuntimeException( e );
}
} );
}
@Override
default <C, T> T callWithConnection(ConnectionFunction<C, T> function) {
return doReturningWork( (connection) -> {
try {
//noinspection unchecked
return function.apply( (C) connection );
}
catch (Exception e) {
throw new RuntimeException( e );
}
} );
}
}

View File

@ -178,7 +178,7 @@ public class NamedProcedureCallDefinitionImpl implements NamedProcedureCallDefin
this.position = position;
this.name = normalize( annotation.name() );
this.parameterMode = annotation.mode();
this.type = annotation.type();
this.type = (Class<T>) annotation.type();
}
public ParameterMemento toMemento(SessionFactoryImplementor sessionFactory) {

View File

@ -207,6 +207,11 @@ public class IdentifierGeneratorDefinition implements Serializable {
return new Index[0];
}
@Override
public String options() {
return "";
}
@Override
public Class<? extends Annotation> annotationType() {
return TableGenerator.class;
@ -252,6 +257,11 @@ public class IdentifierGeneratorDefinition implements Serializable {
return 50;
}
@Override
public String options() {
return "";
}
@Override
public Class<? extends Annotation> annotationType() {
return SequenceGenerator.class;

View File

@ -36,6 +36,7 @@ import jakarta.persistence.AssociationOverride;
import jakarta.persistence.AssociationOverrides;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.AttributeOverrides;
import jakarta.persistence.CheckConstraint;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
@ -707,6 +708,11 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
return columnDefinition;
}
@Override
public String options() {
return "";
}
@Override
public String table() {
return table;
@ -727,6 +733,16 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
return 0;
}
@Override
public CheckConstraint[] check() {
return new CheckConstraint[0];
}
@Override
public String comment() {
return "";
}
@Override
public Class<? extends Annotation> annotationType() {
return Column.class;

View File

@ -27,12 +27,13 @@ public class AttributeConversionInfo {
private final XAnnotatedElement source;
@SuppressWarnings({ "unchecked", "rawtypes" })
public AttributeConversionInfo(
Class<? extends AttributeConverter<?,?>> converterClass,
Class<? extends AttributeConverter> converterClass,
boolean conversionDisabled,
String attributeName,
XAnnotatedElement source) {
this.converterClass = converterClass;
this.converterClass = (Class<? extends AttributeConverter<?, ?>>) converterClass;
this.conversionDisabled = conversionDisabled;
this.attributeName = attributeName;
this.source = source;

View File

@ -8,6 +8,7 @@ package org.hibernate.boot.model.internal;
import java.lang.annotation.Annotation;
import jakarta.persistence.CheckConstraint;
import jakarta.persistence.Column;
import jakarta.persistence.MapKeyColumn;
@ -52,6 +53,11 @@ public class MapKeyColumnDelegator implements Column {
return column.columnDefinition();
}
@Override
public String options() {
return column.options();
}
@Override
public String table() {
return column.table();
@ -72,6 +78,16 @@ public class MapKeyColumnDelegator implements Column {
return column.scale();
}
@Override
public CheckConstraint[] check() {
return new CheckConstraint[0];
}
@Override
public String comment() {
return "";
}
@Override
public Class<? extends Annotation> annotationType() {
return Column.class;

View File

@ -8,6 +8,7 @@ package org.hibernate.boot.model.internal;
import java.lang.annotation.Annotation;
import jakarta.persistence.CheckConstraint;
import jakarta.persistence.Column;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.JoinColumn;
@ -59,6 +60,11 @@ public class MapKeyJoinColumnDelegator implements JoinColumn {
return column.columnDefinition();
}
@Override
public String options() {
return column.options();
}
@Override
public String table() {
return column.table();
@ -69,6 +75,16 @@ public class MapKeyJoinColumnDelegator implements JoinColumn {
return column.foreignKey();
}
@Override
public CheckConstraint[] check() {
return new CheckConstraint[0];
}
@Override
public String comment() {
return "";
}
@Override
public Class<? extends Annotation> annotationType() {
return Column.class;

View File

@ -12,8 +12,6 @@ import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import org.hibernate.CacheMode;
import org.hibernate.Filter;
import org.hibernate.FlushMode;
@ -63,10 +61,15 @@ import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.stat.SessionStatistics;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.FindOption;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.LockOption;
import jakarta.persistence.RefreshOption;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
@ -308,6 +311,11 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
delegate.lock( entity, lockMode, properties );
}
@Override
public void lock(Object entity, LockModeType lockMode, LockOption... options) {
}
@Override
public void flush() {
delegate.flush();
@ -908,6 +916,16 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
return delegate.find( entityClass, primaryKey, lockMode, properties );
}
@Override
public <T> T find(Class<T> entityClass, Object primaryKey, FindOption... options) {
return delegate.find( entityClass, primaryKey, options );
}
@Override
public <T> T find(EntityGraph<T> entityGraph, Object primaryKey, FindOption... options) {
return delegate.find( entityGraph, primaryKey, options );
}
@Override
public <T> T getReference(Class<T> entityClass, Object id) {
return delegate.getReference( entityClass, id );
@ -978,6 +996,11 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
delegate.refresh( entity, lockMode, properties );
}
@Override
public void refresh(Object entity, RefreshOption... options) {
delegate.refresh( entity, options );
}
@Override
public void refresh(String entityName, Object object) {
delegate.refresh( entityName, object );

View File

@ -11,10 +11,13 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.naming.NamingException;
import javax.naming.Reference;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.PersistenceUnitUtil;
import jakarta.persistence.Query;
import jakarta.persistence.SynchronizationType;
@ -146,6 +149,11 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getPersistenceUnitUtil();
}
@Override
public PersistenceUnitTransactionType getTransactionType() {
return delegate.getTransactionType();
}
@Override
public void addNamedQuery(String name, Query query) {
delegate.addNamedQuery( name, query );
@ -161,6 +169,16 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
delegate.addNamedEntityGraph( graphName, entityGraph );
}
@Override
public void runInTransaction(Consumer<EntityManager> work) {
delegate.runInTransaction( work );
}
@Override
public <R> R callInTransaction(Function<EntityManager, R> work) {
return delegate.callInTransaction( work );
}
@Override
public Set<String> getDefinedFilterNames() {
return delegate.getDefinedFilterNames();

View File

@ -44,10 +44,15 @@ import org.hibernate.query.criteria.JpaCriteriaInsert;
import org.hibernate.query.criteria.JpaCriteriaInsertSelect;
import org.hibernate.stat.SessionStatistics;
import jakarta.persistence.ConnectionConsumer;
import jakarta.persistence.ConnectionFunction;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.FindOption;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.LockOption;
import jakarta.persistence.RefreshOption;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
@ -547,6 +552,16 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().getEntityGraphs( entityClass );
}
@Override
public <C> void runWithConnection(ConnectionConsumer<C> action) {
}
@Override
public <C, T> T callWithConnection(ConnectionFunction<C, T> function) {
return null;
}
@Override
public <R> Query<R> createQuery(String queryString, Class<R> resultClass) {
return this.lazySession.get().createQuery( queryString, resultClass );
@ -840,6 +855,16 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().find( entityClass, primaryKey, lockMode, properties );
}
@Override
public <T> T find(Class<T> entityClass, Object primaryKey, FindOption... options) {
return this.lazySession.get().find( entityClass, primaryKey, options );
}
@Override
public <T> T find(EntityGraph<T> entityGraph, Object primaryKey, FindOption... options) {
return this.lazySession.get().find( entityGraph, primaryKey, options );
}
@Override
public void lock(Object entity, LockModeType lockMode) {
this.lazySession.get().lock( entity, lockMode );
@ -850,6 +875,11 @@ public class SessionLazyDelegator implements Session {
this.lazySession.get().lock( entity, lockMode, properties );
}
@Override
public void lock(Object entity, LockModeType lockMode, LockOption... options) {
this.lazySession.get().lock( entity, lockMode, options );
}
@Override
public void refresh(Object entity, Map<String, Object> properties) {
this.lazySession.get().refresh( entity, properties );
@ -865,6 +895,11 @@ public class SessionLazyDelegator implements Session {
this.lazySession.get().refresh( entity, lockMode, properties );
}
@Override
public void refresh(Object entity, RefreshOption... options) {
this.lazySession.get().refresh( entity, options );
}
@Override
public boolean contains(Object entity) {
return this.lazySession.get().contains( entity );

View File

@ -73,6 +73,7 @@ public interface SubGraph<J> extends Graph<J>, Subgraph<J> {
return addSubGraph( name, type );
}
@Override
default <X> SubGraph<X> addKeySubgraph(Attribute<J, X> attribute) {
return addKeySubGraph( (PersistentAttribute<J, X>) attribute );

View File

@ -20,6 +20,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
@ -124,7 +126,9 @@ import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.PersistenceUnitUtil;
import jakarta.persistence.Query;
import jakarta.persistence.SynchronizationType;
@ -976,6 +980,14 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
return jpaPersistenceUnitUtil;
}
@Override
public PersistenceUnitTransactionType getTransactionType() {
return fastSessionServices.transactionCoordinatorBuilder.isJta()
? PersistenceUnitTransactionType.JTA
: PersistenceUnitTransactionType.RESOURCE_LOCAL;
}
@Override
public void addNamedQuery(String name, Query query) {
validateNotClosed();
@ -1074,6 +1086,18 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
getMappingMetamodel().addNamedEntityGraph( graphName, (RootGraphImplementor<T>) entityGraph );
}
@Override
public void runInTransaction(Consumer<EntityManager> work) {
//noinspection unchecked,rawtypes
inTransaction( (Consumer) work );
}
@Override
public <R> R callInTransaction(Function<EntityManager, R> work) {
//noinspection unchecked,rawtypes
return (R) fromTransaction( (Function) work );
}
@Override
public boolean isClosed() {
return status == Status.CLOSED;

View File

@ -138,11 +138,15 @@ import org.hibernate.type.descriptor.WrapperOptions;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.FindOption;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.LockOption;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.RefreshOption;
import jakarta.persistence.TransactionRequiredException;
import jakarta.persistence.metamodel.Metamodel;
@ -171,9 +175,9 @@ import static org.hibernate.event.spi.LoadEventListener.INTERNAL_LOAD_NULLABLE;
import static org.hibernate.jpa.HibernateHints.HINT_BATCH_FETCH_SIZE;
import static org.hibernate.jpa.HibernateHints.HINT_ENABLE_SUBSELECT_FETCH;
import static org.hibernate.jpa.HibernateHints.HINT_FETCH_PROFILE;
import static org.hibernate.jpa.HibernateHints.HINT_FLUSH_MODE;
import static org.hibernate.jpa.HibernateHints.HINT_JDBC_BATCH_SIZE;
import static org.hibernate.jpa.HibernateHints.HINT_READ_ONLY;
import static org.hibernate.jpa.HibernateHints.HINT_FLUSH_MODE;
import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_LOCK_TIMEOUT;
import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_QUERY_TIMEOUT;
import static org.hibernate.jpa.SpecHints.HINT_SPEC_LOCK_TIMEOUT;
@ -2518,6 +2522,18 @@ public class SessionImpl
}
}
@Override
public <T> T find(Class<T> entityClass, Object primaryKey, FindOption... options) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <T> T find(EntityGraph<T> entityGraph, Object primaryKey, FindOption... options) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
private void checkTransactionNeededForLock(LockModeType lockModeType) {
if ( lockModeType != LockModeType.NONE ) {
checkTransactionNeededForUpdateOperation();
@ -2596,7 +2612,7 @@ public class SessionImpl
@Override
public void lock(Object entity, LockModeType lockModeType) {
lock( entity, lockModeType, null );
lock( entity, lockModeType, (Map<String,Object>) null );
}
@Override
@ -2617,6 +2633,12 @@ public class SessionImpl
}
}
@Override
public void lock(Object entity, LockModeType lockMode, LockOption... options) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public void refresh(Object entity, Map<String, Object> properties) {
refresh( entity, null, properties );
@ -2662,6 +2684,12 @@ public class SessionImpl
}
}
@Override
public void refresh(Object entity, RefreshOption... options) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
private LockOptions buildLockOptions(LockModeType lockModeType, Map<String, Object> properties) {
LockOptions lockOptions = new LockOptions();
if ( this.lockOptions != null ) { //otherwise the default LockOptions constructor is the same as DEFAULT_LOCK_OPTIONS

View File

@ -10,6 +10,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.PersistenceConfiguration;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.spi.LoadState;
import jakarta.persistence.spi.PersistenceProvider;
@ -194,6 +195,12 @@ public class HibernatePersistenceProvider implements PersistenceProvider {
}
};
@Override
public EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration configuration) {
// todo (jpa 3.2) : implement this
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public ProviderUtil getProviderUtil() {
return providerUtil;

View File

@ -8,6 +8,7 @@ package org.hibernate.jpa.internal;
import java.io.Serializable;
import jakarta.persistence.PersistenceUnitUtil;
import jakarta.persistence.metamodel.Attribute;
import org.hibernate.Hibernate;
import org.hibernate.MappingException;
@ -54,6 +55,11 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
}
}
@Override
public <E> boolean isLoaded(E entity, Attribute<? super E, ?> attribute) {
return Hibernate.isPropertyInitialized( entity, attribute.getName() );
}
@Override
public boolean isLoaded(Object entity) {
// added log message to help with HHH-7454, if state == LoadState,NOT_LOADED, returning true or false is not accurate.
@ -61,6 +67,35 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
return getLoadState( entity ) != NOT_LOADED;
}
@Override
public void load(Object entity, String attributeName) {
// todo (jpa 3.2) : implement this
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <E> void load(E entity, Attribute<? super E, ?> attribute) {
// todo (jpa 3.2) : implement this
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public void load(Object entity) {
Hibernate.initialize( entity );
}
@Override
public boolean isInstance(Object entity, Class<?> entityClass) {
// todo (jpa 3.2) : implement this
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <T> Class<? extends T> getClass(T entity) {
// todo (jpa 3.2) : implement this
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public Object getIdentifier(Object entity) {
if ( entity == null ) {
@ -92,6 +127,12 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
}
}
@Override
public Object getVersion(Object entity) {
// todo (jpa 3.2) : implement this
throw new UnsupportedOperationException( "Not yet implemented" );
}
private Object getIdentifierFromPersister(Object entity) {
final Class<?> entityClass = Hibernate.getClass( entity );
final EntityPersister persister;

View File

@ -57,12 +57,12 @@ public interface JpaMetamodel extends Metamodel {
/**
* Access to an entity supporting Hibernate's entity-name feature
*/
<X> EntityDomainType<X> entity(String entityName);
EntityDomainType<?> entity(String entityName);
/**
* Access to an embeddable type from FQN
*/
<X> EmbeddableDomainType<X> embeddable(String embeddableName);
EmbeddableDomainType<?> embeddable(String embeddableName);
/**
* Specialized handling for resolving entity-name references in

View File

@ -138,7 +138,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
}
@Override
public <X> EntityDomainType<X> entity(String entityName) {
public EntityDomainType<?> entity(String entityName) {
if ( entityName == null ) {
return null;
}
@ -146,12 +146,11 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
if ( !( managedType instanceof EntityDomainType<?> ) ) {
return null;
}
//noinspection unchecked
return (EntityDomainType<X>) managedType;
return (EntityDomainType<?>) managedType;
}
@Override
public <X> EmbeddableDomainType<X> embeddable(String embeddableName) {
public EmbeddableDomainType<?> embeddable(String embeddableName) {
if ( embeddableName == null ) {
return null;
}
@ -159,8 +158,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
if ( !( managedType instanceof EmbeddableDomainType<?> ) ) {
return null;
}
//noinspection unchecked
return (EmbeddableDomainType<X>) managedType;
return (EmbeddableDomainType<?>) managedType;
}
@Override
@ -172,9 +170,10 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
entityName = importInfo.importedName;
}
final EntityDomainType<X> entityDescriptor = entity( entityName );
final EntityDomainType<?> entityDescriptor = entity( entityName );
if ( entityDescriptor != null ) {
return entityDescriptor;
//noinspection unchecked
return (EntityDomainType<X>) entityDescriptor;
}
if ( loadedClass == null ) {
@ -428,7 +427,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
definition.getEntityName(),
definition.getJpaEntityName()
);
final EntityDomainType<Object> entityType = entity( definition.getEntityName() );
final EntityDomainType<Object> entityType = (EntityDomainType<Object>) entity( definition.getEntityName() );
if ( entityType == null ) {
throw new IllegalArgumentException(
"Attempted to register named entity graph [" + definition.getRegisteredName()
@ -520,7 +519,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
{
final String proxyEntityName = entityProxyInterfaceMap.get( javaType );
if ( proxyEntityName != null ) {
return entity( proxyEntityName );
return (EntityDomainType<T>) entity( proxyEntityName );
}
}

View File

@ -495,7 +495,7 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
}
@Override
public <X> EntityDomainType<X> entity(String entityName) {
public EntityDomainType<?> entity(String entityName) {
return jpaMetamodel.entity( entityName );
}

View File

@ -84,6 +84,8 @@ import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.NoResultException;
@ -1101,6 +1103,15 @@ public class ProcedureCallImpl<R>
throw new IllegalStateException( "Illegal attempt to set lock mode for a procedure calls" );
}
@Override
public ProcedureCallImplementor<R> setTimeout(Integer timeout) {
if ( timeout == null ) {
timeout = -1;
}
super.setTimeout( (int) timeout );
return this;
}
@Override
public LockModeType getLockMode() {
// the JPA spec requires IllegalStateException here, even
@ -1246,4 +1257,13 @@ public class ProcedureCallImpl<R>
return resultSetMapping;
}
@Override
public ProcedureCallImplementor<R> setCacheRetrieveMode(CacheRetrieveMode cacheRetrieveMode) {
return (ProcedureCallImplementor<R>) super.setCacheRetrieveMode( cacheRetrieveMode );
}
@Override
public ProcedureCallImplementor<R> setCacheStoreMode(CacheStoreMode cacheStoreMode) {
return (ProcedureCallImplementor<R>) super.setCacheStoreMode( cacheStoreMode );
}
}

View File

@ -15,9 +15,12 @@ import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.type.BasicTypeReference;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.Parameter;
import jakarta.persistence.ParameterMode;
import jakarta.persistence.StoredProcedureQuery;
import jakarta.persistence.TemporalType;
/**
@ -78,6 +81,15 @@ public interface ProcedureCallImplementor<R> extends ProcedureCall, QueryImpleme
@Override
ProcedureCallImplementor<R> setFlushMode(FlushModeType flushMode);
@Override
ProcedureCallImplementor<R> setCacheRetrieveMode(CacheRetrieveMode cacheRetrieveMode);
@Override
ProcedureCallImplementor<R> setCacheStoreMode(CacheStoreMode cacheStoreMode);
@Override
ProcedureCallImplementor<R> setTimeout(Integer timeout);
@Override
ProcedureCallImplementor<R> registerStoredProcedureParameter(int position, Class type, ParameterMode mode);

View File

@ -9,6 +9,8 @@ package org.hibernate.query;
import org.hibernate.AssertionFailure;
import org.hibernate.dialect.NullOrdering;
import jakarta.persistence.criteria.Nulls;
/**
* Enumerates the possibilities for the precedence of null values within
* query result sets sorted by an {@code ORDER BY} clause.
@ -19,15 +21,21 @@ public enum NullPrecedence {
/**
* Null precedence not specified. Relies on the RDBMS implementation.
*/
NONE,
NONE( Nulls.NONE ),
/**
* Null values appear at the beginning of the sorted collection.
*/
FIRST,
FIRST( Nulls.FIRST ),
/**
* Null values appear at the end of the sorted collection.
*/
LAST;
LAST( Nulls.LAST );
private final Nulls jpaValue;
NullPrecedence(Nulls jpaValue) {
this.jpaValue = jpaValue;
}
/**
* Is this null precedence the default for the given sort order and null ordering.
@ -96,4 +104,24 @@ public enum NullPrecedence {
final NullPrecedence value = parse( name );
return value != null ? value : defaultValue;
}
public Nulls getJpaValue() {
return jpaValue;
}
public static NullPrecedence fromJpaValue(Nulls jpaValue) {
switch ( jpaValue ) {
case NONE: {
return NullPrecedence.NONE;
}
case FIRST: {
return NullPrecedence.FIRST;
}
case LAST: {
return NullPrecedence.LAST;
}
}
throw new IllegalArgumentException( "Unexpected JPA Nulls - " + jpaValue );
}
}

View File

@ -35,6 +35,7 @@ import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.MapJoin;
import jakarta.persistence.criteria.Nulls;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
@ -1003,6 +1004,11 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence, boolean ignoreCase);
JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder, NullPrecedence nullPrecedence);
default JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder, Nulls nullPrecedence) {
return sort( sortExpression, sortOrder, NullPrecedence.fromJpaValue( nullPrecedence ) );
}
JpaOrder sort(JpaExpression<?> sortExpression, SortDirection sortOrder);
JpaOrder sort(JpaExpression<?> sortExpression);
@ -2695,7 +2701,6 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
*/
@Incubating
JpaExpression<String> arrayToString(Expression<? extends Object[]> arrayExpression, String separator);
/**
* Whether an array contains an element.
*

View File

@ -14,19 +14,19 @@ import jakarta.persistence.criteria.Predicate;
/**
* @author Steve Ebersole
*/
public interface JpaEntityJoin<T> extends JpaJoinedFrom<T,T> {
public interface JpaEntityJoin<L,R> extends JpaJoinedFrom<L,R> {
@Override
EntityDomainType<T> getModel();
EntityDomainType<R> getModel();
@Override
JpaEntityJoin<T> on(JpaExpression<Boolean> restriction);
JpaEntityJoin<L,R> on(JpaExpression<Boolean> restriction);
@Override
JpaEntityJoin<T> on(Expression<Boolean> restriction);
JpaEntityJoin<L,R> on(Expression<Boolean> restriction);
@Override
JpaEntityJoin<T> on(JpaPredicate... restrictions);
JpaEntityJoin<L,R> on(JpaPredicate... restrictions);
@Override
JpaEntityJoin<T> on(Predicate... restrictions);
JpaEntityJoin<L,R> on(Predicate... restrictions);
}

View File

@ -10,6 +10,7 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
/**
* API extension to the JPA {@link Expression} contract
@ -53,9 +54,11 @@ public interface JpaExpression<T> extends JpaSelection<T>, Expression<T> {
@Override
JpaPredicate in(Expression<Collection<?>> values);
JpaPredicate equalTo(Expression<T> that);
@Override
Predicate equalTo(Expression<?> value);
JpaPredicate equalTo(T that);
@Override
Predicate equalTo(Object value);
<X> JpaExpression<X> cast(Class<X> type);
}

View File

@ -11,9 +11,11 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.sqm.tree.SqmJoinType;
import jakarta.persistence.criteria.From;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.CollectionAttribute;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.ListAttribute;
import jakarta.persistence.metamodel.MapAttribute;
import jakarta.persistence.metamodel.SetAttribute;
@ -28,13 +30,27 @@ public interface JpaFrom<O,T> extends JpaPath<T>, JpaFetchParent<O,T>, From<O,T>
@Override
JpaFrom<O,T> getCorrelationParent();
<X> JpaEntityJoin<X> join(Class<X> entityJavaType);
@Override
<Y> JpaEntityJoin<T, Y> join(Class<Y> entityClass);
<X> JpaEntityJoin<X> join(EntityDomainType<X> entity);
@Override
<Y> JpaJoin<T, Y> join(Class<Y> entityClass, JoinType joinType);
<X> JpaEntityJoin<X> join(Class<X> entityJavaType, SqmJoinType joinType);
@Override
<Y> JpaJoin<T, Y> join(EntityType<Y> entity);
<X> JpaEntityJoin<X> join(EntityDomainType<X> entity, SqmJoinType joinType);
@Override
<Y> JpaJoin<T, Y> join(EntityType<Y> entity, JoinType joinType);
//
// @Override
// <Y> JpaEntityJoin<Y> join(Class<Y> entityClass);
//
// <X> JpaEntityJoin<X> join(EntityDomainType<X> entity);
//
// <X> JpaEntityJoin<X> join(Class<X> entityJavaType, SqmJoinType joinType);
//
// <X> JpaEntityJoin<X> join(EntityDomainType<X> entity, SqmJoinType joinType);
@Incubating
<X> JpaDerivedJoin<X> join(Subquery<X> subquery);
@ -124,4 +140,10 @@ public interface JpaFrom<O,T> extends JpaPath<T>, JpaFetchParent<O,T>, From<O,T>
@Override
<X, K, V> JpaMapJoin<X, K, V> joinMap(String attributeName, JoinType jt);
@Override
<S extends T> JpaFrom<O,S> treatAs(Class<S> treatJavaType);
@Override
<S extends T> JpaFrom<O,S> treatAs(EntityDomainType<S> treatJavaType);
}

View File

@ -20,23 +20,23 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute;
*
* @author Steve Ebersole
*/
public interface JpaJoin<O, T> extends JpaJoinedFrom<O, T>, Join<O, T> {
public interface JpaJoin<L, R> extends JpaFrom<L,R>, Join<L,R> {
@Override
PersistentAttribute<? super O, ?> getAttribute();
PersistentAttribute<? super L, ?> getAttribute();
JpaJoin<O, T> on(JpaExpression<Boolean> restriction);
JpaJoin<L, R> on(JpaExpression<Boolean> restriction);
@Override
JpaJoin<O, T> on(Expression<Boolean> restriction);
JpaJoin<L, R> on(Expression<Boolean> restriction);
JpaJoin<O, T> on(JpaPredicate... restrictions);
JpaJoin<L, R> on(JpaPredicate... restrictions);
@Override
JpaJoin<O, T> on(Predicate... restrictions);
JpaJoin<L, R> on(Predicate... restrictions);
@Override
<S extends T> JpaJoin<O, S> treatAs(Class<S> treatAsType);
<S extends R> JpaJoin<L, S> treatAs(Class<S> treatAsType);
@Override
<S extends T> JpaJoin<O, S> treatAs(EntityDomainType<S> treatAsType);
<S extends R> JpaJoin<L, S> treatAs(EntityDomainType<S> treatAsType);
}

View File

@ -19,15 +19,15 @@ import jakarta.persistence.criteria.Predicate;
*
* @author Steve Ebersole
*/
public interface JpaJoinedFrom<O,T> extends JpaFrom<O, T> {
public interface JpaJoinedFrom<L, R> extends JpaFrom<L,R>, JpaJoin<L,R> {
JpaJoinedFrom<O, T> on(JpaExpression<Boolean> restriction);
JpaJoinedFrom<L, R> on(JpaExpression<Boolean> restriction);
JpaJoinedFrom<O, T> on(Expression<Boolean> restriction);
JpaJoinedFrom<L, R> on(Expression<Boolean> restriction);
JpaJoinedFrom<O, T> on(JpaPredicate... restrictions);
JpaJoinedFrom<L, R> on(JpaPredicate... restrictions);
JpaJoinedFrom<O, T> on(Predicate... restrictions);
JpaJoinedFrom<L, R> on(Predicate... restrictions);
JpaPredicate getOn();

View File

@ -6,9 +6,9 @@
*/
package org.hibernate.query.criteria;
import jakarta.persistence.criteria.Nulls;
import jakarta.persistence.criteria.Order;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortDirection;
/**
@ -24,12 +24,12 @@ public interface JpaOrder extends Order, JpaCriteriaNode {
/**
* Set the precedence of nulls for this order element
*/
JpaOrder nullPrecedence(NullPrecedence precedence);
JpaOrder nullPrecedence(Nulls precedence);
/**
* The precedence for nulls for this order element
*/
NullPrecedence getNullPrecedence();
Nulls getNullPrecedence();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -9,6 +9,7 @@ package org.hibernate.query.criteria;
import java.util.Collection;
import java.util.Map;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.metamodel.MapAttribute;
import jakarta.persistence.metamodel.PluralAttribute;
@ -55,10 +56,10 @@ public interface JpaPath<T> extends JpaExpression<T>, Path<T> {
<Y> JpaPath<Y> get(SingularAttribute<? super T, Y> attribute);
@Override
<E, C extends Collection<E>> JpaExpression<C> get(PluralAttribute<T, C, E> collection);
<E, C extends Collection<E>> Expression<C> get(PluralAttribute<? super T, C, E> collection);
@Override
<K, V, M extends Map<K, V>> JpaExpression<M> get(MapAttribute<T, K, V> map);
<K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<? super T, K, V> map);
@Override
JpaExpression<Class<? extends T>> type();

View File

@ -33,7 +33,7 @@ public interface JpaSubQuery<T> extends Subquery<T>, JpaSelectCriteria<T>, JpaEx
<X> JpaCrossJoin<X> correlate(JpaCrossJoin<X> parentCrossJoin);
<X> JpaEntityJoin<X> correlate(JpaEntityJoin<X> parentEntityJoin);
<X> JpaEntityJoin<T,X> correlate(JpaEntityJoin<T,X> parentEntityJoin);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Limit/Offset/Fetch clause

View File

@ -23,8 +23,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import jakarta.persistence.criteria.CriteriaBuilder;
import org.hibernate.Incubating;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortDirection;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.criteria.JpaCoalesce;
@ -56,22 +56,25 @@ import org.hibernate.query.criteria.JpaSubQuery;
import org.hibernate.query.criteria.JpaValues;
import org.hibernate.query.criteria.JpaWindow;
import org.hibernate.query.criteria.JpaWindowFrame;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.sqm.TemporalUnit;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CollectionJoin;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.MapJoin;
import jakarta.persistence.criteria.Nulls;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Selection;
import jakarta.persistence.criteria.SetJoin;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.criteria.TemporalField;
public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilder {
private final HibernateCriteriaBuilder criteriaBuilder;
@ -313,6 +316,11 @@ public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilde
return criteriaBuilder.localTime();
}
@Override
public <N, T extends Temporal> Expression<N> extract(TemporalField<N, T> field, Expression<T> temporal) {
return null;
}
@Override
public <P, F> JpaExpression<F> fk(Path<P> path) {
return criteriaBuilder.fk( path );
@ -328,6 +336,36 @@ public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilde
return criteriaBuilder.treat( root, type );
}
@Override
public <T> CriteriaQuery<T> union(CriteriaQuery<? extends T> left, CriteriaQuery<? extends T> right) {
return criteriaBuilder.union( left, right );
}
@Override
public <T> CriteriaQuery<T> unionAll(CriteriaQuery<? extends T> left, CriteriaQuery<? extends T> right) {
return criteriaBuilder.unionAll( left, right );
}
@Override
public <T> CriteriaQuery<T> intersect(CriteriaQuery<? super T> left, CriteriaQuery<? super T> right) {
return criteriaBuilder.intersect( left, right );
}
@Override
public <T> CriteriaQuery<T> intersectAll(CriteriaQuery<? super T> left, CriteriaQuery<? super T> right) {
return criteriaBuilder.intersectAll( left, right );
}
@Override
public <T> CriteriaQuery<T> except(CriteriaQuery<T> left, CriteriaQuery<?> right) {
return criteriaBuilder.except( left, right );
}
@Override
public <T> CriteriaQuery<T> exceptAll(CriteriaQuery<T> left, CriteriaQuery<?> right) {
return criteriaBuilder.exceptAll( left, right );
}
@Override
public <X, T, V extends T> JpaJoin<X, V> treat(Join<X, T> join, Class<V> type) {
return criteriaBuilder.treat( join, type );
@ -823,6 +861,11 @@ public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilde
return criteriaBuilder.and( restrictions );
}
@Override
public Predicate and(List<Predicate> restrictions) {
return null;
}
@Override
public JpaPredicate or(Expression<Boolean> x, Expression<Boolean> y) {
return criteriaBuilder.or( x, y );
@ -833,6 +876,11 @@ public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilde
return criteriaBuilder.or( restrictions );
}
@Override
public Predicate or(List<Predicate> restrictions) {
return criteriaBuilder.or( restrictions );
}
@Override
public JpaPredicate not(Expression<Boolean> restriction) {
return criteriaBuilder.not( restriction );
@ -1129,6 +1177,11 @@ public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilde
return criteriaBuilder.notLike( x, pattern, escapeChar );
}
@Override
public Expression<String> concat(List<Expression<String>> expressions) {
return criteriaBuilder.concat( expressions );
}
@Override
public JpaPredicate notIlike(Expression<String> x, Expression<String> pattern) {
return criteriaBuilder.notIlike( x, pattern );
@ -1234,6 +1287,16 @@ public class HibernateCriteriaBuilderDelegate implements HibernateCriteriaBuilde
return criteriaBuilder.desc( x );
}
@Override
public Order asc(Expression<?> expression, Nulls nullPrecedence) {
return criteriaBuilder.asc( expression, nullPrecedence );
}
@Override
public Order desc(Expression<?> expression, Nulls nullPrecedence) {
return criteriaBuilder.desc( expression, nullPrecedence );
}
@Override
public JpaOrder asc(Expression<?> x, boolean nullsFirst) {
return criteriaBuilder.asc( x, nullsFirst );

View File

@ -32,6 +32,8 @@ import org.hibernate.type.descriptor.java.EnumJavaType;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
@ -222,6 +224,21 @@ public class FullyQualifiedReflectivePathTerminal
return null;
}
@Override
public Predicate notEqualTo(Expression value) {
return null;
}
@Override
public Predicate notEqualTo(Object value) {
return null;
}
@Override
public Expression cast(Class type) {
return null;
}
@Override
public SqmPredicate in(Object... values) {
return null;

View File

@ -227,6 +227,7 @@ import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
import jakarta.persistence.criteria.Nulls;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.metamodel.Bindable;
import jakarta.persistence.metamodel.SingularAttribute;
@ -1295,10 +1296,11 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
}
}
@SuppressWarnings("rawtypes")
private EntityDomainType<R> getResultEntity() {
final JpaMetamodelImplementor jpaMetamodel = creationContext.getJpaMetamodel();
if ( expectedResultEntity != null ) {
final EntityDomainType<R> entityDescriptor = jpaMetamodel.entity( expectedResultEntity );
final EntityDomainType entityDescriptor = jpaMetamodel.entity( expectedResultEntity );
if ( entityDescriptor == null ) {
throw new SemanticException( "Query has no 'from' clause, and the result type '"
+ expectedResultEntity + "' is not an entity type", query );
@ -2223,7 +2225,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
try {
final SqmQualifiedJoin<X, ?> join = getJoin( sqmRoot, joinType, qualifiedJoinTargetContext, alias, fetch );
final HqlParser.JoinRestrictionContext joinRestrictionContext = parserJoin.joinRestriction();
if ( join instanceof SqmEntityJoin<?> || join instanceof SqmDerivedJoin<?> || join instanceof SqmCteJoin<?> ) {
if ( join instanceof SqmEntityJoin<?,?> || join instanceof SqmDerivedJoin<?> || join instanceof SqmCteJoin<?> ) {
sqmRoot.addSqmJoin( join );
}
else if ( join instanceof SqmAttributeJoin<?, ?> ) {

View File

@ -149,7 +149,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
}
@Override
public <E> void replace(SqmEntityJoin<E> sqmJoin, SqmRoot<E> sqmRoot) {
public <E> void replace(SqmEntityJoin<?,E> sqmJoin, SqmRoot<E> sqmRoot) {
final String alias = sqmJoin.getExplicitAlias();
if ( alias != null ) {
final String aliasToUse = jpaCompliance.isJpaQueryComplianceEnabled()
@ -241,8 +241,8 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
else if ( parentRegistered instanceof SqmCrossJoin<?> ) {
correlated = selectQuery.correlate( (SqmCrossJoin<?>) parentRegistered );
}
else if ( parentRegistered instanceof SqmEntityJoin<?> ) {
correlated = selectQuery.correlate( (SqmEntityJoin<?>) parentRegistered );
else if ( parentRegistered instanceof SqmEntityJoin<?,?> ) {
correlated = selectQuery.correlate( (SqmEntityJoin<?,?>) parentRegistered );
}
else {
throw new UnsupportedOperationException( "Can't correlate from node: " + parentRegistered );

View File

@ -46,7 +46,7 @@ public class SqmTreeCreationHelper {
SqmTreeCreationLogger.LOGGER.debugf( "Handling secondary root path as cross-join - %s", sqmRoot.getEntityName() );
final String alias = extractAlias( fromRootContext.variable(), sqmBuilder );
final SqmEntityJoin<E> pseudoCrossJoin = new SqmEntityJoin<>(
final SqmEntityJoin<?,E> pseudoCrossJoin = new SqmEntityJoin<>(
sqmRoot.getManagedType(),
alias,
SqmJoinType.CROSS,

View File

@ -7,8 +7,8 @@
package org.hibernate.query.hql.spi;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.domain.SqmSimplePath;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
/**
* @asciidoc

View File

@ -10,13 +10,12 @@ import java.util.function.Function;
import org.hibernate.Incubating;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.select.SqmAliasedNode;
import org.hibernate.spi.NavigablePath;
/**
* Registry for SqmPath references providing the ability to access them
@ -52,7 +51,7 @@ public interface SqmPathRegistry {
* has used the previous registration between its registration and this call.
* Generally, most callers want {@link #register(SqmPath)} instead.
*/
<E> void replace(SqmEntityJoin<E> sqmJoin, SqmRoot<E> sqmRoot);
<E> void replace(SqmEntityJoin<?,E> sqmJoin, SqmRoot<E> sqmRoot);
/**
* Find a SqmFrom by its identification variable (alias).

View File

@ -567,6 +567,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
return getQueryOptions().getTimeout();
}
@Override
public CommonQueryContract setTimeout(int timeout) {
getQueryOptions().setTimeout( timeout );

View File

@ -109,6 +109,7 @@ import jakarta.persistence.Parameter;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.TemporalType;
import jakarta.persistence.Tuple;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.metamodel.SingularAttribute;
import static org.hibernate.jpa.HibernateHints.HINT_NATIVE_LOCK_MODE;
@ -1203,6 +1204,15 @@ public class NativeQueryImpl<R>
return this;
}
@Override
public TypedQuery<R> setTimeout(Integer timeout) {
if ( timeout == null ) {
timeout = -1;
}
super.setTimeout( (int) timeout );
return this;
}
@Override
public NativeQueryImplementor<R> setCacheable(boolean cacheable) {
super.setCacheable( cacheable );

View File

@ -64,6 +64,7 @@ import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.MapJoin;
import jakarta.persistence.criteria.Nulls;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;

View File

@ -166,7 +166,7 @@ public interface SemanticQueryWalker<T> {
T visitPluralPartJoin(SqmPluralPartJoin<?, ?> joinedFromElement);
T visitQualifiedEntityJoin(SqmEntityJoin<?> joinedFromElement);
T visitQualifiedEntityJoin(SqmEntityJoin<?,?> joinedFromElement);
T visitQualifiedAttributeJoin(SqmAttributeJoin<?, ?> joinedFromElement);
@ -174,7 +174,7 @@ public interface SemanticQueryWalker<T> {
return visitCrossJoin( join );
}
default T visitCorrelatedEntityJoin(SqmCorrelatedEntityJoin<?> join) {
default T visitCorrelatedEntityJoin(SqmCorrelatedEntityJoin<?,?> join) {
return visitQualifiedEntityJoin( join );
}

View File

@ -1006,6 +1006,15 @@ public class QuerySqmImpl<R>
return this;
}
@Override
public SqmQueryImplementor<R> setTimeout(Integer timeout) {
if ( timeout == null ) {
timeout = -1;
}
setTimeout( (int) timeout );
return this;
}
@Override
public SqmQueryImplementor<R> setCacheable(boolean cacheable) {
super.setCacheable( cacheable );

View File

@ -172,12 +172,15 @@ import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.MapJoin;
import jakarta.persistence.criteria.Nulls;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Selection;
import jakarta.persistence.criteria.SetJoin;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.criteria.TemporalField;
import jakarta.persistence.metamodel.Bindable;
import static java.util.Arrays.asList;
@ -541,6 +544,42 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
return ( (SqmRoot<X>) root ).treatAs( type );
}
@Override
public <T> CriteriaQuery<T> union(CriteriaQuery<? extends T> left, CriteriaQuery<? extends T> right) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <T> CriteriaQuery<T> unionAll(CriteriaQuery<? extends T> left, CriteriaQuery<? extends T> right) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <T> CriteriaQuery<T> intersect(CriteriaQuery<? super T> left, CriteriaQuery<? super T> right) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <T> CriteriaQuery<T> intersectAll(CriteriaQuery<? super T> left, CriteriaQuery<? super T> right) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <T> CriteriaQuery<T> except(CriteriaQuery<T> left, CriteriaQuery<?> right) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <T> CriteriaQuery<T> exceptAll(CriteriaQuery<T> left, CriteriaQuery<?> right) {
// todo (jpa 3.2) : implement
throw new UnsupportedOperationException( "Not yet implemented" );
}
@Override
public <X, T, V extends T> SqmSingularJoin<X, V> treat(Join<X, T> join, Class<V> type) {
return ( (SqmSingularJoin<X, T>) join ).treatAs( type );
@ -596,6 +635,16 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
return new SqmSortSpecification( (SqmExpression<?>) x, SortDirection.DESCENDING );
}
@Override
public Order asc(Expression<?> expression, Nulls nullPrecedence) {
return new SqmSortSpecification( (SqmExpression<?>) expression, SortDirection.ASCENDING, NullPrecedence.fromJpaValue( nullPrecedence ) );
}
@Override
public Order desc(Expression<?> expression, Nulls nullPrecedence) {
return new SqmSortSpecification( (SqmExpression<?>) expression, SortDirection.DESCENDING, NullPrecedence.fromJpaValue( nullPrecedence ) );
}
@Override
public JpaOrder asc(Expression<?> x, boolean nullsFirst) {
return new SqmSortSpecification(
@ -1746,6 +1795,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
);
}
@Override
public <N, T extends Temporal> Expression<N> extract(TemporalField<N, T> field, Expression<T> temporal) {
return null;
}
@Override
public <T> SqmFunction<T> function(String name, Class<T> type, Expression<?>[] args) {
final BasicType<T> resultType = getTypeConfiguration().standardBasicTypeForJavaType( type );
@ -2065,6 +2119,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
return new SqmJunctionPredicate( Predicate.BooleanOperator.AND, predicates, this );
}
@Override
public Predicate and(List<Predicate> restrictions) {
return null;
}
@Override
public SqmPredicate or(Expression<Boolean> x, Expression<Boolean> y) {
return new SqmJunctionPredicate(
@ -2088,6 +2147,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
return new SqmJunctionPredicate( Predicate.BooleanOperator.OR, predicates, this );
}
@Override
public Predicate or(List<Predicate> restrictions) {
return null;
}
@Override
public SqmPredicate not(Expression<Boolean> restriction) {
return wrap( restriction ).not();
@ -2610,6 +2674,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
return not( like( x, pattern, escapeChar ) );
}
@Override
public Expression<String> concat(List<Expression<String>> expressions) {
return null;
}
@Override
public SqmPredicate notIlike(Expression<String> x, Expression<String> pattern) {
return not( ilike( x, pattern ) );

View File

@ -22,14 +22,14 @@ import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
import org.hibernate.query.sqm.tree.domain.SqmCteRoot;
import org.hibernate.query.sqm.tree.domain.SqmDerivedRoot;
import org.hibernate.query.sqm.tree.domain.SqmElementAggregateFunction;
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmFkExpression;
import org.hibernate.query.sqm.tree.domain.SqmIndexAggregateFunction;
import org.hibernate.query.sqm.tree.domain.SqmFunctionPath;
import org.hibernate.query.sqm.tree.domain.SqmIndexedCollectionAccessPath;
import org.hibernate.query.sqm.tree.domain.SqmMapEntryReference;
import org.hibernate.query.sqm.tree.domain.SqmElementAggregateFunction;
import org.hibernate.query.sqm.tree.domain.SqmIndexAggregateFunction;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
@ -320,8 +320,8 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
else if ( sqmJoin instanceof SqmCrossJoin<?> ) {
consumeCrossJoin( ( (SqmCrossJoin<?>) sqmJoin ), transitive );
}
else if ( sqmJoin instanceof SqmEntityJoin<?> ) {
consumeEntityJoin( ( (SqmEntityJoin<?>) sqmJoin ), transitive );
else if ( sqmJoin instanceof SqmEntityJoin<?,?> ) {
consumeEntityJoin( ( (SqmEntityJoin<?,?>) sqmJoin ), transitive );
}
else if ( sqmJoin instanceof SqmDerivedJoin<?> ) {
consumeDerivedJoin( ( (SqmDerivedJoin<?>) sqmJoin ), transitive );
@ -352,7 +352,7 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
}
}
protected void consumeEntityJoin(SqmEntityJoin<?> sqmJoin, boolean transitive) {
protected void consumeEntityJoin(SqmEntityJoin<?,?> sqmJoin, boolean transitive) {
if ( sqmJoin.getJoinPredicate() != null ) {
sqmJoin.getJoinPredicate().accept( this );
}
@ -415,10 +415,12 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
}
@Override
public Object visitQualifiedEntityJoin(SqmEntityJoin<?> joinedFromElement) {
public Object visitQualifiedEntityJoin(SqmEntityJoin<?,?> joinedFromElement) {
return joinedFromElement;
}
@Override
public Object visitQualifiedAttributeJoin(SqmAttributeJoin<?,?> joinedFromElement) {
return joinedFromElement;

View File

@ -6,10 +6,19 @@
*/
package org.hibernate.query.sqm.spi;
import java.util.List;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.sql.ast.tree.predicate.Junction;
import jakarta.persistence.criteria.Predicate;
import java.util.concurrent.atomic.AtomicLong;
@ -68,6 +77,63 @@ public class SqmCreationHelper {
return buildSubNavigablePath( navigablePath, subNavigable, alias );
}
public static SqmPredicate combinePredicates(SqmPredicate baseRestriction, List<SqmPredicate> incomingRestrictions) {
if ( CollectionHelper.isEmpty( incomingRestrictions ) ) {
return baseRestriction;
}
SqmPredicate combined = combinePredicates( null, baseRestriction );
for ( int i = 0; i < incomingRestrictions.size(); i++ ) {
combined = combinePredicates( combined, incomingRestrictions.get(i) );
}
return combined;
}
public static SqmPredicate combinePredicates(SqmPredicate baseRestriction, SqmPredicate incomingRestriction) {
if ( baseRestriction == null ) {
return incomingRestriction;
}
if ( incomingRestriction == null ) {
return baseRestriction;
}
final SqmJunctionPredicate combinedPredicate;
if ( baseRestriction instanceof SqmJunctionPredicate ) {
// we already had multiple before
final SqmJunctionPredicate junction = (SqmJunctionPredicate) baseRestriction;
if ( junction.getPredicates().isEmpty() ) {
return incomingRestriction;
}
if ( junction.getOperator() == Predicate.BooleanOperator.AND ) {
combinedPredicate = junction;
}
else {
combinedPredicate = new SqmJunctionPredicate(
Predicate.BooleanOperator.AND,
baseRestriction.getExpressible(),
baseRestriction.nodeBuilder()
);
combinedPredicate.getPredicates().add( baseRestriction );
}
}
else {
combinedPredicate = new SqmJunctionPredicate(
Predicate.BooleanOperator.AND,
baseRestriction.getExpressible(),
baseRestriction.nodeBuilder()
);
combinedPredicate.getPredicates().add( baseRestriction );
}
combinedPredicate.getPredicates().add( incomingRestriction );
return combinedPredicate;
}
private SqmCreationHelper() {
}

View File

@ -3286,8 +3286,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
else if ( sqmJoin instanceof SqmCrossJoin<?> ) {
return consumeCrossJoin( ( (SqmCrossJoin<?>) sqmJoin ), lhsTableGroup, transitive );
}
else if ( sqmJoin instanceof SqmEntityJoin<?> ) {
return consumeEntityJoin( ( (SqmEntityJoin<?>) sqmJoin ), lhsTableGroup, transitive );
else if ( sqmJoin instanceof SqmEntityJoin<?,?> ) {
return consumeEntityJoin( ( (SqmEntityJoin<?,?>) sqmJoin ), lhsTableGroup, transitive );
}
else if ( sqmJoin instanceof SqmDerivedJoin<?> ) {
return consumeDerivedJoin( ( (SqmDerivedJoin<?>) sqmJoin ), lhsTableGroup, transitive );
@ -3487,7 +3487,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return tableGroup;
}
private TableGroup consumeEntityJoin(SqmEntityJoin<?> sqmJoin, TableGroup lhsTableGroup, boolean transitive) {
private TableGroup consumeEntityJoin(SqmEntityJoin<?,?> sqmJoin, TableGroup lhsTableGroup, boolean transitive) {
final EntityPersister entityDescriptor = resolveEntityPersister( sqmJoin.getReferencedPathSource() );
final SqlAstJoinType correspondingSqlJoinType = sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType();
@ -4093,7 +4093,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
}
@Override
public Expression visitQualifiedEntityJoin(SqmEntityJoin<?> sqmJoin) {
public Expression visitQualifiedEntityJoin(SqmEntityJoin<?,?> sqmJoin) {
final TableGroup existing = getFromClauseAccess().findTableGroup( sqmJoin.getNavigablePath() );
if ( existing != null ) {
log.tracef( "SqmEntityJoin [%s] resolved to existing TableGroup [%s]", sqmJoin, existing );

View File

@ -8,6 +8,7 @@ package org.hibernate.query.sqm.tree.delete;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.hibernate.query.criteria.JpaCriteriaDelete;
import org.hibernate.query.sqm.NodeBuilder;
@ -18,12 +19,16 @@ import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter;
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.EntityType;
/**
* @author Steve Ebersole
@ -136,4 +141,22 @@ public class SqmDeleteStatement<T>
SqmFromClause.appendTreatJoins( root, sb );
super.appendHqlString( sb );
}
@Override
public <U> Subquery<U> subquery(EntityType<U> type) {
throw new UnsupportedOperationException( "DELETE query cannot be sub-query" );
}
@Override
public Set<ParameterExpression<?>> getParameters() {
// At this level, the number of parameters may still be growing as
// nodes are added to the Criteria - so we re-calculate this every
// time.
//
// for a "finalized" set of parameters, use `#resolveParameters` instead
assert getQuerySource() == SqmQuerySource.CRITERIA;
return getSqmParameters().stream()
.filter( parameterExpression -> !( parameterExpression instanceof ValueBindJpaCriteriaParameter ) )
.collect( Collectors.toSet() );
}
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.query.sqm.tree.domain;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.criteria.JpaPredicate;
@ -18,26 +19,25 @@ import org.hibernate.query.sqm.spi.SqmCreationHelper;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
import org.hibernate.spi.NavigablePath;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Predicate;
/**
* Models a join based on a mapped attribute reference.
*
* @author Steve Ebersole
*/
public abstract class AbstractSqmAttributeJoin<O,T>
extends AbstractSqmQualifiedJoin<O,T>
implements SqmAttributeJoin<O,T> {
public abstract class AbstractSqmAttributeJoin<L, R>
extends AbstractSqmQualifiedJoin<L, R>
implements SqmAttributeJoin<L, R> {
private boolean fetched;
public AbstractSqmAttributeJoin(
SqmFrom<?,O> lhs,
SqmFrom<?, L> lhs,
SqmJoinable joinedNavigable,
String alias,
SqmJoinType joinType,
@ -55,7 +55,7 @@ public abstract class AbstractSqmAttributeJoin<O,T>
}
protected AbstractSqmAttributeJoin(
SqmFrom<?,O> lhs,
SqmFrom<?, L> lhs,
NavigablePath navigablePath,
SqmJoinable joinedNavigable,
String alias,
@ -65,7 +65,7 @@ public abstract class AbstractSqmAttributeJoin<O,T>
//noinspection unchecked
super(
navigablePath,
(SqmPathSource<T>) joinedNavigable,
(SqmPathSource<R>) joinedNavigable,
lhs,
alias,
joinType,
@ -76,13 +76,13 @@ public abstract class AbstractSqmAttributeJoin<O,T>
}
@Override
public SqmFrom<?, O> getLhs() {
public SqmFrom<?, L> getLhs() {
//noinspection unchecked
return (SqmFrom<?, O>) super.getLhs();
return (SqmFrom<?, L>) super.getLhs();
}
@Override
public JavaType<T> getNodeJavaType() {
public JavaType<R> getNodeJavaType() {
return getJavaTypeDescriptor();
}
@ -120,37 +120,23 @@ public abstract class AbstractSqmAttributeJoin<O,T>
// JPA
@Override
public PersistentAttribute<? super O, ?> getAttribute() {
public PersistentAttribute<? super L, ?> getAttribute() {
//noinspection unchecked
return (PersistentAttribute<? super O, ?>) getReferencedPathSource();
return (PersistentAttribute<? super L, ?>) getReferencedPathSource();
}
@Override
public SqmAttributeJoin<O, T> on(JpaExpression<Boolean> restriction) {
super.on( restriction );
return this;
public SqmAttributeJoin<L, R> on(JpaExpression<Boolean> restriction) {
return (SqmAttributeJoin<L, R>) super.on( restriction );
}
@Override
public SqmAttributeJoin<O, T> on(Expression<Boolean> restriction) {
super.on( restriction );
return this;
public SqmAttributeJoin<L, R> on(JpaPredicate... restrictions) {
return (SqmAttributeJoin<L, R>) super.on( restrictions );
}
@Override
public SqmAttributeJoin<O, T> on(JpaPredicate... restrictions) {
super.on( restrictions );
return this;
}
@Override
public SqmAttributeJoin<O, T> on(Predicate... restrictions) {
super.on( restrictions );
return this;
}
@Override
public SqmFrom<?, O> getParent() {
public SqmFrom<?, L> getParent() {
return getLhs();
}
@ -158,4 +144,14 @@ public abstract class AbstractSqmAttributeJoin<O,T>
public JoinType getJoinType() {
return getSqmJoinType().getCorrespondingJpaJoinType();
}
@Override
public <S extends R> SqmAttributeJoin<L, S> treatAs(Class<S> treatTarget) {
return (SqmAttributeJoin<L, S>) super.treatAs( treatTarget );
}
@Override
public <S extends R> SqmAttributeJoin<L, S> treatAs(EntityDomainType<S> treatTarget) {
return (SqmAttributeJoin<L, S>) super.treatAs( treatTarget );
}
}

View File

@ -24,17 +24,12 @@ import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.SemanticException;
import org.hibernate.query.criteria.JpaCrossJoin;
import org.hibernate.query.criteria.JpaCteCriteria;
import org.hibernate.query.criteria.JpaDerivedJoin;
import org.hibernate.query.criteria.JpaJoinedFrom;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.from.SqmCteJoin;
import org.hibernate.query.sqm.tree.from.SqmDerivedJoin;
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.SemanticException;
import org.hibernate.query.criteria.JpaEntityJoin;
import org.hibernate.query.criteria.JpaJoinedFrom;
import org.hibernate.query.criteria.JpaPath;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.hql.spi.SqmCreationState;
@ -43,18 +38,24 @@ import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.spi.SqmCreationHelper;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmCteJoin;
import org.hibernate.query.sqm.tree.from.SqmDerivedJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
import org.hibernate.spi.NavigablePath;
import jakarta.persistence.criteria.Fetch;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.CollectionAttribute;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.ListAttribute;
import jakarta.persistence.metamodel.MapAttribute;
import jakarta.persistence.metamodel.PluralAttribute;
@ -222,8 +223,8 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
// if ( lhs instanceof SqmRoot<?> ) {
// entityName = ( (SqmRoot<?>) lhs ).getEntityName();
// }
// else if ( lhs instanceof SqmEntityJoin<?> ) {
// entityName = ( (SqmEntityJoin<?>) lhs ).getEntityName();
// else if ( lhs instanceof SqmEntityJoin<?,?> ) {
// entityName = ( (SqmEntityJoin<?,?>) lhs ).getEntityName();
// }
// else {
// assert lhs instanceof SqmCrossJoin<?>;
@ -291,7 +292,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
return treats == null ? Collections.emptyList() : treats;
}
protected <S, X extends SqmFrom<?, S>> X findTreat(ManagedDomainType<S> targetType, String alias) {
protected <S, X extends SqmFrom<T, S>> X findTreat(ManagedDomainType<S> targetType, String alias) {
if ( treats != null ) {
for ( SqmFrom<?, ?> treat : treats ) {
if ( treat.getModel() == targetType ) {
@ -557,25 +558,25 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
}
@Override
public <X> JpaEntityJoin<X> join(Class<X> entityJavaType) {
public <R> JpaEntityJoin<T, R> join(Class<R> entityJavaType) {
return join( nodeBuilder().getDomainModel().entity( entityJavaType ) );
}
@Override
public <X> JpaEntityJoin<X> join(EntityDomainType<X> entity) {
return join( entity, SqmJoinType.INNER );
public <R> JpaEntityJoin<T, R> join(EntityType<R> entityType) {
return join( entityType, JoinType.INNER );
}
@Override
public <X> JpaEntityJoin<X> join(Class<X> entityJavaType, SqmJoinType joinType) {
public <Y> JpaEntityJoin<T, Y> join(Class<Y> entityJavaType, JoinType joinType) {
return join( nodeBuilder().getDomainModel().entity( entityJavaType ), joinType );
}
@Override
public <X> JpaEntityJoin<X> join(EntityDomainType<X> entity, SqmJoinType joinType) {
final SqmEntityJoin<X> join = new SqmEntityJoin<>( entity, null, joinType, findRoot() );
public <Y> JpaEntityJoin<T, Y> join(EntityType<Y> entity, JoinType joinType) {
//noinspection unchecked
addSqmJoin( (SqmJoin<T, ?>) join );
final SqmEntityJoin<T,Y> join = new SqmEntityJoin<>( entity, null, joinType, (SqmRoot<T>) findRoot() );
addSqmJoin( join );
return join;
}

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.tree.domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -289,17 +290,18 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
}
@Override
@SuppressWarnings("unchecked")
public <E, C extends java.util.Collection<E>> SqmPath<C> get(PluralAttribute<T, C, E> attribute) {
public <E, C extends Collection<E>> SqmExpression<C> get(PluralAttribute<? super T, C, E> attribute) {
//noinspection unchecked
return resolvePath( (PersistentAttribute<T, C>) attribute );
}
@Override
@SuppressWarnings("unchecked")
public <K, V, M extends Map<K, V>> SqmPath<M> get(MapAttribute<T, K, V> map) {
return resolvePath( (PersistentAttribute<T, M>) map );
public <K, V, M extends Map<K, V>> SqmExpression<M> get(MapAttribute<? super T, K, V> attribute) {
//noinspection unchecked
return resolvePath( (PersistentAttribute<T, M>) attribute );
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" + navigablePath + ")";

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.query.sqm.tree.domain;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.criteria.JpaJoinedFrom;
import org.hibernate.query.criteria.JpaPredicate;
@ -24,18 +25,18 @@ import jakarta.persistence.criteria.Predicate;
/**
* @author Steve Ebersole
*/
public abstract class AbstractSqmQualifiedJoin<O, T> extends AbstractSqmJoin<O,T> implements SqmQualifiedJoin<O, T>, JpaJoinedFrom<O, T> {
public abstract class AbstractSqmQualifiedJoin<L, R> extends AbstractSqmJoin<L,R> implements SqmQualifiedJoin<L,R>, JpaJoinedFrom<L, R> {
private SqmPredicate onClausePredicate;
public AbstractSqmQualifiedJoin(
NavigablePath navigablePath,
SqmPathSource<T> referencedNavigable,
SqmPathSource<R> referencedNavigable,
SqmFrom<?, ?> lhs, String alias, SqmJoinType joinType, NodeBuilder nodeBuilder) {
super( navigablePath, referencedNavigable, lhs, alias, joinType, nodeBuilder );
}
protected void copyTo(AbstractSqmQualifiedJoin<O, T> target, SqmCopyContext context) {
protected void copyTo(AbstractSqmQualifiedJoin<L, R> target, SqmCopyContext context) {
super.copyTo( target, context );
target.onClausePredicate = onClausePredicate == null ? null : onClausePredicate.copy( context );
}
@ -50,6 +51,8 @@ public abstract class AbstractSqmQualifiedJoin<O, T> extends AbstractSqmJoin<O,T
return onClausePredicate;
}
@Override
public void setJoinPredicate(SqmPredicate predicate) {
if ( log.isTraceEnabled() ) {
@ -73,25 +76,35 @@ public abstract class AbstractSqmQualifiedJoin<O, T> extends AbstractSqmJoin<O,T
}
@Override
public JpaJoinedFrom<O, T> on(JpaExpression<Boolean> restriction) {
public <S extends R> SqmQualifiedJoin<L, S> treatAs(Class<S> treatAsType) {
return treatAs( treatAsType, null );
}
@Override
public <S extends R> SqmQualifiedJoin<L, S> treatAs(EntityDomainType<S> treatAsType) {
return treatAs( treatAsType, null );
}
@Override
public JpaJoinedFrom<L, R> on(JpaExpression<Boolean> restriction) {
applyRestriction( nodeBuilder().wrap( restriction ) );
return this;
}
@Override
public JpaJoinedFrom<O, T> on(Expression<Boolean> restriction) {
public JpaJoinedFrom<L, R> on(Expression<Boolean> restriction) {
applyRestriction( nodeBuilder().wrap( restriction ) );
return this;
}
@Override
public JpaJoinedFrom<O, T> on(JpaPredicate... restrictions) {
public JpaJoinedFrom<L, R> on(JpaPredicate... restrictions) {
applyRestriction( nodeBuilder().wrap( restrictions ) );
return this;
}
@Override
public JpaJoinedFrom<O, T> on(Predicate... restrictions) {
public JpaJoinedFrom<L, R> on(Predicate... restrictions) {
applyRestriction( nodeBuilder().wrap( restrictions ) );
return this;
}

View File

@ -18,12 +18,12 @@ import org.hibernate.query.sqm.tree.from.SqmRoot;
/**
* @author Christian Beikov
*/
public class SqmCorrelatedEntityJoin<T> extends SqmEntityJoin<T> implements SqmCorrelation<T, T> {
public class SqmCorrelatedEntityJoin<L,R> extends SqmEntityJoin<L,R> implements SqmCorrelation<L, R> {
private final SqmCorrelatedRootJoin<T> correlatedRootJoin;
private final SqmEntityJoin<T> correlationParent;
private final SqmCorrelatedRootJoin<L> correlatedRootJoin;
private final SqmEntityJoin<L,R> correlationParent;
public SqmCorrelatedEntityJoin(SqmEntityJoin<T> correlationParent) {
public SqmCorrelatedEntityJoin(SqmEntityJoin<L,R> correlationParent) {
super(
correlationParent.getNavigablePath(),
correlationParent.getReferencedPathSource(),
@ -36,24 +36,24 @@ public class SqmCorrelatedEntityJoin<T> extends SqmEntityJoin<T> implements SqmC
}
public SqmCorrelatedEntityJoin(
EntityDomainType<T> joinedEntityDescriptor,
EntityDomainType<R> joinedEntityDescriptor,
String alias,
SqmJoinType joinType,
SqmRoot<?> sqmRoot,
SqmCorrelatedRootJoin<T> correlatedRootJoin,
SqmEntityJoin<T> correlationParent) {
SqmRoot<L> sqmRoot,
SqmCorrelatedRootJoin<L> correlatedRootJoin,
SqmEntityJoin<L,R> correlationParent) {
super( correlationParent.getNavigablePath(), joinedEntityDescriptor, alias, joinType, sqmRoot );
this.correlatedRootJoin = correlatedRootJoin;
this.correlationParent = correlationParent;
}
@Override
public SqmCorrelatedEntityJoin<T> copy(SqmCopyContext context) {
final SqmCorrelatedEntityJoin<T> existing = context.getCopy( this );
public SqmCorrelatedEntityJoin<L,R> copy(SqmCopyContext context) {
final SqmCorrelatedEntityJoin<L,R> existing = context.getCopy( this );
if ( existing != null ) {
return existing;
}
final SqmCorrelatedEntityJoin<T> path = context.registerCopy(
final SqmCorrelatedEntityJoin<L,R> path = context.registerCopy(
this,
new SqmCorrelatedEntityJoin<>(
getReferencedPathSource(),
@ -79,12 +79,12 @@ public class SqmCorrelatedEntityJoin<T> extends SqmEntityJoin<T> implements SqmC
}
@Override
public SqmEntityJoin<T> getCorrelationParent() {
public SqmEntityJoin<L,R> getCorrelationParent() {
return correlationParent;
}
@Override
public SqmPath<T> getWrappedPath() {
public SqmPath<R> getWrappedPath() {
return correlationParent;
}
@ -94,12 +94,12 @@ public class SqmCorrelatedEntityJoin<T> extends SqmEntityJoin<T> implements SqmC
}
@Override
public SqmRoot<T> getCorrelatedRoot() {
public SqmRoot<L> getCorrelatedRoot() {
return correlatedRootJoin;
}
@Override
public SqmCorrelatedEntityJoin<T> makeCopy(SqmCreationProcessingState creationProcessingState) {
public SqmCorrelatedEntityJoin<L,R> makeCopy(SqmCreationProcessingState creationProcessingState) {
final SqmPathRegistry pathRegistry = creationProcessingState.getPathRegistry();
return new SqmCorrelatedEntityJoin<>(
getReferencedPathSource(),

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.query.sqm.tree.domain;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmPathSource;
@ -14,6 +13,7 @@ import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.spi.NavigablePath;
/**
* @author Steve Ebersole
@ -91,5 +91,4 @@ public class SqmCorrelatedRootJoin<T> extends SqmRoot<T> implements SqmCorrelati
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitCorrelatedRootJoin( this );
}
}

View File

@ -8,14 +8,12 @@ package org.hibernate.query.sqm.tree.domain;
import org.hibernate.Incubating;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.PathException;
import org.hibernate.query.criteria.JpaRoot;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.spi.SqmCreationHelper;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.spi.NavigablePath;
@ -104,24 +102,4 @@ public class SqmCteRoot<T> extends SqmRoot<T> implements JpaRoot<T> {
public SqmCorrelatedRoot<T> createCorrelation() {
throw new UnsupportedOperationException();
}
@Override
public <S extends T> SqmTreatedRoot<T, S> treatAs(Class<S> treatJavaType) throws PathException {
throw new UnsupportedOperationException( "CTE roots can not be treated" );
}
@Override
public <S extends T> SqmTreatedRoot<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
throw new UnsupportedOperationException( "CTE roots can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias) {
throw new UnsupportedOperationException( "CTE roots can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "CTE roots can not be treated" );
}
}

View File

@ -108,22 +108,22 @@ public class SqmDerivedRoot<T> extends SqmRoot<T> implements JpaDerivedRoot<T> {
}
@Override
public <S extends T> SqmTreatedRoot<T, S> treatAs(Class<S> treatJavaType) throws PathException {
public <S extends T> SqmFrom<T, S> treatAs(Class<S> treatJavaType) throws PathException {
throw new UnsupportedOperationException( "Derived roots can not be treated" );
}
@Override
public <S extends T> SqmTreatedRoot<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
public <S extends T> SqmFrom<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
throw new UnsupportedOperationException( "Derived roots can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias) {
public <S extends T> SqmFrom<T, S> treatAs(Class<S> treatJavaType, String alias) {
throw new UnsupportedOperationException( "Derived roots can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
public <S extends T> SqmFrom<T, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "Derived roots can not be treated" );
}
}

View File

@ -156,6 +156,26 @@ public class SqmMapEntryReference<K,V>
throw new UnsupportedOperationException( "Whatever JPA" );
}
@Override
public Predicate equalTo(Expression<?> value) {
throw new UnsupportedOperationException( "Whatever JPA" );
}
@Override
public Predicate equalTo(Object value) {
throw new UnsupportedOperationException( "Whatever JPA" );
}
@Override
public Predicate notEqualTo(Expression<?> value) {
throw new UnsupportedOperationException( "Whatever JPA" );
}
@Override
public Predicate notEqualTo(Object value) {
throw new UnsupportedOperationException( "Whatever JPA" );
}
@Override
public Predicate in(Object... values) {
throw new UnsupportedOperationException( "Whatever JPA" );
@ -180,4 +200,9 @@ public class SqmMapEntryReference<K,V>
public <X> Expression<X> as(Class<X> type) {
throw new UnsupportedOperationException( "Whatever JPA" );
}
@Override
public <X> Expression<X> cast(Class<X> type) {
throw new UnsupportedOperationException( "Whatever JPA" );
}
}

View File

@ -11,6 +11,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.metamodel.MapAttribute;
import jakarta.persistence.metamodel.PluralAttribute;
import jakarta.persistence.metamodel.SingularAttribute;
@ -18,6 +19,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.criteria.JpaPath;
import org.hibernate.query.hql.spi.SemanticPathPart;
@ -154,10 +156,10 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
<Y> SqmPath<Y> get(SingularAttribute<? super T, Y> attribute);
@Override
<E, C extends Collection<E>> SqmExpression<C> get(PluralAttribute<T, C, E> collection);
<E, C extends Collection<E>> SqmExpression<C> get(PluralAttribute<? super T, C, E> collection);
@Override
<K, V, M extends Map<K, V>> SqmExpression<M> get(MapAttribute<T, K, V> map);
<K, V, M extends Map<K, V>> SqmExpression<M> get(MapAttribute<? super T, K, V> map);
@Override
SqmExpression<Class<? extends T>> type();
@ -167,4 +169,6 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
@Override
SqmPath<T> copy(SqmCopyContext context);
}

View File

@ -17,11 +17,13 @@ import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmJoinable;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.spi.NavigablePath;
/**
* @author Steve Ebersole

View File

@ -99,6 +99,7 @@ public class SqmTreatedCrossJoin<T, S extends T> extends SqmCrossJoin<S> impleme
return treatTarget;
}
@Override
public void appendHqlString(StringBuilder sb) {
sb.append( "treat(" );

View File

@ -15,12 +15,12 @@ import org.hibernate.spi.NavigablePath;
/**
* @author Steve Ebersole
*/
public class SqmTreatedEntityJoin<T, S extends T> extends SqmEntityJoin<S> implements SqmTreatedPath<T,S> {
private final SqmEntityJoin<T> wrappedPath;
public class SqmTreatedEntityJoin<L,R,S extends R> extends SqmEntityJoin<L,S> implements SqmTreatedPath<R,S> {
private final SqmEntityJoin<L,R> wrappedPath;
private final EntityDomainType<S> treatTarget;
public SqmTreatedEntityJoin(
SqmEntityJoin<T> wrappedPath,
SqmEntityJoin<L,R> wrappedPath,
EntityDomainType<S> treatTarget,
String alias) {
super(
@ -39,7 +39,7 @@ public class SqmTreatedEntityJoin<T, S extends T> extends SqmEntityJoin<S> imple
private SqmTreatedEntityJoin(
NavigablePath navigablePath,
SqmEntityJoin<T> wrappedPath,
SqmEntityJoin<L,R> wrappedPath,
EntityDomainType<S> treatTarget,
String alias) {
super(
@ -54,12 +54,12 @@ public class SqmTreatedEntityJoin<T, S extends T> extends SqmEntityJoin<S> imple
}
@Override
public SqmTreatedEntityJoin<T, S> copy(SqmCopyContext context) {
final SqmTreatedEntityJoin<T, S> existing = context.getCopy( this );
public SqmTreatedEntityJoin<L,R,S> copy(SqmCopyContext context) {
final SqmTreatedEntityJoin<L,R,S> existing = context.getCopy( this );
if ( existing != null ) {
return existing;
}
final SqmTreatedEntityJoin<T, S> path = context.registerCopy(
final SqmTreatedEntityJoin<L,R,S> path = context.registerCopy(
this,
new SqmTreatedEntityJoin<>(
getNavigablePath(),
@ -83,7 +83,7 @@ public class SqmTreatedEntityJoin<T, S extends T> extends SqmEntityJoin<S> imple
}
@Override
public SqmPath<T> getWrappedPath() {
public SqmPath<R> getWrappedPath() {
return wrappedPath;
}

View File

@ -20,6 +20,7 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;
import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType2;
@ -112,13 +113,28 @@ public abstract class AbstractSqmExpression<T> extends AbstractJpaSelection<T> i
}
@Override
public SqmPredicate equalTo(Expression<T> that) {
return nodeBuilder().equal( this, that );
public SqmPredicate equalTo(Expression<?> value) {
return nodeBuilder().equal( this, value );
}
@Override
public SqmPredicate equalTo(T that) {
return nodeBuilder().equal( this, that );
public SqmPredicate equalTo(Object value) {
return nodeBuilder().equal( this, value );
}
@Override
public Predicate notEqualTo(Expression<?> value) {
return nodeBuilder().notEqual( this, value );
}
@Override
public Predicate notEqualTo(Object value) {
return nodeBuilder().notEqual( this, value );
}
@Override
public <X> Expression<X> cast(Class<X> castTarget) {
return nodeBuilder().cast( this, castTarget );
}
@Override

View File

@ -11,6 +11,7 @@ import java.math.BigInteger;
import java.util.Collection;
import java.util.function.Consumer;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.Internal;
@ -90,10 +91,10 @@ public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T>
SqmPredicate isNotNull();
@Override
SqmPredicate equalTo(Expression<T> that);
SqmPredicate equalTo(Expression<?> value);
@Override
SqmPredicate equalTo(T that);
SqmPredicate equalTo(Object value);
@Override
SqmPredicate in(Object... values);

View File

@ -29,6 +29,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@ -154,15 +155,30 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressible<T>,
}
@Override
public SqmPredicate equalTo(Expression<T> that) {
public SqmPredicate equalTo(Expression<?> that) {
return nodeBuilder().equal( this, that );
}
@Override
public SqmPredicate equalTo(T that) {
public SqmPredicate equalTo(Object that) {
return nodeBuilder().equal( this, that );
}
@Override
public Predicate notEqualTo(Expression<?> that) {
return nodeBuilder().notEqual( this, that );
}
@Override
public Predicate notEqualTo(Object that) {
return nodeBuilder().notEqual( this, that );
}
@Override
public <X> Expression<X> cast(Class<X> type) {
return null;
}
@Override
public SqmPredicate isNotNull() {
return nodeBuilder().isNotNull( this );

View File

@ -11,6 +11,7 @@ import org.hibernate.Remove;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.criteria.JpaFetch;
import org.hibernate.query.criteria.JpaJoin;
import org.hibernate.query.criteria.JpaJoinedFrom;
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
@ -21,7 +22,7 @@ import org.hibernate.type.descriptor.java.JavaType;
*
* @author Steve Ebersole
*/
public interface SqmAttributeJoin<O,T> extends SqmQualifiedJoin<O,T>, JpaFetch<O,T>, JpaJoin<O,T> {
public interface SqmAttributeJoin<O,T> extends SqmQualifiedJoin<O,T>, JpaFetch<O,T>, JpaJoinedFrom<O,T>, JpaJoin<O,T> {
@Override
SqmFrom<?,O> getLhs();
@ -49,18 +50,14 @@ public interface SqmAttributeJoin<O,T> extends SqmQualifiedJoin<O,T>, JpaFetch<O
@Override
<S extends T> SqmAttributeJoin<O, S> treatAs(Class<S> treatJavaType);
@Override
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatTarget);
@Override
<S extends T> SqmAttributeJoin<O, S> treatAs(Class<S> treatJavaType, String alias);
@Override
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatJavaType, String alias);
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatTarget);
<S extends T> SqmAttributeJoin<O, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch);
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatJavaType, String alias, boolean fetch);
@Override
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatTarget, String alias);
/*
@deprecated not used anymore

View File

@ -8,8 +8,6 @@ package org.hibernate.query.sqm.tree.from;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.criteria.JpaCrossJoin;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.PathException;
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.SemanticQueryWalker;
@ -19,6 +17,7 @@ import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom;
import org.hibernate.query.sqm.tree.domain.SqmCorrelatedCrossJoin;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedCrossJoin;
import org.hibernate.spi.NavigablePath;
import static org.hibernate.query.sqm.spi.SqmCreationHelper.buildRootNavigablePath;
@ -118,30 +117,33 @@ public class SqmCrossJoin<T> extends AbstractSqmFrom<T, T> implements JpaCrossJo
return new SqmCorrelatedCrossJoin<>( this );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA
@Override
public <S extends T> SqmTreatedCrossJoin<T,S> treatAs(Class<S> treatJavaType) throws PathException {
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
public <S extends T> SqmJoin<T, S> treatAs(Class<S> treatTarget) {
return treatAs( nodeBuilder().getDomainModel().entity( treatTarget ) );
}
@Override
public <S extends T> SqmTreatedCrossJoin<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
final SqmTreatedCrossJoin<T, S> treat = findTreat( treatTarget, null );
public <S extends T> SqmJoin<T, S> treatAs(EntityDomainType<S> treatTarget) {
final SqmJoin<T, S> treat = findTreat( treatTarget, null );
if ( treat == null ) {
return addTreat( new SqmTreatedCrossJoin<>( this, treatTarget, null ) );
//noinspection unchecked
return addTreat( (SqmJoin<T, S>) new SqmTreatedCrossJoin<>( this, treatTarget, null ) );
}
return treat;
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias) {
public <S extends T> SqmJoin<T, S> treatAs(Class<S> treatJavaType, String alias) {
throw new UnsupportedOperationException( "Cross join treats can not be aliased" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
public <S extends T> SqmJoin<T, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "Cross join treats can not be aliased" );
}

View File

@ -8,7 +8,7 @@ package org.hibernate.query.sqm.tree.from;
import org.hibernate.Incubating;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.PathException;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.query.criteria.JpaJoinedFrom;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmPathSource;
@ -21,6 +21,9 @@ import org.hibernate.query.sqm.tree.domain.SqmCorrelatedEntityJoin;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.spi.NavigablePath;
import jakarta.persistence.criteria.From;
import jakarta.persistence.criteria.JoinType;
/**
* @author Christian Beikov
*/
@ -115,27 +118,32 @@ public class SqmCteJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements Jpa
// JPA
@Override
public SqmCorrelatedEntityJoin<T> createCorrelation() {
public SqmCorrelatedEntityJoin<T,T> createCorrelation() {
throw new UnsupportedOperationException();
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType) throws PathException {
throw new UnsupportedOperationException( "CTE joins can not be treated" );
public PersistentAttribute<? super T, ?> getAttribute() {
return null;
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
public <S extends T> SqmQualifiedJoin<T, S> treatAs(Class<S> treatJavaType, String alias) {
throw new UnsupportedOperationException( "CTE joins can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias) {
public <S extends T> SqmQualifiedJoin<T, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "CTE joins can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "CTE joins can not be treated" );
public From<?, T> getParent() {
return getCorrelationParent();
}
@Override
public JoinType getJoinType() {
return getSqmJoinType().getCorrespondingJpaJoinType();
}
}

View File

@ -8,7 +8,7 @@ package org.hibernate.query.sqm.tree.from;
import org.hibernate.Incubating;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.PathException;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.query.criteria.JpaDerivedJoin;
import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.criteria.JpaPredicate;
@ -25,6 +25,8 @@ import org.hibernate.query.sqm.tree.select.SqmSubQuery;
import org.hibernate.spi.NavigablePath;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.From;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Predicate;
/**
@ -166,27 +168,44 @@ public class SqmDerivedJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements
// JPA
@Override
public SqmCorrelatedEntityJoin<T> createCorrelation() {
public SqmCorrelatedEntityJoin<T,T> createCorrelation() {
throw new UnsupportedOperationException();
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType) throws PathException {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
public <S extends T> SqmCorrelatedEntityJoin<T, S> treatAs(Class<S> treatAsType) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias) {
public <S extends T> SqmCorrelatedEntityJoin<T, S> treatAs(EntityDomainType<S> treatAsType) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
public <S extends T> SqmCorrelatedEntityJoin<T, S> treatAs(Class<S> treatJavaType, String alias) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Override
public <S extends T> SqmCorrelatedEntityJoin<T, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Override
public PersistentAttribute<? super T, ?> getAttribute() {
// none
return null;
}
@Override
public From<?, T> getParent() {
//noinspection unchecked
return (From<?, T>) getRoot();
}
@Override
public JoinType getJoinType() {
return getSqmJoinType().getCorrespondingJpaJoinType();
}
}

View File

@ -7,12 +7,10 @@
package org.hibernate.query.sqm.tree.from;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.query.criteria.JpaEntityJoin;
import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.criteria.JpaPredicate;
import org.hibernate.query.sqm.tree.domain.AbstractSqmQualifiedJoin;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.PathException;
import org.hibernate.query.criteria.JpaEntityJoin;
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.hql.spi.SqmPathRegistry;
@ -20,25 +18,30 @@ import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.spi.SqmCreationHelper;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.domain.AbstractSqmQualifiedJoin;
import org.hibernate.query.sqm.tree.domain.SqmCorrelatedEntityJoin;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedEntityJoin;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.spi.NavigablePath;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.From;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.metamodel.EntityType;
/**
* @author Steve Ebersole
*/
public class SqmEntityJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements JpaEntityJoin<T> {
private final SqmRoot<?> sqmRoot;
public class SqmEntityJoin<L,R> extends AbstractSqmQualifiedJoin<L,R> implements JpaEntityJoin<L,R> {
private final SqmRoot<L> sqmRoot;
public SqmEntityJoin(
EntityDomainType<T> joinedEntityDescriptor,
EntityDomainType<R> joinedEntityDescriptor,
String alias,
SqmJoinType joinType,
SqmRoot<?> sqmRoot) {
SqmRoot<L> sqmRoot) {
this(
SqmCreationHelper.buildRootNavigablePath( joinedEntityDescriptor.getHibernateEntityName(), alias ),
joinedEntityDescriptor,
@ -50,26 +53,34 @@ public class SqmEntityJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements
protected SqmEntityJoin(
NavigablePath navigablePath,
EntityDomainType<T> joinedEntityDescriptor,
EntityDomainType<R> joinedEntityDescriptor,
String alias,
SqmJoinType joinType,
SqmRoot<?> sqmRoot) {
SqmRoot<L> sqmRoot) {
super( navigablePath, joinedEntityDescriptor, sqmRoot, alias, joinType, sqmRoot.nodeBuilder() );
this.sqmRoot = sqmRoot;
}
public SqmEntityJoin(
EntityType<R> entity,
String alias,
JoinType joinType,
SqmRoot<L> root) {
this( (EntityDomainType<R>) entity, alias, SqmJoinType.from( joinType ), root );
}
@Override
public boolean isImplicitlySelectable() {
return true;
}
@Override
public SqmEntityJoin<T> copy(SqmCopyContext context) {
final SqmEntityJoin<T> existing = context.getCopy( this );
public SqmEntityJoin<L,R> copy(SqmCopyContext context) {
final SqmEntityJoin<L,R> existing = context.getCopy( this );
if ( existing != null ) {
return existing;
}
final SqmEntityJoin<T> path = context.registerCopy(
final SqmEntityJoin<L,R> path = context.registerCopy(
this,
new SqmEntityJoin<>(
getNavigablePath(),
@ -83,15 +94,25 @@ public class SqmEntityJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements
return path;
}
public SqmRoot<?> getRoot() {
public SqmRoot<L> getRoot() {
return sqmRoot;
}
@Override
public From<?, L> getParent() {
return getRoot();
}
@Override
public SqmRoot<?> findRoot() {
return getRoot();
}
@Override
public JoinType getJoinType() {
return getSqmJoinType().getCorrespondingJpaJoinType();
}
@Override
public SqmPath<?> resolveIndexedAccess(
SqmExpression<?> selector,
@ -101,8 +122,8 @@ public class SqmEntityJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements
}
@Override
public EntityDomainType<T> getModel() {
return (EntityDomainType<T>) super.getModel();
public EntityDomainType<R> getModel() {
return (EntityDomainType<R>) super.getModel();
}
@Override
@ -112,8 +133,8 @@ public class SqmEntityJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements
}
@Override
public EntityDomainType<T> getReferencedPathSource() {
return (EntityDomainType<T>) super.getReferencedPathSource();
public EntityDomainType<R> getReferencedPathSource() {
return (EntityDomainType<R>) super.getReferencedPathSource();
}
public String getEntityName() {
@ -121,23 +142,23 @@ public class SqmEntityJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements
}
@Override
public SqmEntityJoin<T> on(JpaExpression<Boolean> restriction) {
return (SqmEntityJoin<T>) super.on( restriction );
public SqmEntityJoin<L,R> on(JpaExpression<Boolean> restriction) {
return (SqmEntityJoin<L,R>) super.on( restriction );
}
@Override
public SqmEntityJoin<T> on(Expression<Boolean> restriction) {
return (SqmEntityJoin<T>) super.on( restriction );
public SqmEntityJoin<L,R> on(Expression<Boolean> restriction) {
return (SqmEntityJoin<L,R>) super.on( restriction );
}
@Override
public SqmEntityJoin<T> on(JpaPredicate... restrictions) {
return (SqmEntityJoin<T>) super.on( restrictions );
public SqmEntityJoin<L,R> on(JpaPredicate... restrictions) {
return (SqmEntityJoin<L,R>) super.on( restrictions );
}
@Override
public SqmEntityJoin<T> on(Predicate... restrictions) {
return (SqmEntityJoin<T>) super.on( restrictions );
public SqmEntityJoin<L,R> on(Predicate... restrictions) {
return (SqmEntityJoin<L,R>) super.on( restrictions );
}
@Override
@ -150,34 +171,54 @@ public class SqmEntityJoin<T> extends AbstractSqmQualifiedJoin<T, T> implements
// JPA
@Override
public <S extends T> SqmTreatedEntityJoin<T,S> treatAs(Class<S> treatJavaType) throws PathException {
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
public <S extends R> SqmTreatedEntityJoin<L,R,S> treatAs(Class<S> treatAsType) {
return treatAs( nodeBuilder().getDomainModel().entity( treatAsType ) );
}
@Override
public <S extends T> SqmTreatedEntityJoin<T,S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
final SqmTreatedEntityJoin<T,S> treat = findTreat( treatTarget, null );
public <S extends R> SqmTreatedEntityJoin<L,R,S> treatAs(EntityDomainType<S> treatAsType) {
final SqmTreatedEntityJoin<L,R,S> treat = findTreat( treatAsType, null );
if ( treat == null ) {
return addTreat( new SqmTreatedEntityJoin<>( this, treatTarget, null ) );
return addTreat( new SqmTreatedEntityJoin<>( this, treatAsType, null ) );
}
return treat;
}
// @Override
// public <S extends T> SqmTreatedEntityJoin<T,S> treatAs(Class<S> treatJavaType) throws PathException {
// return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
// }
// @Override
// public <S extends T> SqmTreatedEntityJoin<T,S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
// final SqmTreatedEntityJoin<T,S> treat = findTreat( treatTarget, null );
// if ( treat == null ) {
// return addTreat( new SqmTreatedEntityJoin<>( this, treatTarget, null ) );
// }
// return treat;
// }
@Override
public <S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias) {
public <S extends R> SqmEntityJoin<L,S> treatAs(Class<S> treatJavaType, String alias) {
throw new UnsupportedOperationException( "Entity join treats can not be aliased" );
}
@Override
public <S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
public <S extends R> SqmEntityJoin<L,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "Entity join treats can not be aliased" );
}
@Override
public SqmCorrelatedEntityJoin<T> createCorrelation() {
public PersistentAttribute<? super L, ?> getAttribute() {
// there is no attribute
return null;
}
@Override
public SqmCorrelatedEntityJoin<L,R> createCorrelation() {
return new SqmCorrelatedEntityJoin<>( this );
}
public SqmEntityJoin<T> makeCopy(SqmCreationProcessingState creationProcessingState) {
public SqmEntityJoin<L,R> makeCopy(SqmCreationProcessingState creationProcessingState) {
final SqmPathRegistry pathRegistry = creationProcessingState.getPathRegistry();
return new SqmEntityJoin<>(
getReferencedPathSource(),

View File

@ -31,11 +31,14 @@ import org.hibernate.query.sqm.tree.domain.SqmSingularJoin;
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
/**
* Models a Bindable's inclusion in the {@code FROM} clause.
* Models a SqmPathSource's inclusion in the {@code FROM} clause.
*
* @param <L> The from-element's "left hand side". It may be the same as {@code R} for roots.
* @param <R> The from-element's "right hand side". For joins, this is the target side.
*
* @author Steve Ebersole
*/
public interface SqmFrom<O,T> extends SqmVisitableNode, SqmPath<T>, JpaFrom<O, T> {
public interface SqmFrom<L, R> extends SqmVisitableNode, SqmPath<R>, JpaFrom<L, R> {
/**
* The Navigable for an SqmFrom will always be a NavigableContainer
*
@ -43,24 +46,24 @@ public interface SqmFrom<O,T> extends SqmVisitableNode, SqmPath<T>, JpaFrom<O, T
* @return
*/
@Override
SqmPathSource<T> getReferencedPathSource();
SqmPathSource<R> getReferencedPathSource();
boolean hasJoins();
/**
* The joins associated with this SqmFrom
*/
List<SqmJoin<T,?>> getSqmJoins();
List<SqmJoin<R,?>> getSqmJoins();
/**
* Add an associated join
*/
void addSqmJoin(SqmJoin<T, ?> join);
void addSqmJoin(SqmJoin<R, ?> join);
/**
* Visit all associated joins
*/
void visitSqmJoins(Consumer<SqmJoin<T, ?>> consumer);
void visitSqmJoins(Consumer<SqmJoin<R, ?>> consumer);
/**
* The treats associated with this SqmFrom
@ -72,50 +75,50 @@ public interface SqmFrom<O,T> extends SqmVisitableNode, SqmPath<T>, JpaFrom<O, T
}
@Override
<S extends T> SqmFrom<?, S> treatAs(Class<S> treatAsType);
<S extends R> SqmFrom<L, S> treatAs(Class<S> treatAsType);
@Override
<S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatAsType);
<S extends R> SqmFrom<L, S> treatAs(EntityDomainType<S> treatAsType);
<S extends T> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias);
<S extends R> SqmFrom<L, S> treatAs(Class<S> treatJavaType, String alias);
<S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias);
<S extends R> SqmFrom<L, S> treatAs(EntityDomainType<S> treatTarget, String alias);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA
@Override
SqmFrom<O, T> getCorrelationParent();
SqmFrom<L, R> getCorrelationParent();
@Override
<A> SqmSingularJoin<T, A> join(SingularAttribute<? super T, A> attribute);
<A> SqmSingularJoin<R, A> join(SingularAttribute<? super R, A> attribute);
@Override
<A> SqmSingularJoin<T, A> join(SingularAttribute<? super T, A> attribute, JoinType jt);
<A> SqmSingularJoin<R, A> join(SingularAttribute<? super R, A> attribute, JoinType jt);
@Override
<E> SqmBagJoin<T, E> join(CollectionAttribute<? super T, E> attribute);
<E> SqmBagJoin<R, E> join(CollectionAttribute<? super R, E> attribute);
@Override
<E> SqmBagJoin<T, E> join(CollectionAttribute<? super T, E> attribute, JoinType jt);
<E> SqmBagJoin<R, E> join(CollectionAttribute<? super R, E> attribute, JoinType jt);
@Override
<E> SqmSetJoin<T, E> join(SetAttribute<? super T, E> set);
<E> SqmSetJoin<R, E> join(SetAttribute<? super R, E> set);
@Override
<E> SqmSetJoin<T, E> join(SetAttribute<? super T, E> set, JoinType jt);
<E> SqmSetJoin<R, E> join(SetAttribute<? super R, E> set, JoinType jt);
@Override
<E> SqmListJoin<T, E> join(ListAttribute<? super T, E> list);
<E> SqmListJoin<R, E> join(ListAttribute<? super R, E> list);
@Override
<E> SqmListJoin<T, E> join(ListAttribute<? super T, E> list, JoinType jt);
<E> SqmListJoin<R, E> join(ListAttribute<? super R, E> list, JoinType jt);
@Override
<K, V> SqmMapJoin<T, K, V> join(MapAttribute<? super T, K, V> map);
<K, V> SqmMapJoin<R, K, V> join(MapAttribute<? super R, K, V> map);
@Override
<K, V> SqmMapJoin<T, K, V> join(MapAttribute<? super T, K, V> map, JoinType jt);
<K, V> SqmMapJoin<R, K, V> join(MapAttribute<? super R, K, V> map, JoinType jt);
@Override
<X, Y> SqmAttributeJoin<X, Y> join(String attributeName);
@ -148,5 +151,5 @@ public interface SqmFrom<O,T> extends SqmVisitableNode, SqmPath<T>, JpaFrom<O, T
<X, K, V> SqmMapJoin<X, K, V> joinMap(String attributeName, JoinType jt);
@Override
SqmFrom<O, T> copy(SqmCopyContext context);
SqmFrom<L, R> copy(SqmCopyContext context);
}

View File

@ -8,13 +8,14 @@ package org.hibernate.query.sqm.tree.from;
import jakarta.persistence.criteria.JoinType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmJoinType;
/**
* @author Steve Ebersole
*/
public interface SqmJoin<O,T> extends SqmFrom<O,T> {
public interface SqmJoin<L, R> extends SqmFrom<L, R> {
/**
* The type of join - inner, cross, etc
*/
@ -32,5 +33,17 @@ public interface SqmJoin<O,T> extends SqmFrom<O,T> {
<X, Y> SqmAttributeJoin<X, Y> join(String attributeName, JoinType jt);
@Override
SqmJoin<O, T> copy(SqmCopyContext context);
SqmJoin<L, R> copy(SqmCopyContext context);
@Override
<S extends R> SqmJoin<L, S> treatAs(Class<S> treatAsType);
@Override
<S extends R> SqmJoin<L, S> treatAs(EntityDomainType<S> treatAsType);
@Override
<S extends R> SqmJoin<L, S> treatAs(Class<S> treatJavaType, String alias);
@Override
<S extends R> SqmJoin<L, S> treatAs(EntityDomainType<S> treatTarget, String alias);
}

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.query.sqm.tree.from;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.criteria.JpaJoinedFrom;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
/**
@ -13,7 +15,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
*
* @author Steve Ebersole
*/
public interface SqmQualifiedJoin<O,T> extends SqmJoin<O,T> {
public interface SqmQualifiedJoin<L, R> extends SqmJoin<L,R>, JpaJoinedFrom<L,R> {
/**
* Obtain the join predicate
*
@ -27,4 +29,16 @@ public interface SqmQualifiedJoin<O,T> extends SqmJoin<O,T> {
* @param predicate The join predicate
*/
void setJoinPredicate(SqmPredicate predicate);
@Override
<S extends R> SqmQualifiedJoin<L, S> treatAs(Class<S> treatAsType);
@Override
<S extends R> SqmQualifiedJoin<L, S> treatAs(EntityDomainType<S> treatAsType);
@Override
<S extends R> SqmQualifiedJoin<L, S> treatAs(Class<S> treatJavaType, String alias);
@Override
<S extends R> SqmQualifiedJoin<L, S> treatAs(EntityDomainType<S> treatTarget, String alias);
}

View File

@ -191,26 +191,27 @@ public class SqmRoot<E> extends AbstractSqmFrom<E,E> implements JpaRoot<E> {
}
@Override
public <S extends E> SqmTreatedRoot<E, S> treatAs(Class<S> treatJavaType) throws PathException {
public <S extends E> SqmFrom<E, S> treatAs(Class<S> treatJavaType) throws PathException {
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
}
@Override
public <S extends E> SqmTreatedRoot<E, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
final SqmTreatedRoot<E, S> treat = findTreat( treatTarget, null );
public <S extends E> SqmFrom<E, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
final SqmFrom<E, S> treat = findTreat( treatTarget, null );
if ( treat == null ) {
return addTreat( new SqmTreatedRoot<>( this, treatTarget ) );
//noinspection rawtypes,unchecked
return addTreat( new SqmTreatedRoot( this, treatTarget ) );
}
return treat;
}
@Override
public <S extends E> SqmFrom<?, S> treatAs(Class<S> treatJavaType, String alias) {
public <S extends E> SqmFrom<E, S> treatAs(Class<S> treatJavaType, String alias) {
throw new UnsupportedOperationException( "Root treats can not be aliased" );
}
@Override
public <S extends E> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
public <S extends E> SqmFrom<E, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
throw new UnsupportedOperationException( "Root treats can not be aliased" );
}

View File

@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.insert;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.hibernate.Incubating;
import org.hibernate.query.criteria.JpaConflictClause;
@ -21,6 +22,7 @@ import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
@ -32,6 +34,10 @@ import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Path;
import org.checkerframework.checker.nullness.qual.Nullable;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.EntityType;
/**
* @author Steve Ebersole
*/
@ -124,12 +130,30 @@ public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> i
return walker.visitInsertSelectStatement( this );
}
@Override
public <U> Subquery<U> subquery(EntityType<U> type) {
throw new UnsupportedOperationException( "INSERT cannot be basis for subquery" );
}
@Override
public JpaPredicate getRestriction() {
// insert has no predicate
return null;
}
@Override
public Set<ParameterExpression<?>> getParameters() {
// At this level, the number of parameters may still be growing as
// nodes are added to the Criteria - so we re-calculate this every
// time.
//
// for a "finalized" set of parameters, use `#resolveParameters` instead
assert getQuerySource() == SqmQuerySource.CRITERIA;
return getSqmParameters().stream()
.filter( parameterExpression -> !( parameterExpression instanceof ValueBindJpaCriteriaParameter ) )
.collect( Collectors.toSet() );
}
@Override
public SqmInsertSelectStatement<T> setInsertionTargetPaths(Path<?>... insertionTargetPaths) {
super.setInsertionTargetPaths( insertionTargetPaths );

View File

@ -12,6 +12,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.hibernate.query.criteria.JpaConflictClause;
import org.hibernate.query.criteria.JpaCriteriaInsertValues;
@ -25,8 +26,13 @@ import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.criteria.Path;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -132,11 +138,29 @@ public class SqmInsertValuesStatement<T> extends AbstractSqmInsertStatement<T> i
return walker.visitInsertValuesStatement( this );
}
@Override
public <U> Subquery<U> subquery(EntityType<U> type) {
throw new UnsupportedOperationException( "INSERT query cannot be sub-query" );
}
@Override
public JpaPredicate getRestriction() {
return null;
}
@Override
public Set<ParameterExpression<?>> getParameters() {
// At this level, the number of parameters may still be growing as
// nodes are added to the Criteria - so we re-calculate this every
// time.
//
// for a "finalized" set of parameters, use `#resolveParameters` instead
assert getQuerySource() == SqmQuerySource.CRITERIA;
return getSqmParameters().stream()
.filter( parameterExpression -> !( parameterExpression instanceof ValueBindJpaCriteriaParameter ) )
.collect( Collectors.toSet() );
}
@Override
public SqmInsertValuesStatement<T> setInsertionTargetPaths(Path<?>... insertionTargetPaths) {
super.setInsertionTargetPaths( insertionTargetPaths );

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import jakarta.persistence.criteria.Expression;
@ -22,6 +23,15 @@ public class SqmJunctionPredicate extends AbstractSqmPredicate {
private final BooleanOperator booleanOperator;
private final List<SqmPredicate> predicates;
public SqmJunctionPredicate(
BooleanOperator booleanOperator,
SqmExpressible<Boolean> expressible,
NodeBuilder nodeBuilder) {
super( expressible, nodeBuilder );
this.booleanOperator = booleanOperator;
this.predicates = new ArrayList<>();
}
public SqmJunctionPredicate(
BooleanOperator booleanOperator,
SqmPredicate leftHandPredicate,

View File

@ -13,17 +13,10 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Selection;
import org.hibernate.query.sqm.FetchClauseType;
import org.hibernate.query.criteria.JpaCriteriaQuery;
import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.sqm.FetchClauseType;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmQuerySource;
@ -34,8 +27,19 @@ import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Selection;
import jakarta.persistence.metamodel.EntityType;
import static org.hibernate.query.sqm.spi.SqmCreationHelper.combinePredicates;
import static org.hibernate.query.sqm.SqmQuerySource.CRITERIA;
import static org.hibernate.query.sqm.tree.SqmCopyContext.noParamCopyContext;
import static org.hibernate.query.sqm.tree.jpa.ParameterCollector.collectParameters;
@ -269,6 +273,26 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
.collect( Collectors.toSet() );
}
@Override
public <U> SqmSubQuery<U> subquery(EntityType<U> type) {
return new SqmSubQuery<>( this, type, nodeBuilder() );
}
@Override
public CriteriaQuery<T> where(List<Predicate> restrictions) {
//noinspection rawtypes,unchecked
getQuerySpec().getWhereClause().applyPredicates( (List) restrictions );
return this;
}
@Override
public CriteriaQuery<T> having(List<Predicate> restrictions) {
//noinspection unchecked,rawtypes
final SqmPredicate combined = combinePredicates( getQuerySpec().getHavingClausePredicate(), (List) restrictions );
getQuerySpec().setHavingClausePredicate( combined );
return this;
}
@Override
@SuppressWarnings("unchecked")
public SqmSelectStatement<T> select(Selection<? extends T> selection) {

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.query.sqm.tree.select;
import java.util.Objects;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortDirection;
import org.hibernate.query.criteria.JpaExpression;
@ -13,19 +15,20 @@ import org.hibernate.query.criteria.JpaOrder;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import java.util.Objects;
import jakarta.persistence.criteria.Nulls;
/**
* @author Steve Ebersole
*/
public class SqmSortSpecification implements JpaOrder {
@SuppressWarnings("rawtypes")
private final SqmExpression sortExpression;
private final SortDirection sortOrder;
private final boolean ignoreCase;
private NullPrecedence nullPrecedence;
public SqmSortSpecification(
SqmExpression sortExpression,
@SuppressWarnings("rawtypes") SqmExpression sortExpression,
SortDirection sortOrder,
NullPrecedence nullPrecedence) {
this( sortExpression, sortOrder, nullPrecedence, false );
@ -45,10 +48,12 @@ public class SqmSortSpecification implements JpaOrder {
this.ignoreCase = ignoreCase;
}
@SuppressWarnings("rawtypes")
public SqmSortSpecification(SqmExpression sortExpression) {
this( sortExpression, SortDirection.ASCENDING, NullPrecedence.NONE );
}
@SuppressWarnings("rawtypes")
public SqmSortSpecification(SqmExpression sortExpression, SortDirection sortOrder) {
this( sortExpression, sortOrder, NullPrecedence.NONE );
}
@ -75,14 +80,14 @@ public class SqmSortSpecification implements JpaOrder {
// JPA
@Override
public JpaOrder nullPrecedence(NullPrecedence nullPrecedence) {
this.nullPrecedence = nullPrecedence;
public JpaOrder nullPrecedence(Nulls nullPrecedence) {
this.nullPrecedence = NullPrecedence.fromJpaValue( nullPrecedence );
return this;
}
@Override
public NullPrecedence getNullPrecedence() {
return nullPrecedence;
public Nulls getNullPrecedence() {
return nullPrecedence.getJpaValue();
}
@Override

View File

@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.select;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -64,12 +65,17 @@ import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.MapJoin;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.PluralJoin;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Selection;
import jakarta.persistence.criteria.SetJoin;
import org.checkerframework.checker.nullness.qual.Nullable;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.EntityType;
import static org.hibernate.query.sqm.spi.SqmCreationHelper.combinePredicates;
/**
* @author Steve Ebersole
@ -111,6 +117,15 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
applyInferableType( resultType );
}
public SqmSubQuery(
SqmQuery<?> parent,
EntityType<T> resultType,
NodeBuilder builder) {
super( resultType.getJavaType(), builder );
this.parent = parent;
applyInferableType( resultType.getJavaType() );
}
public SqmSubQuery(
SqmQuery<?> parent,
NodeBuilder builder) {
@ -518,9 +533,8 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
}
@Override
public <X> SqmEntityJoin<X> correlate(JpaEntityJoin<X> parentEntityJoin) {
final SqmCorrelatedEntityJoin<X> correlated =
((SqmEntityJoin<X>) parentEntityJoin).createCorrelation();
public <X> JpaEntityJoin<T, X> correlate(JpaEntityJoin<T, X> parentEntityJoin) {
final SqmCorrelatedEntityJoin<T,X> correlated = ((SqmEntityJoin<T,X>) parentEntityJoin).createCorrelation();
getQuerySpec().addRoot( correlated.getCorrelatedRoot() );
return correlated;
}
@ -571,12 +585,12 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
}
@Override
public SqmPredicate equalTo(Expression<T> that) {
public SqmPredicate equalTo(Expression<?> that) {
return nodeBuilder().equal( this, that );
}
@Override
public SqmPredicate equalTo(T that) {
public SqmPredicate equalTo(Object that) {
return nodeBuilder().equal( this, that );
}
@ -681,6 +695,46 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
return new SqmSubQuery<>( this, type, nodeBuilder() );
}
@Override
public <U> Subquery<U> subquery(EntityType<U> type) {
return new SqmSubQuery<>( this, type, nodeBuilder() );
}
@Override
public Subquery<T> where(List<Predicate> restrictions) {
//noinspection rawtypes,unchecked
getQuerySpec().getWhereClause().applyPredicates( (List) restrictions );
return this;
}
@Override
public Subquery<T> having(List<Predicate> restrictions) {
//noinspection unchecked,rawtypes
final SqmPredicate combined = combinePredicates( getQuerySpec().getHavingClausePredicate(), (List) restrictions );
getQuerySpec().setHavingClausePredicate( combined );
return this;
}
@Override
public Set<ParameterExpression<?>> getParameters() {
return Collections.emptySet();
}
@Override
public Predicate notEqualTo(Expression<?> value) {
return nodeBuilder().notEqual( this, value );
}
@Override
public Predicate notEqualTo(Object value) {
return nodeBuilder().notEqual( this, value );
}
@Override
public <X> Expression<X> cast(Class<X> targetType) {
return nodeBuilder().cast( this, targetType );
}
@Override
public String asLoggableText() {
return "<sub-query>";

View File

@ -34,10 +34,14 @@ import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.SingularAttribute;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -255,6 +259,16 @@ public class SqmUpdateStatement<T>
return walker.visitUpdateStatement( this );
}
@Override
public <U> SqmSubQuery<U> subquery(EntityType<U> type) {
return new SqmSubQuery<>( this, type, nodeBuilder() );
}
@Override
public Set<ParameterExpression<?>> getParameters() {
return null;
}
public <Y> void applyAssignment(SqmPath<Y> targetPath, SqmExpression<? extends Y> value) {
applyAssignment( new SqmAssignment<>( targetPath, value ) );
}

View File

@ -21,7 +21,7 @@ import org.hibernate.Incubating;
* @author Gavin King
*/
@Incubating
public interface SchemaManager {
public interface SchemaManager extends jakarta.persistence.SchemaManager {
/**
* Export database objects mapped by Hibernate entities.
* <p>
@ -60,4 +60,14 @@ public interface SchemaManager {
* Programmatic way to run {@link org.hibernate.tool.schema.spi.SchemaTruncator}.
*/
void truncateMappedObjects();
@Override
default void create(boolean createSchemas) {
exportMappedObjects( createSchemas );
}
@Override
default void drop(boolean dropSchemas) {
drop( dropSchemas );
}
}

View File

@ -9,8 +9,6 @@ package org.hibernate.spi;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.internal.util.NullnessUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
/**

View File

@ -6735,7 +6735,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
private boolean isNullsFirst(SortSpecification sortSpecification) {
NullPrecedence nullPrecedence = sortSpecification.getNullPrecedence();
NullPrecedence nullPrecedence = sortSpecification.getHibernateNullPrecedence();
if ( nullPrecedence == null || nullPrecedence == NullPrecedence.NONE ) {
switch ( dialect.getNullOrdering() ) {
case FIRST:

View File

@ -12,6 +12,8 @@ import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import jakarta.persistence.criteria.Nulls;
/**
* @author Steve Ebersole
*/
@ -39,6 +41,10 @@ public class SortSpecification implements SqlAstNode {
this.ignoreCase = ignoreCase;
}
public SortSpecification(Expression sortExpression, SortDirection sortOrder, Nulls nullPrecedence) {
this( sortExpression,sortOrder, NullPrecedence.fromJpaValue( nullPrecedence ) );
}
public Expression getSortExpression() {
return sortExpression;
}
@ -47,10 +53,14 @@ public class SortSpecification implements SqlAstNode {
return sortOrder;
}
public NullPrecedence getNullPrecedence() {
public NullPrecedence getHibernateNullPrecedence() {
return nullPrecedence;
}
public Nulls getNullPrecedence() {
return nullPrecedence.getJpaValue();
}
public boolean isIgnoreCase() {
return ignoreCase;
}

View File

@ -17,8 +17,8 @@ import org.gradle.api.initialization.Settings;
*/
public class JpaVersion {
public static final String EXT_KEY = "jakartaJpaVersion";
public static final String VERSION_KEY = "jakartaJpaVersion";
public static final String DEFAULT_VERSION = "3.1.0";
public static final String VERSION_KEY = "jakartaJpaVersionOverride";
public static final String DEFAULT_VERSION = "3.2.0-B01";
private final String name;
private final String osgiName;

View File

@ -2576,7 +2576,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
}
}
else if ( selection instanceof JpaEntityJoin ) {
final JpaEntityJoin<?> from = (JpaEntityJoin<?>) selection;
final JpaEntityJoin<?,?> from = (JpaEntityJoin<?,?>) selection;
returnTypeCorrect = checkReturnedEntity( from.getModel(), returnType );
}
else if ( selection instanceof JpaRoot ) {