From 4174c146754c8a91566f35c58b096a0dd8e17c53 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Sat, 23 Jun 2012 20:41:50 -0500 Subject: [PATCH] HHH-7387 - Integrate Draft 6 of the JPA 2.1 spec : UPDATE/DELETE criterias --- hibernate-core/src/main/antlr/hql.g | 2 +- .../ejb/AbstractEntityManagerImpl.java | 51 +- .../org/hibernate/ejb/EntityManagerImpl.java | 12 - .../AbstractManipulationCriteriaQuery.java | 171 +++++++ .../ejb/criteria/CriteriaBuilderImpl.java | 4 +- .../ejb/criteria/CriteriaDeleteImpl.java | 62 +++ .../ejb/criteria/CriteriaQueryCompiler.java | 477 ------------------ .../ejb/criteria/CriteriaQueryImpl.java | 120 +++-- .../ejb/criteria/CriteriaSubqueryImpl.java | 5 +- .../ejb/criteria/CriteriaUpdateImpl.java | 147 ++++++ .../ejb/criteria/FromImplementor.java | 6 +- .../hibernate/ejb/criteria/PathSource.java | 4 +- .../ejb/criteria/QueryStructure.java | 9 +- .../hibernate/ejb/criteria/Renderable.java | 6 +- .../criteria/compile/CompilableCriteria.java | 34 ++ .../criteria/compile/CriteriaCompiler.java | 154 ++++++ .../compile/CriteriaInterpretation.java | 47 ++ .../CriteriaQueryTypeQueryAdapter.java | 271 ++++++++++ .../compile/ImplicitParameterBinding.java | 56 ++ .../compile/InterpretedParameterMetadata.java | 38 ++ .../criteria/compile/RenderingContext.java | 68 +++ .../expression/BinaryArithmeticOperation.java | 6 +- .../expression/CoalesceExpression.java | 6 +- .../expression/CompoundSelectionImpl.java | 6 +- .../criteria/expression/ConcatExpression.java | 6 +- .../expression/EntityTypeExpression.java | 6 +- .../expression/ListIndexExpression.java | 6 +- .../expression/LiteralExpression.java | 6 +- .../expression/MapEntryExpression.java | 8 +- .../expression/NullLiteralExpression.java | 6 +- .../criteria/expression/NullifExpression.java | 6 +- .../expression/ParameterExpressionImpl.java | 6 +- .../expression/PathTypeExpression.java | 6 +- .../expression/SearchedCaseExpression.java | 6 +- .../expression/SimpleCaseExpression.java | 6 +- .../SizeOfCollectionExpression.java | 6 +- .../SubqueryComparisonModifierExpression.java | 6 +- .../expression/UnaryArithmeticOperation.java | 6 +- .../expression/function/AbsFunction.java | 5 + .../function/AggregationFunction.java | 14 +- .../function/BasicFunctionExpression.java | 6 +- .../expression/function/CastFunction.java | 4 +- .../expression/function/LengthFunction.java | 5 + .../expression/function/LocateFunction.java | 4 +- .../expression/function/LowerFunction.java | 5 + .../ParameterizedFunctionExpression.java | 53 +- .../expression/function/SqrtFunction.java | 5 + .../function/SubstringFunction.java | 4 +- .../expression/function/TrimFunction.java | 4 +- .../expression/function/UpperFunction.java | 5 + .../ejb/criteria/path/AbstractFromImpl.java | 12 +- .../ejb/criteria/path/AbstractJoinImpl.java | 4 +- .../ejb/criteria/path/AbstractPathImpl.java | 8 +- .../path/CollectionAttributeJoin.java | 8 +- .../ejb/criteria/path/ListAttributeJoin.java | 8 +- .../ejb/criteria/path/MapAttributeJoin.java | 8 +- .../hibernate/ejb/criteria/path/RootImpl.java | 36 +- .../ejb/criteria/path/SetAttributeJoin.java | 8 +- .../criteria/path/SingularAttributeJoin.java | 6 +- .../criteria/path/SingularAttributePath.java | 8 +- .../criteria/predicate/BetweenPredicate.java | 6 +- .../predicate/BooleanAssertionPredicate.java | 6 +- .../predicate/BooleanExpressionPredicate.java | 6 +- .../BooleanStaticAssertionPredicate.java | 6 +- .../predicate/ComparisonPredicate.java | 6 +- .../criteria/predicate/CompoundPredicate.java | 6 +- .../criteria/predicate/ExistsPredicate.java | 6 +- .../predicate/ExplicitTruthValueCheck.java | 6 +- .../ejb/criteria/predicate/InPredicate.java | 6 +- .../criteria/predicate/IsEmptyPredicate.java | 6 +- .../ejb/criteria/predicate/LikePredicate.java | 6 +- .../criteria/predicate/MemberOfPredicate.java | 6 +- .../criteria/predicate/NullnessPredicate.java | 6 +- .../criteria/ManipulationCriteriaTest.java | 173 +++++++ 74 files changed, 1597 insertions(+), 722 deletions(-) create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractManipulationCriteriaQuery.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaDeleteImpl.java delete mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaUpdateImpl.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CompilableCriteria.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaCompiler.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaInterpretation.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaQueryTypeQueryAdapter.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/ImplicitParameterBinding.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/InterpretedParameterMetadata.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/RenderingContext.java create mode 100644 hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/ManipulationCriteriaTest.java diff --git a/hibernate-core/src/main/antlr/hql.g b/hibernate-core/src/main/antlr/hql.g index 20652c5eee..efa86e7cbc 100644 --- a/hibernate-core/src/main/antlr/hql.g +++ b/hibernate-core/src/main/antlr/hql.g @@ -723,7 +723,7 @@ castedIdentPrimaryBase aggregate : ( SUM^ | AVG^ | MAX^ | MIN^ ) OPEN! additiveExpression CLOSE! { #aggregate.setType(AGGREGATE); } // Special case for count - It's 'parameters' can be keywords. - | COUNT^ OPEN! ( STAR { #STAR.setType(ROW_STAR); } | ( ( DISTINCT | ALL )? ( path | collectionExpr ) ) ) CLOSE! + | COUNT^ OPEN! ( STAR { #STAR.setType(ROW_STAR); } | ( ( DISTINCT | ALL )? ( path | collectionExpr | NUM_INT ) ) ) CLOSE! | collectionExpr ; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java index fc2e3bd5ed..0925c26268 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java @@ -23,15 +23,6 @@ */ package org.hibernate.ejb; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import javax.persistence.CacheRetrieveMode; import javax.persistence.CacheStoreMode; import javax.persistence.EntityExistsException; @@ -55,13 +46,24 @@ import javax.persistence.Tuple; import javax.persistence.TupleElement; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.CriteriaUpdate; import javax.persistence.criteria.Selection; import javax.persistence.metamodel.Metamodel; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.transaction.Status; import javax.transaction.SystemException; import javax.transaction.TransactionManager; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.jboss.logging.Logger; @@ -86,8 +88,9 @@ import org.hibernate.cfg.Environment; import org.hibernate.dialect.lock.LockingStrategyException; import org.hibernate.dialect.lock.OptimisticEntityLockException; import org.hibernate.dialect.lock.PessimisticEntityLockException; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ValueHandlerFactory; +import org.hibernate.ejb.criteria.compile.CompilableCriteria; +import org.hibernate.ejb.criteria.compile.CriteriaCompiler; import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl; import org.hibernate.ejb.internal.EntityManagerMessageLogger; import org.hibernate.ejb.util.CacheModeHelper; @@ -452,7 +455,9 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage org.hibernate.Query hqlQuery = getSession().createQuery( jpaqlString ); if ( options.getValueHandlers() == null ) { - options.getResultMetadataValidator().validate( hqlQuery.getReturnTypes() ); + if ( options.getResultMetadataValidator() != null ) { + options.getResultMetadataValidator().validate( hqlQuery.getReturnTypes() ); + } } // determine if we need a result transformer @@ -578,13 +583,27 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage } } - private CriteriaQueryCompiler criteriaQueryCompiler; + private CriteriaCompiler criteriaCompiler; + + protected CriteriaCompiler criteriaCompiler() { + if ( criteriaCompiler == null ) { + criteriaCompiler = new CriteriaCompiler( this ); + } + return criteriaCompiler; + } public TypedQuery createQuery(CriteriaQuery criteriaQuery) { - if ( criteriaQueryCompiler == null ) { - criteriaQueryCompiler = new CriteriaQueryCompiler( this ); - } - return criteriaQueryCompiler.compile( criteriaQuery ); + return (TypedQuery) criteriaCompiler().compile( (CompilableCriteria) criteriaQuery ); + } + + @Override + public Query createQuery(CriteriaUpdate criteriaUpdate) { + return criteriaCompiler().compile( (CompilableCriteria) criteriaUpdate ); + } + + @Override + public Query createQuery(CriteriaDelete criteriaDelete) { + return criteriaCompiler().compile( (CompilableCriteria) criteriaDelete ); } public Query createNamedQuery(String name) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java index a96640d5e8..d34d476d6b 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java @@ -28,8 +28,6 @@ import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceException; import javax.persistence.Query; import javax.persistence.StoredProcedureQuery; -import javax.persistence.criteria.CriteriaDelete; -import javax.persistence.criteria.CriteriaUpdate; import javax.persistence.spi.PersistenceUnitTransactionType; import org.jboss.logging.Logger; @@ -131,16 +129,6 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess return session; } - @Override - public Query createQuery(CriteriaUpdate updateQuery) { - throw new NotYetImplementedException(); - } - - @Override - public Query createQuery(CriteriaDelete deleteQuery) { - throw new NotYetImplementedException(); - } - @Override public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { throw new NotYetImplementedException(); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractManipulationCriteriaQuery.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractManipulationCriteriaQuery.java new file mode 100644 index 0000000000..3101309f04 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractManipulationCriteriaQuery.java @@ -0,0 +1,171 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria; + +import javax.persistence.Query; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; +import javax.persistence.metamodel.EntityType; +import java.util.List; +import java.util.Map; + +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.ejb.HibernateEntityManagerImplementor; +import org.hibernate.ejb.QueryImpl; +import org.hibernate.ejb.criteria.compile.CompilableCriteria; +import org.hibernate.ejb.criteria.compile.CriteriaInterpretation; +import org.hibernate.ejb.criteria.compile.ImplicitParameterBinding; +import org.hibernate.ejb.criteria.compile.InterpretedParameterMetadata; +import org.hibernate.ejb.criteria.compile.RenderingContext; +import org.hibernate.ejb.criteria.path.RootImpl; + +/** + * Base class for commonality between {@link javax.persistence.criteria.CriteriaUpdate} and + * {@link javax.persistence.criteria.CriteriaDelete} + * + * @author Steve Ebersole + */ +public abstract class AbstractManipulationCriteriaQuery implements CompilableCriteria { + private final CriteriaBuilderImpl criteriaBuilder; + + private RootImpl root; + private Predicate restriction; + private List> subQueries; + + protected AbstractManipulationCriteriaQuery(CriteriaBuilderImpl criteriaBuilder) { + this.criteriaBuilder = criteriaBuilder; + } + + protected CriteriaBuilderImpl criteriaBuilder() { + return criteriaBuilder; + } + + + // Root ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public Root from(Class entityClass) { + EntityType entityType = criteriaBuilder.getEntityManagerFactory() + .getMetamodel() + .entity( entityClass ); + if ( entityType == null ) { + throw new IllegalArgumentException( entityClass + " is not an entity" ); + } + return from( entityType ); + } + + public Root from(EntityType entityType) { + root = new RootImpl( criteriaBuilder, entityType, false ); + return root; + } + + public Root getRoot() { + return root; + } + + + // Restriction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + protected void setRestriction(Expression restriction) { + this.restriction = criteriaBuilder.wrap( restriction ); + } + + public void setRestriction(Predicate... restrictions) { + this.restriction = criteriaBuilder.and( restrictions ); + } + + public Predicate getRestriction() { + return restriction; + } + + public Subquery subquery(Class type) { + // Need clarification on spec in terms of how the built Subquery.getParent should be handled since getParent + // returns an AbstractQuery whereas neither CriteriaUpdate nor CriteriaDelete extend AbstractQuery + throw new NotYetImplementedException( "Need clarification on spec" ); + } + + + // compiling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public void validate() { + if ( root == null ) { + throw new IllegalStateException( "UPDATE/DELETE criteria must name root entity" ); + } + } + + @Override + public CriteriaInterpretation interpret(RenderingContext renderingContext) { + final String jpaqlString = renderQuery( renderingContext ); + return new CriteriaInterpretation() { + @Override + @SuppressWarnings("unchecked") + public Query buildCompiledQuery( + HibernateEntityManagerImplementor entityManager, + final InterpretedParameterMetadata interpretedParameterMetadata) { + + QueryImpl jpaqlQuery = entityManager.createQuery( + jpaqlString, + null, + null, + new HibernateEntityManagerImplementor.Options() { + @Override + public List getValueHandlers() { + return null; + } + + @Override + public Map getNamedParameterExplicitTypes() { + return interpretedParameterMetadata.implicitParameterTypes(); + } + + @Override + public ResultMetadataValidator getResultMetadataValidator() { + return null; + } + } + ); + + for ( ImplicitParameterBinding implicitParameterBinding : interpretedParameterMetadata.implicitParameterBindings() ) { + implicitParameterBinding.bind( jpaqlQuery ); + } + + return jpaqlQuery; + } + }; + } + + protected abstract String renderQuery(RenderingContext renderingContext); + + protected void renderRoot(StringBuilder jpaql, RenderingContext renderingContext) { + jpaql.append( ( (FromImplementor) root ).renderTableExpression( renderingContext ) ); + } + + protected void renderRestrictions(StringBuilder jpaql, RenderingContext renderingContext) { + if ( getRestriction() != null) { + jpaql.append( " where " ) + .append( ( (Renderable) getRestriction() ).render( renderingContext ) ); + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java index 22ff6312cc..92e14ea534 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java @@ -137,12 +137,12 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { @Override public CriteriaUpdate createCriteriaUpdate(Class targetEntity) { - throw new NotYetImplementedException(); + return new CriteriaUpdateImpl( this ); } @Override public CriteriaDelete createCriteriaDelete(Class targetEntity) { - throw new NotYetImplementedException(); + return new CriteriaDeleteImpl( this ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaDeleteImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaDeleteImpl.java new file mode 100644 index 0000000000..6b27764d62 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaDeleteImpl.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria; + +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Predicate; + +import org.hibernate.ejb.criteria.compile.RenderingContext; + +/** + * Hibernate implementation of the JPA 2.1 {@link CriteriaDelete} contract. + * + * @author Steve Ebersole + */ +public class CriteriaDeleteImpl extends AbstractManipulationCriteriaQuery implements CriteriaDelete { + protected CriteriaDeleteImpl(CriteriaBuilderImpl criteriaBuilder) { + super( criteriaBuilder ); + } + + @Override + public CriteriaDelete where(Expression restriction) { + setRestriction( restriction ); + return this; + } + + @Override + public CriteriaDelete where(Predicate... restrictions) { + setRestriction( restrictions ); + return this; + } + + @Override + protected String renderQuery(RenderingContext renderingContext) { + final StringBuilder jpaql = new StringBuilder( "delete " ); + renderRoot( jpaql, renderingContext ); + renderRestrictions( jpaql, renderingContext ); + + return jpaql.toString(); + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java deleted file mode 100644 index 3354a66b10..0000000000 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.ejb.criteria; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.persistence.FlushModeType; -import javax.persistence.LockModeType; -import javax.persistence.Parameter; -import javax.persistence.TemporalType; -import javax.persistence.TypedQuery; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.ParameterExpression; - -import org.jboss.logging.Logger; - -import org.hibernate.Query; -import org.hibernate.ejb.HibernateEntityManagerImplementor; -import org.hibernate.ejb.HibernateQuery; -import org.hibernate.ejb.QueryImpl; -import org.hibernate.ejb.internal.EntityManagerMessageLogger; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.type.Type; - -/** - * Compiles a JPA criteria query into an executable {@link TypedQuery}. Its single contract is the {@link #compile} - * method. - *

- * NOTE : This is a temporary implementation which simply translates the criteria query into a JPAQL query string. A - * better, long-term solution is being implemented as part of refactoring the JPAQL/HQL translator. - * - * @author Steve Ebersole - */ -public class CriteriaQueryCompiler implements Serializable { - - private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class, - CriteriaQueryCompiler.class.getName()); - - /** - * Used to describe implicit (not defined in criteria query) parameters. - */ - public static interface ImplicitParameterBinding { - /** - * Retrieve the generated name of the implicit parameter. - * - * @return The parameter name. - */ - public String getParameterName(); - - /** - * Get the java type of the "thing" that led to the implicit parameter. Used from - * {@link org.hibernate.ejb.HibernateEntityManagerImplementor.Options#getNamedParameterExplicitTypes()} - * in determining "guessed type" overriding. - * - * @return The java type - */ - public Class getJavaType(); - - /** - * Bind the implicit parameter's value to the JPA query. - * - * @param typedQuery The JPA query. - */ - public void bind(TypedQuery typedQuery); - } - - /** - * Used to provide a context and services to the rendering. - */ - public static interface RenderingContext { - /** - * Generate a correlation name. - * - * @return The generated correlation name - */ - public String generateAlias(); - - /** - * Register parameters explicitly encountered in the criteria query. - * - * @param criteriaQueryParameter The parameter expression - * - * @return The JPA-QL parameter name - */ - public String registerExplicitParameter(ParameterExpression criteriaQueryParameter); - - /** - * Register a parameter that was not part of the criteria query (at least not as a parameter). - * - * @param literal The literal value - * @param javaType The java type as whcih to handle the literal value. - * - * @return The JPA-QL parameter name - */ - public String registerLiteralParameterBinding(Object literal, Class javaType); - - /** - * Given a java type, determine the proper cast type name. - * - * @param javaType The java type. - * - * @return The cast type name. - */ - public String getCastType(Class javaType); - } - - public static interface RenderedCriteriaQuery { - public String getQueryString(); - public List getValueHandlers(); - public HibernateEntityManagerImplementor.Options.ResultMetadataValidator getResultMetadataValidator(); - } - - private final HibernateEntityManagerImplementor entityManager; - - public CriteriaQueryCompiler(HibernateEntityManagerImplementor entityManager) { - this.entityManager = entityManager; - } - - public TypedQuery compile(CriteriaQuery criteriaQuery) { - CriteriaQueryImpl criteriaQueryImpl = ( CriteriaQueryImpl ) criteriaQuery; - criteriaQueryImpl.validate(); - - final Map,String> explicitParameterMapping = new HashMap,String>(); - final Map> explicitParameterNameMapping = new HashMap>(); - final List implicitParameterBindings = new ArrayList(); - final Map implicitParameterTypes = new HashMap(); - - RenderingContext renderingContext = new RenderingContext() { - private int aliasCount = 0; - private int explicitParameterCount = 0; - - public String generateAlias() { - return "generatedAlias" + aliasCount++; - } - - public String generateParameterName() { - return "param" + explicitParameterCount++; - } - - public String registerExplicitParameter(ParameterExpression criteriaQueryParameter) { - final String jpaqlParameterName; - if ( explicitParameterMapping.containsKey( criteriaQueryParameter ) ) { - jpaqlParameterName = explicitParameterMapping.get( criteriaQueryParameter ); - } - else { - jpaqlParameterName = generateParameterName(); - explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName ); - } - if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) { - explicitParameterNameMapping.put( - criteriaQueryParameter.getName(), - criteriaQueryParameter - ); - } - return jpaqlParameterName; - } - - public String registerLiteralParameterBinding(final Object literal, final Class javaType) { - final String parameterName = generateParameterName(); - final ImplicitParameterBinding binding = new CriteriaQueryCompiler.ImplicitParameterBinding() { - public String getParameterName() { - return parameterName; - } - - public Class getJavaType() { - return javaType; - } - - public void bind(TypedQuery typedQuery) { - typedQuery.setParameter( parameterName, literal ); - } - }; - - implicitParameterBindings.add( binding ); - implicitParameterTypes.put( parameterName, javaType ); - return parameterName; - } - - public String getCastType(Class javaType) { - SessionFactoryImplementor factory = - ( SessionFactoryImplementor ) entityManager.getFactory().getSessionFactory(); - Type hibernateType = factory.getTypeResolver().heuristicType( javaType.getName() ); - if ( hibernateType == null ) { - throw new IllegalArgumentException( - "Could not convert java type [" + javaType.getName() + "] to Hibernate type" - ); - } - return hibernateType.getName(); - } - }; - - final RenderedCriteriaQuery renderedCriteriaQuery = criteriaQueryImpl.render( renderingContext ); - - LOG.debugf("Rendered criteria query -> %s", renderedCriteriaQuery.getQueryString()); - - QueryImpl jpaqlQuery = entityManager.createQuery( - renderedCriteriaQuery.getQueryString(), - criteriaQuery.getResultType(), - criteriaQuery.getSelection(), - new HibernateEntityManagerImplementor.Options() { - public List getValueHandlers() { - return renderedCriteriaQuery.getValueHandlers(); - } - - public Map getNamedParameterExplicitTypes() { - return implicitParameterTypes; - } - - public ResultMetadataValidator getResultMetadataValidator() { - return renderedCriteriaQuery.getResultMetadataValidator(); - } - } - ); - - for ( ImplicitParameterBinding implicitParameterBinding : implicitParameterBindings ) { - implicitParameterBinding.bind( jpaqlQuery ); - } - - return new CriteriaQueryTypeQueryAdapter( jpaqlQuery, explicitParameterMapping, explicitParameterNameMapping ); - } - - public static class CriteriaQueryTypeQueryAdapter implements TypedQuery, HibernateQuery { - private final QueryImpl jpaqlQuery; - private final Map, String> explicitParameterMapping; - private final Map> explicitParameterNameMapping; - - public CriteriaQueryTypeQueryAdapter( - QueryImpl jpaqlQuery, - Map, String> explicitParameterMapping, - Map> explicitParameterNameMapping) { - this.jpaqlQuery = jpaqlQuery; - this.explicitParameterMapping = explicitParameterMapping; - this.explicitParameterNameMapping = explicitParameterNameMapping; - } - - @Override - public Query getHibernateQuery() { - return jpaqlQuery.getHibernateQuery(); - } - - public List getResultList() { - return jpaqlQuery.getResultList(); - } - - public X getSingleResult() { - return jpaqlQuery.getSingleResult(); - } - - public int getMaxResults() { - return jpaqlQuery.getMaxResults(); - } - - public TypedQuery setMaxResults(int i) { - jpaqlQuery.setMaxResults( i ); - return this; - } - - public int getFirstResult() { - return jpaqlQuery.getFirstResult(); - } - - public TypedQuery setFirstResult(int i) { - jpaqlQuery.setFirstResult( i ); - return this; - } - - public Map getHints() { - return jpaqlQuery.getHints(); - } - - public TypedQuery setHint(String name, Object value) { - jpaqlQuery.setHint( name, value); - return this; - } - - public FlushModeType getFlushMode() { - return jpaqlQuery.getFlushMode(); - } - - public TypedQuery setFlushMode(FlushModeType flushModeType) { - jpaqlQuery.setFlushMode( flushModeType ); - return this; - } - - public LockModeType getLockMode() { - return jpaqlQuery.getLockMode(); - } - - public TypedQuery setLockMode(LockModeType lockModeType) { - jpaqlQuery.setLockMode( lockModeType ); - return this; - } - - @SuppressWarnings({ "unchecked" }) - public Set getParameters() { - return explicitParameterMapping.keySet(); - } - - public boolean isBound(Parameter param) { - return jpaqlQuery.isBound( param ); - } - - @SuppressWarnings({ "unchecked" }) - public T getParameterValue(Parameter param) { - return ( T ) jpaqlQuery.getParameterValue( mapToNamedParameter( param ) ); - } - - @SuppressWarnings({ "unchecked" }) - public TypedQuery setParameter(Parameter param, T t) { - jpaqlQuery.setParameter( mapToNamedParameter( param ), t ); - return this; - } - - @SuppressWarnings({ "RedundantCast" }) - private Parameter mapToNamedParameter(Parameter criteriaParameter) { - return jpaqlQuery.getParameter( - explicitParameterMapping.get( criteriaParameter ) - ); - } - - @SuppressWarnings({ "unchecked" }) - public TypedQuery setParameter(Parameter param, Calendar calendar, TemporalType temporalType) { - jpaqlQuery.setParameter( mapToNamedParameter( param ), calendar, temporalType ); - return this; - } - - @SuppressWarnings({ "unchecked" }) - public TypedQuery setParameter(Parameter param, Date date, TemporalType temporalType) { - jpaqlQuery.setParameter( mapToNamedParameter( param ), date, temporalType ); - return this; - } - - public T unwrap(Class cls) { - return jpaqlQuery.unwrap( cls ); - } - - @SuppressWarnings({ "unchecked" }) - public Object getParameterValue(String name) { - return getParameterValue( resolveExplicitCriteriaParameterName( name ) ); - } - - private Parameter resolveExplicitCriteriaParameterName(String name) { - Parameter parameter = explicitParameterNameMapping.get( name ); - if ( parameter == null ) { - throw new IllegalArgumentException( "Named parameter [" + name + "] not encountered" ); - } - return parameter; - } - - public Parameter getParameter(String name) { - return mapToNamedParameter( resolveExplicitCriteriaParameterName( name ) ); - } - - @SuppressWarnings({ "unchecked" }) - public Parameter getParameter(String name, Class type) { - Parameter parameter = resolveExplicitCriteriaParameterName( name ); - if ( type.isAssignableFrom( parameter.getParameterType() ) ) { - return parameter; - } - throw new IllegalArgumentException( - "Named parameter [" + name + "] type is not assignanle to request type [" - + type.getName() + "]" - ); - } - - @SuppressWarnings({ "unchecked" }) - public TypedQuery setParameter(String name, Object value) { - setParameter( - resolveExplicitCriteriaParameterName( name, value ), - value - ); - return this; - } - - private Parameter resolveExplicitCriteriaParameterName(String name, Object value) { - Parameter parameter = resolveExplicitCriteriaParameterName( name ); - // todo : is null valid? - if ( value != null ) { - if ( ! parameter.getParameterType().isInstance( value ) ) { - throw new IllegalArgumentException( - "Named parameter [" + name + "] type mismatch; expecting [" - + parameter.getParameterType().getName() + "], found [" - + value.getClass().getName() + "]" - ); - } - } - return parameter; - } - - @SuppressWarnings({ "unchecked" }) - public TypedQuery setParameter(String name, Calendar calendar, TemporalType temporalType) { - Parameter parameter = resolveExplicitCriteriaParameterName( name ); - if ( ! Calendar.class.isAssignableFrom( parameter.getParameterType() ) ) { - throw new IllegalArgumentException( - "Named parameter [" + name + "] type mismatch; expecting [" - + Calendar.class.getName() + "], found [" - + parameter.getParameterType().getName() + "]" - ); - } - setParameter( parameter, calendar, temporalType ); - return this; - } - - @SuppressWarnings({ "unchecked" }) - public TypedQuery setParameter(String name, Date date, TemporalType temporalType) { - Parameter parameter = resolveExplicitCriteriaParameterName( name ); - if ( ! Date.class.isAssignableFrom( parameter.getParameterType() ) ) { - throw new IllegalArgumentException( - "Named parameter [" + name + "] type mismatch; expecting [" - + Date.class.getName() + "], found [" - + parameter.getParameterType().getName() + "]" - ); - } - setParameter( parameter, date, temporalType ); - return this; - } - - - // unsupported stuff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - public int executeUpdate() { - throw new IllegalArgumentException( "Criteria queries do not support update queries" ); - } - - public TypedQuery setParameter(int i, Object o) { - throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); - } - - public TypedQuery setParameter(int i, Calendar calendar, TemporalType temporalType) { - throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); - } - - public TypedQuery setParameter(int i, Date date, TemporalType temporalType) { - throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); - } - - public Object getParameterValue(int position) { - throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); - } - - public Parameter getParameter(int position) { - throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); - } - - public Parameter getParameter(int position, Class type) { - throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); - } - } -} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryImpl.java index 712e00062c..78b0e381c9 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryImpl.java @@ -27,7 +27,9 @@ import java.io.Serializable; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.persistence.Query; import javax.persistence.Tuple; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; @@ -39,7 +41,16 @@ import javax.persistence.criteria.Selection; import javax.persistence.criteria.Subquery; import javax.persistence.metamodel.EntityType; +import org.jboss.logging.Logger; + import org.hibernate.ejb.HibernateEntityManagerImplementor; +import org.hibernate.ejb.QueryImpl; +import org.hibernate.ejb.criteria.compile.CompilableCriteria; +import org.hibernate.ejb.criteria.compile.CriteriaInterpretation; +import org.hibernate.ejb.criteria.compile.CriteriaQueryTypeQueryAdapter; +import org.hibernate.ejb.criteria.compile.ImplicitParameterBinding; +import org.hibernate.ejb.criteria.compile.InterpretedParameterMetadata; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.type.Type; /** @@ -48,7 +59,9 @@ import org.hibernate.type.Type; * * @author Steve Ebersole */ -public class CriteriaQueryImpl extends AbstractNode implements CriteriaQuery, Serializable { +public class CriteriaQueryImpl extends AbstractNode implements CriteriaQuery, CompilableCriteria, Serializable { + private static final Logger log = Logger.getLogger( CriteriaQueryImpl.class ); + private final Class returnType; private final QueryStructure queryStructure; @@ -334,60 +347,89 @@ public class CriteriaQueryImpl extends AbstractNode implements CriteriaQuery< return true; } - public CriteriaQueryCompiler.RenderedCriteriaQuery render(CriteriaQueryCompiler.RenderingContext renderingContext) { - final StringBuilder jpaqlQuery = new StringBuilder(); + @Override + public CriteriaInterpretation interpret(RenderingContext renderingContext) { + final StringBuilder jpaqlBuffer = new StringBuilder(); - queryStructure.render( jpaqlQuery, renderingContext ); + queryStructure.render( jpaqlBuffer, renderingContext ); if ( ! getOrderList().isEmpty() ) { - jpaqlQuery.append( " order by " ); + jpaqlBuffer.append( " order by " ); String sep = ""; for ( Order orderSpec : getOrderList() ) { - jpaqlQuery.append( sep ) + jpaqlBuffer.append( sep ) .append( ( ( Renderable ) orderSpec.getExpression() ).render( renderingContext ) ) .append( orderSpec.isAscending() ? " asc" : " desc" ); sep = ", "; } } - return new CriteriaQueryCompiler.RenderedCriteriaQuery() { - public String getQueryString() { - return jpaqlQuery.toString(); - } + final String jpaqlString = jpaqlBuffer.toString(); - @SuppressWarnings({ "unchecked" }) - public List getValueHandlers() { - SelectionImplementor selection = (SelectionImplementor) queryStructure.getSelection(); - return selection == null - ? null - : selection.getValueHandlers(); - } + log.debugf( "Rendered criteria query -> %s", jpaqlString ); - public HibernateEntityManagerImplementor.Options.ResultMetadataValidator getResultMetadataValidator() { - return new HibernateEntityManagerImplementor.Options.ResultMetadataValidator() { - public void validate(Type[] returnTypes) { - SelectionImplementor selection = (SelectionImplementor) queryStructure.getSelection(); - if ( selection != null ) { - if ( selection.isCompoundSelection() ) { - if ( returnTypes.length != selection.getCompoundSelectionItems().size() ) { - throw new IllegalStateException( - "Number of return values [" + returnTypes.length + - "] did not match expected [" + - selection.getCompoundSelectionItems().size() + "]" - ); - } + return new CriteriaInterpretation() { + @Override + @SuppressWarnings("unchecked") + public Query buildCompiledQuery(HibernateEntityManagerImplementor entityManager, final InterpretedParameterMetadata parameterMetadata) { + + QueryImpl jpaqlQuery = entityManager.createQuery( + jpaqlString, + getResultType(), + getSelection(), + new HibernateEntityManagerImplementor.Options() { + @Override + public List getValueHandlers() { + SelectionImplementor selection = (SelectionImplementor) queryStructure.getSelection(); + return selection == null + ? null + : selection.getValueHandlers(); } - else { - if ( returnTypes.length > 1 ) { - throw new IllegalStateException( - "Number of return values [" + returnTypes.length + - "] did not match expected [1]" - ); - } + + @Override + public Map getNamedParameterExplicitTypes() { + return parameterMetadata.implicitParameterTypes(); } + + @Override + public ResultMetadataValidator getResultMetadataValidator() { + return new HibernateEntityManagerImplementor.Options.ResultMetadataValidator() { + @Override + public void validate(Type[] returnTypes) { + SelectionImplementor selection = (SelectionImplementor) queryStructure.getSelection(); + if ( selection != null ) { + if ( selection.isCompoundSelection() ) { + if ( returnTypes.length != selection.getCompoundSelectionItems().size() ) { + throw new IllegalStateException( + "Number of return values [" + returnTypes.length + + "] did not match expected [" + + selection.getCompoundSelectionItems().size() + "]" + ); + } + } + else { + if ( returnTypes.length > 1 ) { + throw new IllegalStateException( + "Number of return values [" + returnTypes.length + + "] did not match expected [1]" + ); + } + } + } + } + }; } } - } - }; + ); + + for ( ImplicitParameterBinding implicitParameterBinding : parameterMetadata.implicitParameterBindings() ) { + implicitParameterBinding.bind( jpaqlQuery ); + } + + return new CriteriaQueryTypeQueryAdapter( + jpaqlQuery, + parameterMetadata.explicitParameterMapping(), + parameterMetadata.explicitParameterNameMapping() + ); } }; } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java index bc91c77e50..43b9d2a8cb 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java @@ -39,6 +39,7 @@ import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.Subquery; import javax.persistence.metamodel.EntityType; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.ExpressionImpl; import org.hibernate.ejb.criteria.path.RootImpl; @@ -277,14 +278,14 @@ public class CriteriaSubqueryImpl extends ExpressionImpl implements Subque return queryStructure.subquery( subqueryType ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { StringBuilder subqueryBuffer = new StringBuilder( "(" ); queryStructure.render( subqueryBuffer, renderingContext ); subqueryBuffer.append( ')' ); return subqueryBuffer.toString(); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { throw new IllegalStateException( "Subquery cannot occur in select clause" ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaUpdateImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaUpdateImpl.java new file mode 100644 index 0000000000..32bc32c7f4 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaUpdateImpl.java @@ -0,0 +1,147 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria; + +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.metamodel.SingularAttribute; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.ejb.criteria.compile.RenderingContext; +import org.hibernate.ejb.criteria.path.SingularAttributePath; + +/** + * Hibernate implementation of the JPA 2.1 {@link CriteriaUpdate} contract. + * + * @author Steve Ebersole + */ +public class CriteriaUpdateImpl extends AbstractManipulationCriteriaQuery implements CriteriaUpdate { + private List assignments = new ArrayList(); + + public CriteriaUpdateImpl(CriteriaBuilderImpl criteriaBuilder) { + super( criteriaBuilder ); + } + + @Override + public CriteriaUpdate set(SingularAttribute singularAttribute, X value) { + addAssignment( getRoot().get( singularAttribute ), criteriaBuilder().literal( value ) ); + return this; + } + + @Override + public CriteriaUpdate set( + SingularAttribute singularAttribute, + Expression value) { + addAssignment( getRoot().get( singularAttribute ), value ); + return this; + } + + @Override + public CriteriaUpdate set(Path attributePath, X value) { + addAssignment( attributePath, criteriaBuilder().literal( value ) ); + return this; + } + + @Override + public CriteriaUpdate set(Path attributePath, Expression value) { + addAssignment( attributePath, value ); + return this; + } + + @Override + public CriteriaUpdate set(String attributeName, Object value) { + addAssignment( getRoot().get( attributeName ), criteriaBuilder().literal( value ) ); + return this; + } + + protected void addAssignment(Path attributePath, Expression value) { + if ( ! PathImplementor.class.isInstance( attributePath ) ) { + throw new IllegalArgumentException( "Unexpected path implementation type : " + attributePath.getClass().getName() ); + } + if ( ! SingularAttributePath.class.isInstance( attributePath ) ) { + throw new IllegalArgumentException( + "Attribute path for assignment must represent a singular attribute [" + + ( (PathImplementor) attributePath ).getPathIdentifier() + "]" + ); + } + assignments.add( new Assignment( (SingularAttributePath) attributePath, value ) ); + } + + @Override + public CriteriaUpdate where(Expression restriction) { + setRestriction( restriction ); + return this; + } + + @Override + public CriteriaUpdate where(Predicate... restrictions) { + setRestriction( restrictions ); + return this; + } + + @Override + public void validate() { + super.validate(); + if ( assignments.isEmpty() ) { + throw new IllegalStateException( "No assignments specified as part of UPDATE criteria" ); + } + } + + @Override + protected String renderQuery(RenderingContext renderingContext) { + final StringBuilder jpaql = new StringBuilder( "update " ); + renderRoot( jpaql, renderingContext ); + renderAssignments( jpaql, renderingContext ); + renderRestrictions( jpaql, renderingContext ); + + return jpaql.toString(); + } + + private void renderAssignments(StringBuilder jpaql, RenderingContext renderingContext) { + jpaql.append( " set " ); + boolean first = true; + for ( Assignment assignment : assignments ) { + jpaql.append( assignment.attributePath.render( renderingContext ) ) + .append( " = " ) + .append( assignment.value.render( renderingContext ) ); + if ( ! first ) { + jpaql.append( ", " ); + } + first = false; + } + } + + private class Assignment { + private final SingularAttributePath attributePath; + private final ExpressionImplementor value; + + private Assignment(SingularAttributePath attributePath, Expression value) { + this.attributePath = attributePath; + this.value = (ExpressionImplementor) value; + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java index 0cdbc018e5..b5a8c4b7bf 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java @@ -24,14 +24,16 @@ package org.hibernate.ejb.criteria; import javax.persistence.criteria.From; +import org.hibernate.ejb.criteria.compile.RenderingContext; + /** * Implementation contract for the JPA {@link From} interface. * * @author Steve Ebersole */ public interface FromImplementor extends PathImplementor, From { - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext); - public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext); + public void prepareAlias(RenderingContext renderingContext); + public String renderTableExpression(RenderingContext renderingContext); public FromImplementor correlateTo(CriteriaSubqueryImpl subquery); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java index 98823a73e3..9d034425cf 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java @@ -24,13 +24,15 @@ package org.hibernate.ejb.criteria; import javax.persistence.criteria.Path; +import org.hibernate.ejb.criteria.compile.RenderingContext; + /** * Implementation contract for things which can be the source (parent, left-hand-side, etc) of a path * * @author Steve Ebersole */ public interface PathSource extends Path { - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext); + public void prepareAlias(RenderingContext renderingContext); /** * Get the string representation of this path as a navigation from one of the diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java index 6911f3fca6..5d732ea279 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java @@ -44,6 +44,7 @@ import javax.persistence.criteria.Selection; import javax.persistence.criteria.Subquery; import javax.persistence.metamodel.EntityType; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.path.RootImpl; /** @@ -240,7 +241,7 @@ public class QueryStructure implements Serializable { } @SuppressWarnings({ "unchecked" }) - public void render(StringBuilder jpaqlQuery, CriteriaQueryCompiler.RenderingContext renderingContext) { + public void render(StringBuilder jpaqlQuery, RenderingContext renderingContext) { jpaqlQuery.append( "select " ); if ( isDistinct() ) { jpaqlQuery.append( "distinct " ); @@ -300,7 +301,7 @@ public class QueryStructure implements Serializable { } @SuppressWarnings({ "unchecked" }) - private void renderFromClause(StringBuilder jpaqlQuery, CriteriaQueryCompiler.RenderingContext renderingContext) { + private void renderFromClause(StringBuilder jpaqlQuery, RenderingContext renderingContext) { jpaqlQuery.append( " from " ); String sep = ""; for ( Root root : getRoots() ) { @@ -342,7 +343,7 @@ public class QueryStructure implements Serializable { @SuppressWarnings({ "unchecked" }) private void renderJoins( StringBuilder jpaqlQuery, - CriteriaQueryCompiler.RenderingContext renderingContext, + RenderingContext renderingContext, Collection> joins) { if ( joins == null ) { return; @@ -375,7 +376,7 @@ public class QueryStructure implements Serializable { @SuppressWarnings({ "unchecked" }) private void renderFetches( StringBuilder jpaqlQuery, - CriteriaQueryCompiler.RenderingContext renderingContext, + RenderingContext renderingContext, Collection fetches) { if ( fetches == null ) { return; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/Renderable.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/Renderable.java index 42f11c0d1c..6070709865 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/Renderable.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/Renderable.java @@ -24,12 +24,14 @@ package org.hibernate.ejb.criteria; +import org.hibernate.ejb.criteria.compile.RenderingContext; + /** * TODO : javadoc * * @author Steve Ebersole */ public interface Renderable { - public String render(CriteriaQueryCompiler.RenderingContext renderingContext); - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext); + public String render(RenderingContext renderingContext); + public String renderProjection(RenderingContext renderingContext); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CompilableCriteria.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CompilableCriteria.java new file mode 100644 index 0000000000..890504c4c9 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CompilableCriteria.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria.compile; + +/** + * @author Steve Ebersole + */ +public interface CompilableCriteria { + + public void validate(); + + public CriteriaInterpretation interpret(RenderingContext renderingContext); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaCompiler.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaCompiler.java new file mode 100644 index 0000000000..a97eb6f16f --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaCompiler.java @@ -0,0 +1,154 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria.compile; + +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.ParameterExpression; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.ejb.HibernateEntityManagerImplementor; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.type.Type; + +/** + * Compiles a JPA criteria query into an executable {@link TypedQuery}. Its single contract is the {@link #compile} + * method. + *

+ * NOTE : This is a temporary implementation which simply translates the criteria query into a JPAQL query string. A + * better, long-term solution is being implemented as part of refactoring the JPAQL/HQL translator. + * + * @author Steve Ebersole + */ +public class CriteriaCompiler implements Serializable { + private final HibernateEntityManagerImplementor entityManager; + + public CriteriaCompiler(HibernateEntityManagerImplementor entityManager) { + this.entityManager = entityManager; + } + + public Query compile(CompilableCriteria criteria) { + criteria.validate(); + + final Map,String> explicitParameterMapping = new HashMap,String>(); + final Map> explicitParameterNameMapping = new HashMap>(); + final List implicitParameterBindings = new ArrayList(); + final Map implicitParameterTypes = new HashMap(); + + RenderingContext renderingContext = new RenderingContext() { + private int aliasCount = 0; + private int explicitParameterCount = 0; + + public String generateAlias() { + return "generatedAlias" + aliasCount++; + } + + public String generateParameterName() { + return "param" + explicitParameterCount++; + } + + public String registerExplicitParameter(ParameterExpression criteriaQueryParameter) { + final String jpaqlParameterName; + if ( explicitParameterMapping.containsKey( criteriaQueryParameter ) ) { + jpaqlParameterName = explicitParameterMapping.get( criteriaQueryParameter ); + } + else { + jpaqlParameterName = generateParameterName(); + explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName ); + } + if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) { + explicitParameterNameMapping.put( + criteriaQueryParameter.getName(), + criteriaQueryParameter + ); + } + return jpaqlParameterName; + } + + public String registerLiteralParameterBinding(final Object literal, final Class javaType) { + final String parameterName = generateParameterName(); + final ImplicitParameterBinding binding = new ImplicitParameterBinding() { + public String getParameterName() { + return parameterName; + } + + public Class getJavaType() { + return javaType; + } + + public void bind(TypedQuery typedQuery) { + typedQuery.setParameter( parameterName, literal ); + } + }; + + implicitParameterBindings.add( binding ); + implicitParameterTypes.put( parameterName, javaType ); + return parameterName; + } + + public String getCastType(Class javaType) { + SessionFactoryImplementor factory = + ( SessionFactoryImplementor ) entityManager.getFactory().getSessionFactory(); + Type hibernateType = factory.getTypeResolver().heuristicType( javaType.getName() ); + if ( hibernateType == null ) { + throw new IllegalArgumentException( + "Could not convert java type [" + javaType.getName() + "] to Hibernate type" + ); + } + return hibernateType.getName(); + } + }; + + return criteria.interpret( renderingContext ).buildCompiledQuery( + entityManager, + new InterpretedParameterMetadata() { + @Override + public Map, String> explicitParameterMapping() { + return explicitParameterMapping; + } + + @Override + public Map> explicitParameterNameMapping() { + return explicitParameterNameMapping; + } + + @Override + public List implicitParameterBindings() { + return implicitParameterBindings; + } + + @Override + public Map implicitParameterTypes() { + return implicitParameterTypes; + } + } + ); + } + +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaInterpretation.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaInterpretation.java new file mode 100644 index 0000000000..dbd8544423 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaInterpretation.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria.compile; + +import javax.persistence.Query; + +import org.hibernate.ejb.HibernateEntityManagerImplementor; + +/** + * The interpretation of a JPA criteria object. + * + * @author Steve Ebersole + */ +public interface CriteriaInterpretation { + /** + * Generate a {@link javax.persistence.Query} instance given the interpreted criteria compiled against the + * passed EntityManager. + * + * + * @param entityManager The EntityManager against which to create the Query instance. + * @param interpretedParameterMetadata parameter metadata + * + * @return The created Query instance. + */ + public Query buildCompiledQuery(HibernateEntityManagerImplementor entityManager, InterpretedParameterMetadata interpretedParameterMetadata); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaQueryTypeQueryAdapter.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaQueryTypeQueryAdapter.java new file mode 100644 index 0000000000..d06aec02d0 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/CriteriaQueryTypeQueryAdapter.java @@ -0,0 +1,271 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria.compile; + +import javax.persistence.FlushModeType; +import javax.persistence.LockModeType; +import javax.persistence.Parameter; +import javax.persistence.TemporalType; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.ParameterExpression; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.Query; +import org.hibernate.ejb.HibernateQuery; +import org.hibernate.ejb.QueryImpl; + +/** + * @author Steve Ebersole + */ +public class CriteriaQueryTypeQueryAdapter implements TypedQuery, HibernateQuery { + private final QueryImpl jpaqlQuery; + private final Map, String> explicitParameterMapping; + private final Map> explicitParameterNameMapping; + + public CriteriaQueryTypeQueryAdapter( + QueryImpl jpaqlQuery, + Map, String> explicitParameterMapping, + Map> explicitParameterNameMapping) { + this.jpaqlQuery = jpaqlQuery; + this.explicitParameterMapping = explicitParameterMapping; + this.explicitParameterNameMapping = explicitParameterNameMapping; + } + + @Override + public Query getHibernateQuery() { + return jpaqlQuery.getHibernateQuery(); + } + + public List getResultList() { + return jpaqlQuery.getResultList(); + } + + public X getSingleResult() { + return jpaqlQuery.getSingleResult(); + } + + public int getMaxResults() { + return jpaqlQuery.getMaxResults(); + } + + public TypedQuery setMaxResults(int i) { + jpaqlQuery.setMaxResults( i ); + return this; + } + + public int getFirstResult() { + return jpaqlQuery.getFirstResult(); + } + + public TypedQuery setFirstResult(int i) { + jpaqlQuery.setFirstResult( i ); + return this; + } + + public Map getHints() { + return jpaqlQuery.getHints(); + } + + public TypedQuery setHint(String name, Object value) { + jpaqlQuery.setHint( name, value); + return this; + } + + public FlushModeType getFlushMode() { + return jpaqlQuery.getFlushMode(); + } + + public TypedQuery setFlushMode(FlushModeType flushModeType) { + jpaqlQuery.setFlushMode( flushModeType ); + return this; + } + + public LockModeType getLockMode() { + return jpaqlQuery.getLockMode(); + } + + public TypedQuery setLockMode(LockModeType lockModeType) { + jpaqlQuery.setLockMode( lockModeType ); + return this; + } + + @SuppressWarnings({ "unchecked" }) + public Set getParameters() { + return explicitParameterMapping.keySet(); + } + + public boolean isBound(Parameter param) { + return jpaqlQuery.isBound( param ); + } + + @SuppressWarnings({ "unchecked" }) + public T getParameterValue(Parameter param) { + return ( T ) jpaqlQuery.getParameterValue( mapToNamedParameter( param ) ); + } + + @SuppressWarnings({ "unchecked" }) + public TypedQuery setParameter(Parameter param, T t) { + jpaqlQuery.setParameter( mapToNamedParameter( param ), t ); + return this; + } + + @SuppressWarnings({ "RedundantCast" }) + private Parameter mapToNamedParameter(Parameter criteriaParameter) { + return jpaqlQuery.getParameter( + explicitParameterMapping.get( criteriaParameter ) + ); + } + + @SuppressWarnings({ "unchecked" }) + public TypedQuery setParameter(Parameter param, Calendar calendar, TemporalType temporalType) { + jpaqlQuery.setParameter( mapToNamedParameter( param ), calendar, temporalType ); + return this; + } + + @SuppressWarnings({ "unchecked" }) + public TypedQuery setParameter(Parameter param, Date date, TemporalType temporalType) { + jpaqlQuery.setParameter( mapToNamedParameter( param ), date, temporalType ); + return this; + } + + public T unwrap(Class cls) { + return jpaqlQuery.unwrap( cls ); + } + + @SuppressWarnings({ "unchecked" }) + public Object getParameterValue(String name) { + return getParameterValue( resolveExplicitCriteriaParameterName( name ) ); + } + + private Parameter resolveExplicitCriteriaParameterName(String name) { + Parameter parameter = explicitParameterNameMapping.get( name ); + if ( parameter == null ) { + throw new IllegalArgumentException( "Named parameter [" + name + "] not encountered" ); + } + return parameter; + } + + public Parameter getParameter(String name) { + return mapToNamedParameter( resolveExplicitCriteriaParameterName( name ) ); + } + + @SuppressWarnings({ "unchecked" }) + public Parameter getParameter(String name, Class type) { + Parameter parameter = resolveExplicitCriteriaParameterName( name ); + if ( type.isAssignableFrom( parameter.getParameterType() ) ) { + return parameter; + } + throw new IllegalArgumentException( + "Named parameter [" + name + "] type is not assignanle to request type [" + + type.getName() + "]" + ); + } + + @SuppressWarnings({ "unchecked" }) + public TypedQuery setParameter(String name, Object value) { + setParameter( + resolveExplicitCriteriaParameterName( name, value ), + value + ); + return this; + } + + private Parameter resolveExplicitCriteriaParameterName(String name, Object value) { + Parameter parameter = resolveExplicitCriteriaParameterName( name ); + // todo : is null valid? + if ( value != null ) { + if ( ! parameter.getParameterType().isInstance( value ) ) { + throw new IllegalArgumentException( + "Named parameter [" + name + "] type mismatch; expecting [" + + parameter.getParameterType().getName() + "], found [" + + value.getClass().getName() + "]" + ); + } + } + return parameter; + } + + @SuppressWarnings({ "unchecked" }) + public TypedQuery setParameter(String name, Calendar calendar, TemporalType temporalType) { + Parameter parameter = resolveExplicitCriteriaParameterName( name ); + if ( ! Calendar.class.isAssignableFrom( parameter.getParameterType() ) ) { + throw new IllegalArgumentException( + "Named parameter [" + name + "] type mismatch; expecting [" + + Calendar.class.getName() + "], found [" + + parameter.getParameterType().getName() + "]" + ); + } + setParameter( parameter, calendar, temporalType ); + return this; + } + + @SuppressWarnings({ "unchecked" }) + public TypedQuery setParameter(String name, Date date, TemporalType temporalType) { + Parameter parameter = resolveExplicitCriteriaParameterName( name ); + if ( ! Date.class.isAssignableFrom( parameter.getParameterType() ) ) { + throw new IllegalArgumentException( + "Named parameter [" + name + "] type mismatch; expecting [" + + Date.class.getName() + "], found [" + + parameter.getParameterType().getName() + "]" + ); + } + setParameter( parameter, date, temporalType ); + return this; + } + + + // unsupported stuff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public int executeUpdate() { + throw new IllegalArgumentException( "Criteria queries do not support update queries" ); + } + + public TypedQuery setParameter(int i, Object o) { + throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); + } + + public TypedQuery setParameter(int i, Calendar calendar, TemporalType temporalType) { + throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); + } + + public TypedQuery setParameter(int i, Date date, TemporalType temporalType) { + throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); + } + + public Object getParameterValue(int position) { + throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); + } + + public Parameter getParameter(int position) { + throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); + } + + public Parameter getParameter(int position, Class type) { + throw new IllegalArgumentException( "Criteria queries do not support positioned parameters" ); + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/ImplicitParameterBinding.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/ImplicitParameterBinding.java new file mode 100644 index 0000000000..9a24c7e721 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/ImplicitParameterBinding.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria.compile; + +import javax.persistence.TypedQuery; + +/** + * Used to describe implicit (not defined in criteria query) parameters. + * + * @author Steve Ebersole + */ +public interface ImplicitParameterBinding { + /** + * Retrieve the generated name of the implicit parameter. + * + * @return The parameter name. + */ + public String getParameterName(); + + /** + * Get the java type of the "thing" that led to the implicit parameter. Used from + * {@link org.hibernate.ejb.HibernateEntityManagerImplementor.Options#getNamedParameterExplicitTypes()} + * in determining "guessed type" overriding. + * + * @return The java type + */ + public Class getJavaType(); + + /** + * Bind the implicit parameter's value to the JPA query. + * + * @param typedQuery The JPA query. + */ + public void bind(TypedQuery typedQuery); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/InterpretedParameterMetadata.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/InterpretedParameterMetadata.java new file mode 100644 index 0000000000..2d35921177 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/InterpretedParameterMetadata.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria.compile; + +import javax.persistence.criteria.ParameterExpression; +import java.util.List; +import java.util.Map; + +/** + * @author Steve Ebersole + */ +public interface InterpretedParameterMetadata { + public Map,String> explicitParameterMapping(); + public Map> explicitParameterNameMapping(); + public List implicitParameterBindings(); + public Map implicitParameterTypes(); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/RenderingContext.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/RenderingContext.java new file mode 100644 index 0000000000..2fc15c78c5 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/compile/RenderingContext.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria.compile; + +import javax.persistence.criteria.ParameterExpression; + +/** + * Used to provide a context and services to the rendering. + * + * @author Steve Ebersole + */ +public interface RenderingContext { + /** + * Generate a correlation name. + * + * @return The generated correlation name + */ + public String generateAlias(); + + /** + * Register parameters explicitly encountered in the criteria query. + * + * @param criteriaQueryParameter The parameter expression + * + * @return The JPA-QL parameter name + */ + public String registerExplicitParameter(ParameterExpression criteriaQueryParameter); + + /** + * Register a parameter that was not part of the criteria query (at least not as a parameter). + * + * @param literal The literal value + * @param javaType The java type as whcih to handle the literal value. + * + * @return The JPA-QL parameter name + */ + public String registerLiteralParameterBinding(Object literal, Class javaType); + + /** + * Given a java type, determine the proper cast type name. + * + * @param javaType The java type. + * + * @return The cast type name. + */ + public String getCastType(Class javaType); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/BinaryArithmeticOperation.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/BinaryArithmeticOperation.java index f2e95e7453..b844c91fcf 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/BinaryArithmeticOperation.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/BinaryArithmeticOperation.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.predicate.ImplicitNumericExpressionTypeDeterminer; /** @@ -228,14 +228,14 @@ public class BinaryArithmeticOperation Helper.possibleParameter( getLeftHandOperand(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return getOperator().apply( ( (Renderable) getLeftHandOperand() ).render( renderingContext ), ( (Renderable) getRightHandOperand() ).render( renderingContext ) ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CoalesceExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CoalesceExpression.java index 457f417956..0b2cc368a1 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CoalesceExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CoalesceExpression.java @@ -30,9 +30,9 @@ import javax.persistence.criteria.CriteriaBuilder.Coalesce; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models an ANSI SQL COALESCE expression. COALESCE is a specialized CASE statement. @@ -83,7 +83,7 @@ public class CoalesceExpression extends ExpressionImpl implements Coalesce } } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { StringBuilder buffer = new StringBuilder( "coalesce(" ); String sep = ""; for ( Expression expression : getExpressions() ) { @@ -94,7 +94,7 @@ public class CoalesceExpression extends ExpressionImpl implements Coalesce return buffer.append( ")" ).toString(); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CompoundSelectionImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CompoundSelectionImpl.java index a6b343a883..7381192628 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CompoundSelectionImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CompoundSelectionImpl.java @@ -31,11 +31,11 @@ import javax.persistence.criteria.CompoundSelection; import javax.persistence.criteria.Selection; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; import org.hibernate.ejb.criteria.TupleElementImplementor; import org.hibernate.ejb.criteria.ValueHandlerFactory; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * The Hibernate implementation of the JPA {@link CompoundSelection} @@ -89,7 +89,7 @@ public class CompoundSelectionImpl } } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { StringBuilder buff = new StringBuilder(); if ( isConstructor ) { buff.append( "new " ).append( getJavaType().getName() ).append( '(' ); @@ -106,7 +106,7 @@ public class CompoundSelectionImpl return buff.toString(); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ConcatExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ConcatExpression.java index 6f70ae386f..3a96d8cff7 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ConcatExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ConcatExpression.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * A string concatenation. @@ -80,13 +80,13 @@ public class ConcatExpression extends ExpressionImpl implements Serializ Helper.possibleParameter( getString2(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return ( (Renderable) getString1() ).render( renderingContext ) + " || " + ( (Renderable) getString2() ).render( renderingContext ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java index d8276e7242..e83652f82b 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java @@ -26,8 +26,8 @@ package org.hibernate.ejb.criteria.expression; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * TODO : javadoc @@ -43,12 +43,12 @@ public class EntityTypeExpression extends ExpressionImpl implements Serial // nothign to do } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { // todo : is it valid for this to get rendered into the query itself? throw new IllegalArgumentException( "Unexpected call on EntityTypeExpression#render" ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java index 602e8d412d..32e8ce792f 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.metamodel.ListAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** @@ -58,13 +58,13 @@ public class ListIndexExpression extends ExpressionImpl implements Seri // nothing to do } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "index(" + origin.getPathIdentifier() + '.' + getListAttribute().getName() + ")"; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java index be0cc371fa..db65e461dc 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java @@ -26,9 +26,9 @@ package org.hibernate.ejb.criteria.expression; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.ValueHandlerFactory; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Represents a literal expression. @@ -62,7 +62,7 @@ public class LiteralExpression extends ExpressionImpl implements Serializa } @SuppressWarnings({ "unchecked" }) - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { if ( ValueHandlerFactory.isNumeric( literal ) ) { return ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() ).render( literal ); } @@ -73,7 +73,7 @@ public class LiteralExpression extends ExpressionImpl implements Serializa } @SuppressWarnings({ "unchecked" }) - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { // some drivers/servers do not like parameters in the select clause final ValueHandlerFactory.ValueHandler handler = ValueHandlerFactory.determineAppropriateHandler( literal.getClass() ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java index 20da99aae1..3bdef2ba4a 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java @@ -29,10 +29,10 @@ import javax.persistence.criteria.Expression; import javax.persistence.metamodel.MapAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.PathImplementor; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * TODO : javadoc @@ -64,16 +64,16 @@ public class MapEntryExpression // none to register } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { // don't think this is valid outside of select clause... throw new IllegalStateException( "illegal reference to map entry outside of select clause." ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return "entry(" + path( renderingContext ) + ")"; } - private String path(CriteriaQueryCompiler.RenderingContext renderingContext) { + private String path(RenderingContext renderingContext) { return origin.getPathIdentifier() + '.' + ( (Renderable) getAttribute() ).renderProjection( renderingContext ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullLiteralExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullLiteralExpression.java index e7054b502f..7034d05d5e 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullLiteralExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullLiteralExpression.java @@ -26,8 +26,8 @@ package org.hibernate.ejb.criteria.expression; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Represents a NULLliteral expression. @@ -43,11 +43,11 @@ public class NullLiteralExpression extends ExpressionImpl implements Seria // nothing to do } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "null"; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } \ No newline at end of file diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullifExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullifExpression.java index 71ff07cb50..b375326905 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullifExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/NullifExpression.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models an ANSI SQL NULLIF expression. NULLIF is a specialized CASE statement. @@ -77,7 +77,7 @@ public class NullifExpression extends ExpressionImpl implements Serializab Helper.possibleParameter( getSecondaryExpression(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "nullif(" + ( (Renderable) getPrimaryExpression() ).render( renderingContext ) + ',' @@ -85,7 +85,7 @@ public class NullifExpression extends ExpressionImpl implements Serializab + ")"; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java index ab934e9a93..e8df312450 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java @@ -27,8 +27,8 @@ import java.io.Serializable; import javax.persistence.criteria.ParameterExpression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Defines a parameter specification, or the information about a parameter (where it occurs, what is @@ -84,12 +84,12 @@ public class ParameterExpressionImpl registry.registerParameter( this ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { final String jpaqlParamName = renderingContext.registerExplicitParameter( this ); return ':' + jpaqlParamName; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java index 51ba3a2338..28add73ac7 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java @@ -26,8 +26,8 @@ package org.hibernate.ejb.criteria.expression; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.path.AbstractPathImpl; /** @@ -47,11 +47,11 @@ public class PathTypeExpression extends ExpressionImpl implements Serializ // nothing to do } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "type(" + pathImpl.getPathIdentifier() + ")"; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SearchedCaseExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SearchedCaseExpression.java index 5bfc10a8c5..835c658f32 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SearchedCaseExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SearchedCaseExpression.java @@ -30,9 +30,9 @@ import javax.persistence.criteria.CriteriaBuilder.Case; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models what ANSI SQL terms a searched case expression. This is a CASE expression @@ -130,7 +130,7 @@ public class SearchedCaseExpression } } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { StringBuilder caseStatement = new StringBuilder( "case" ); for ( WhenClause whenClause : getWhenClauses() ) { caseStatement.append( " when " ) @@ -144,7 +144,7 @@ public class SearchedCaseExpression return caseStatement.toString(); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SimpleCaseExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SimpleCaseExpression.java index 49953db624..cf283898f2 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SimpleCaseExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SimpleCaseExpression.java @@ -30,9 +30,9 @@ import javax.persistence.criteria.CriteriaBuilder.SimpleCase; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models what ANSI SQL terms a simple case statement. This is a CASE expression in the form

@@ -138,7 +138,7 @@ public class SimpleCaseExpression
 		Helper.possibleParameter( getOtherwiseResult(), registry );
 	}
 
-	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String render(RenderingContext renderingContext) {
 		StringBuilder caseExpr = new StringBuilder();
 		caseExpr.append( "case " )
 				.append(  ( (Renderable) getExpression() ).render( renderingContext ) )
@@ -154,7 +154,7 @@ public class SimpleCaseExpression
 		return caseExpr.toString();
 	}
 
-	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String renderProjection(RenderingContext renderingContext) {
 		return render( renderingContext );
 	}
 }
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java
index c3dcf677ef..c140db5dcb 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java
@@ -27,8 +27,8 @@ import java.io.Serializable;
 import java.util.Collection;
 
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
-import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
 import org.hibernate.ejb.criteria.ParameterRegistry;
+import org.hibernate.ejb.criteria.compile.RenderingContext;
 import org.hibernate.ejb.criteria.path.PluralAttributePath;
 
 /**
@@ -57,11 +57,11 @@ public class SizeOfCollectionExpression
 		// nothing to do
 	}
 
-	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String render(RenderingContext renderingContext) {
 		return "size(" + getCollectionPath().render( renderingContext ) + ")";
 	}
 
-	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String renderProjection(RenderingContext renderingContext) {
 		return render( renderingContext );
 	}
 }
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SubqueryComparisonModifierExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SubqueryComparisonModifierExpression.java
index c6954d6540..8b63e30b97 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SubqueryComparisonModifierExpression.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SubqueryComparisonModifierExpression.java
@@ -27,9 +27,9 @@ import java.io.Serializable;
 import javax.persistence.criteria.Subquery;
 
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
-import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
 import org.hibernate.ejb.criteria.ParameterRegistry;
 import org.hibernate.ejb.criteria.Renderable;
+import org.hibernate.ejb.criteria.compile.RenderingContext;
 
 /**
  * Represents a {@link Modifier#ALL}, {@link Modifier#ANY}, {@link Modifier#SOME} modifier appplied to a subquery as
@@ -84,11 +84,11 @@ public class SubqueryComparisonModifierExpression
 		// nothing to do (the subquery should be handled directly, and the modified itself is not parameterized)
 	}
 
-	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String render(RenderingContext renderingContext) {
 		return getModifier().rendered() + ( (Renderable) getSubquery() ).render( renderingContext );
 	}
 
-	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String renderProjection(RenderingContext renderingContext) {
 		return render( renderingContext );
 	}
 }
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/UnaryArithmeticOperation.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/UnaryArithmeticOperation.java
index b62253eb9c..d3fabe797b 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/UnaryArithmeticOperation.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/UnaryArithmeticOperation.java
@@ -27,9 +27,9 @@ import java.io.Serializable;
 import javax.persistence.criteria.Expression;
 
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
-import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
 import org.hibernate.ejb.criteria.ParameterRegistry;
 import org.hibernate.ejb.criteria.Renderable;
+import org.hibernate.ejb.criteria.compile.RenderingContext;
 
 /**
  * Models unary arithmetic operation (unary plus and unary minus).
@@ -75,12 +75,12 @@ public class UnaryArithmeticOperation
 		Helper.possibleParameter( getOperand(), registry );
 	}
 
-	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String render(RenderingContext renderingContext) {
 		return ( getOperation() == Operation.UNARY_MINUS ? '-' : '+' )
 				+ ( (Renderable) getOperand() ).render( renderingContext );
 	}
 
-	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+	public String renderProjection(RenderingContext renderingContext) {
 		return render( renderingContext );
 	}
 }
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AbsFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AbsFunction.java
index 0c68b4c809..f2d5df34eb 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AbsFunction.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AbsFunction.java
@@ -41,4 +41,9 @@ public class AbsFunction
 	public AbsFunction(CriteriaBuilderImpl criteriaBuilder, Expression expression) {
 		super( criteriaBuilder, expression.getJavaType(), NAME, expression );
 	}
+
+	@Override
+	protected boolean isStandardJpaFunction() {
+		return true;
+	}
 }
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AggregationFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AggregationFunction.java
index d4a8a5fa35..7d9379cb65 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AggregationFunction.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AggregationFunction.java
@@ -29,7 +29,7 @@ import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Root;
 
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
-import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.compile.RenderingContext;
 import org.hibernate.ejb.criteria.expression.LiteralExpression;
 
 /**
@@ -79,6 +79,11 @@ public class AggregationFunction
 		return true;
 	}
 
+	@Override
+	protected boolean isStandardJpaFunction() {
+		return true;
+	}
+
 	/**
 	 * Implementation of a COUNT function providing convenience in construction.
 	 * 

@@ -96,9 +101,10 @@ public class AggregationFunction } @Override - protected void renderArguments( StringBuilder buffer, - CriteriaQueryCompiler.RenderingContext renderingContext ) { - if (isDistinct()) buffer.append("distinct "); + protected void renderArguments(StringBuilder buffer, RenderingContext renderingContext) { + if ( isDistinct() ) { + buffer.append("distinct "); + } else { // If function specifies a single non-distinct entity with ID, its alias would normally be rendered, which ends up // converting to the column(s) associated with the entity's ID in the rendered SQL. However, some DBs don't support diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/BasicFunctionExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/BasicFunctionExpression.java index 9edaac695b..c2b782c1a6 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/BasicFunctionExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/BasicFunctionExpression.java @@ -26,8 +26,8 @@ package org.hibernate.ejb.criteria.expression.function; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.ExpressionImpl; /** @@ -65,11 +65,11 @@ public class BasicFunctionExpression // nothing to do here... } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return getFunctionName() + "()"; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/CastFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/CastFunction.java index 537bd2e932..5771e647d6 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/CastFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/CastFunction.java @@ -26,8 +26,8 @@ package org.hibernate.ejb.criteria.expression.function; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.ExpressionImpl; /** @@ -63,7 +63,7 @@ public class CastFunction } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return CAST_NAME + '(' + castSource.render( renderingContext ) + " as " + diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LengthFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LengthFunction.java index c105685acd..3417ad416b 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LengthFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LengthFunction.java @@ -38,6 +38,11 @@ public class LengthFunction implements Serializable { public static final String NAME = "length"; + @Override + protected boolean isStandardJpaFunction() { + return true; + } + public LengthFunction(CriteriaBuilderImpl criteriaBuilder, Expression value) { super( criteriaBuilder, Integer.class, NAME, value ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LocateFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LocateFunction.java index 6228da7a19..c7cc228fb3 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LocateFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LocateFunction.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.LiteralExpression; /** @@ -102,7 +102,7 @@ public class LocateFunction } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { StringBuilder buffer = new StringBuilder(); buffer.append( "locate(" ) .append( ( (Renderable) getPattern() ).render( renderingContext ) ) diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LowerFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LowerFunction.java index 3a5cd365d6..77e902944d 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LowerFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/LowerFunction.java @@ -41,4 +41,9 @@ public class LowerFunction public LowerFunction(CriteriaBuilderImpl criteriaBuilder, Expression string) { super( criteriaBuilder, String.class, NAME, string ); } + + @Override + protected boolean isStandardJpaFunction() { + return true; + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/ParameterizedFunctionExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/ParameterizedFunctionExpression.java index 39ae92ede5..94f3733d49 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/ParameterizedFunctionExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/ParameterizedFunctionExpression.java @@ -29,10 +29,10 @@ import java.util.List; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterContainer; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.LiteralExpression; /** @@ -44,7 +44,29 @@ public class ParameterizedFunctionExpression extends BasicFunctionExpression implements FunctionExpression { + public static List STANDARD_JPA_FUNCTION_NAMES = Arrays.asList( + // 4.6.17.2.1 + "CONCAT", + "SUBSTRING", + "TRIM", + "UPPER", + "LOWER", + "LOCATE", + "LENGTH", + //4.6.17.2.2 + "ABS", + "SQRT", + "MOD", + "SIZE", + "INDEX", + // 4.6.17.2.3 + "CURRENT_DATE", + "CURRENT_TIME", + "CURRENT_TIMESTAMP" + ); + private final List> argumentExpressions; + private final boolean isStandardJpaFunction; public ParameterizedFunctionExpression( CriteriaBuilderImpl criteriaBuilder, @@ -53,6 +75,7 @@ public class ParameterizedFunctionExpression List> argumentExpressions) { super( criteriaBuilder, javaType, functionName ); this.argumentExpressions = argumentExpressions; + this.isStandardJpaFunction = STANDARD_JPA_FUNCTION_NAMES.contains( functionName.toUpperCase() ); } public ParameterizedFunctionExpression( @@ -62,14 +85,11 @@ public class ParameterizedFunctionExpression Expression... argumentExpressions) { super( criteriaBuilder, javaType, functionName ); this.argumentExpressions = Arrays.asList( argumentExpressions ); + this.isStandardJpaFunction = STANDARD_JPA_FUNCTION_NAMES.contains( functionName.toUpperCase() ); } - protected static List> wrapAsLiterals(CriteriaBuilderImpl criteriaBuilder, Object... literalArguments) { - List> arguments = new ArrayList>( properSize( literalArguments.length) ); - for ( Object o : literalArguments ) { - arguments.add( new LiteralExpression( criteriaBuilder, o ) ); - } - return arguments; + protected boolean isStandardJpaFunction() { + return isStandardJpaFunction; } protected static int properSize(int number) { @@ -90,21 +110,28 @@ public class ParameterizedFunctionExpression } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { - StringBuilder buffer = new StringBuilder() - .append( "function('" ) - .append( getFunctionName() ) - .append( "', " ); + public String render(RenderingContext renderingContext) { + StringBuilder buffer = new StringBuilder(); + if ( isStandardJpaFunction() ) { + buffer.append( getFunctionName() ) + .append( "(" ); + } + else { + buffer.append( "function('" ) + .append( getFunctionName() ) + .append( "', " ); + } renderArguments( buffer, renderingContext ); buffer.append( ')' ); return buffer.toString(); } - protected void renderArguments(StringBuilder buffer, CriteriaQueryCompiler.RenderingContext renderingContext) { + protected void renderArguments(StringBuilder buffer, RenderingContext renderingContext) { String sep = ""; for ( Expression argument : argumentExpressions ) { buffer.append( sep ).append( ( (Renderable) argument ).render( renderingContext ) ); sep = ", "; } } + } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SqrtFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SqrtFunction.java index 1a007dae48..0f4caee2cc 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SqrtFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SqrtFunction.java @@ -41,4 +41,9 @@ public class SqrtFunction public SqrtFunction(CriteriaBuilderImpl criteriaBuilder, Expression expression) { super( criteriaBuilder, Double.class, NAME, expression ); } + + @Override + protected boolean isStandardJpaFunction() { + return true; + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SubstringFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SubstringFunction.java index a3b0976adf..8723ffa72c 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SubstringFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SubstringFunction.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.LiteralExpression; /** @@ -108,7 +108,7 @@ public class SubstringFunction Helper.possibleParameter( getValue(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { StringBuilder buffer = new StringBuilder(); buffer.append( "substring(" ) .append( ( (Renderable) getValue() ).render( renderingContext ) ) diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/TrimFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/TrimFunction.java index 4263ef7389..b4e5b61c27 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/TrimFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/TrimFunction.java @@ -28,9 +28,9 @@ import javax.persistence.criteria.CriteriaBuilder.Trimspec; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.LiteralExpression; /** @@ -117,7 +117,7 @@ public class TrimFunction } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return new StringBuilder() .append( "trim(" ) .append( trimspec.name() ) diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/UpperFunction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/UpperFunction.java index 311b64c389..f346e958c8 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/UpperFunction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/UpperFunction.java @@ -41,4 +41,9 @@ public class UpperFunction public UpperFunction(CriteriaBuilderImpl criteriaBuilder, Expression string) { super( criteriaBuilder, String.class, NAME, string ); } + + @Override + protected boolean isStandardJpaFunction() { + return true; + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java index 7ced7e2fbc..38df7186a2 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java @@ -48,7 +48,6 @@ import javax.persistence.metamodel.Type; import org.hibernate.ejb.criteria.BasicPathUsageException; import org.hibernate.ejb.criteria.CollectionJoinImplementor; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; import org.hibernate.ejb.criteria.JoinImplementor; @@ -56,6 +55,7 @@ import org.hibernate.ejb.criteria.ListJoinImplementor; import org.hibernate.ejb.criteria.MapJoinImplementor; import org.hibernate.ejb.criteria.PathSource; import org.hibernate.ejb.criteria.SetJoinImplementor; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Convenience base class for various {@link javax.persistence.criteria.From} implementations. @@ -96,7 +96,7 @@ public abstract class AbstractFromImpl } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { if ( getAlias() == null ) { if ( isCorrelated() ) { setAlias( getCorrelationParent().getAlias() ); @@ -108,13 +108,13 @@ public abstract class AbstractFromImpl } @Override - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { prepareAlias( renderingContext ); return getAlias(); } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return renderProjection( renderingContext ); } @@ -227,7 +227,7 @@ public abstract class AbstractFromImpl protected abstract boolean canBeJoinSource(); - private RuntimeException illegalJoin() { + protected RuntimeException illegalJoin() { return new IllegalArgumentException( "Collection of values [" + getPathIdentifier() + "] cannot be source of a join" ); @@ -521,7 +521,7 @@ public abstract class AbstractFromImpl return canBeJoinSource(); } - private RuntimeException illegalFetch() { + protected RuntimeException illegalFetch() { return new IllegalArgumentException( "Collection of values [" + getPathIdentifier() + "] cannot be source of a fetch" ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java index c07b23d135..3fd5152f8d 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java @@ -31,11 +31,11 @@ import javax.persistence.metamodel.Attribute; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; import org.hibernate.ejb.criteria.JoinImplementor; import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.predicate.AbstractPredicateImpl; /** @@ -89,7 +89,7 @@ public abstract class AbstractJoinImpl } @Override - public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderTableExpression(RenderingContext renderingContext) { prepareAlias( renderingContext ); ( (FromImplementor) getParent() ).prepareAlias( renderingContext ); StringBuilder tableExpression = new StringBuilder(); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java index 310ae79bcc..de54b6ac32 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java @@ -35,10 +35,10 @@ import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SingularAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.PathImplementor; import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.ExpressionImpl; import org.hibernate.ejb.criteria.expression.PathTypeExpression; @@ -230,7 +230,7 @@ public abstract class AbstractPathImpl } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // Make sure we delegate up to our source (eventually up to the path root) to // prepare the path properly. PathSource source = getPathSource(); @@ -240,7 +240,7 @@ public abstract class AbstractPathImpl } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { PathSource source = getPathSource(); if ( source != null ) { source.prepareAlias( renderingContext ); @@ -252,7 +252,7 @@ public abstract class AbstractPathImpl } @Override - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java index da330c5d98..3784640546 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java @@ -32,11 +32,11 @@ import javax.persistence.metamodel.CollectionAttribute; import org.hibernate.ejb.criteria.CollectionJoinImplementor; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; import org.hibernate.ejb.criteria.PathImplementor; import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models a join based on a plural association attribute. @@ -105,7 +105,7 @@ public class CollectionAttributeJoin original.criteriaBuilder(), treatAsType, original.getPathSource(), - (CollectionAttribute) original.getAttribute(), + (CollectionAttribute) original.getAttribute(), original.getJoinType() ); this.original = original; @@ -118,12 +118,12 @@ public class CollectionAttributeJoin } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // do nothing... } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java index 20b9c5aafc..6acd729ed0 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java @@ -31,12 +31,12 @@ import javax.persistence.criteria.Predicate; import javax.persistence.metamodel.ListAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; import org.hibernate.ejb.criteria.ListJoinImplementor; import org.hibernate.ejb.criteria.PathImplementor; import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.ListIndexExpression; /** @@ -113,7 +113,7 @@ public class ListAttributeJoin original.criteriaBuilder(), treatAsType, original.getPathSource(), - (ListAttribute) original.getAttribute(), + (ListAttribute) original.getAttribute(), original.getJoinType() ); this.original = original; @@ -126,12 +126,12 @@ public class ListAttributeJoin } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // do nothing... } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java index 00794d01a6..1dec484379 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java @@ -32,12 +32,12 @@ import javax.persistence.criteria.Predicate; import javax.persistence.metamodel.MapAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; import org.hibernate.ejb.criteria.MapJoinImplementor; import org.hibernate.ejb.criteria.PathImplementor; import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.MapEntryExpression; /** @@ -134,7 +134,7 @@ public class MapAttributeJoin original.criteriaBuilder(), treatAsType, original.getPathSource(), - (MapAttribute) original.getAttribute(), + (MapAttribute) original.getAttribute(), original.getJoinType() ); this.original = original; @@ -147,12 +147,12 @@ public class MapAttributeJoin } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // do nothing... } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java index 7977175021..4a35a385e0 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java @@ -28,9 +28,9 @@ import javax.persistence.criteria.Root; import javax.persistence.metamodel.EntityType; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Hibernate implementation of the JPA {@link Root} contract @@ -39,12 +39,16 @@ import org.hibernate.ejb.criteria.FromImplementor; */ public class RootImpl extends AbstractFromImpl implements Root, Serializable { private final EntityType entityType; + private final boolean allowJoins; - public RootImpl( - CriteriaBuilderImpl criteriaBuilder, - EntityType entityType) { + public RootImpl(CriteriaBuilderImpl criteriaBuilder, EntityType entityType) { + this( criteriaBuilder, entityType, true ); + } + + public RootImpl(CriteriaBuilderImpl criteriaBuilder, EntityType entityType, boolean allowJoins) { super( criteriaBuilder, entityType.getJavaType() ); this.entityType = entityType; + this.allowJoins = allowJoins; } public EntityType getEntityType() { @@ -67,10 +71,22 @@ public class RootImpl extends AbstractFromImpl implements Root, Seria @Override protected boolean canBeJoinSource() { - return true; + return allowJoins; } - public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) { + @Override + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + protected RuntimeException illegalJoin() { + return allowJoins ? super.illegalJoin() : new IllegalArgumentException( "UPDATE/DELETE criteria queries cannot define joins" ); + } + + @Override + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + protected RuntimeException illegalFetch() { + return allowJoins ? super.illegalFetch() : new IllegalArgumentException( "UPDATE/DELETE criteria queries cannot define fetches" ); + } + + public String renderTableExpression(RenderingContext renderingContext) { prepareAlias( renderingContext ); return getModel().getName() + " as " + getAlias(); } @@ -81,13 +97,13 @@ public class RootImpl extends AbstractFromImpl implements Root, Seria } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { prepareAlias( renderingContext ); return getAlias(); } @Override - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } @@ -115,12 +131,12 @@ public class RootImpl extends AbstractFromImpl implements Root, Seria } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // do nothing... } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "treat(" + original.getAlias() + " as " + treatAsType.getName() + ")"; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java index 7a1849bc77..5b4714be4f 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java @@ -31,12 +31,12 @@ import javax.persistence.criteria.Predicate; import javax.persistence.metamodel.SetAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; import org.hibernate.ejb.criteria.PathImplementor; import org.hibernate.ejb.criteria.PathSource; import org.hibernate.ejb.criteria.SetJoinImplementor; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models a join based on a set-style plural association attribute. @@ -110,7 +110,7 @@ public class SetAttributeJoin original.criteriaBuilder(), treatAsType, original.getPathSource(), - (SetAttribute) original.getAttribute(), + (SetAttribute) original.getAttribute(), original.getJoinType() ); this.original = original; @@ -123,12 +123,12 @@ public class SetAttributeJoin } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // do nothing... } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java index 0941d44d45..95a442442c 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java @@ -29,10 +29,10 @@ import javax.persistence.metamodel.Bindable; import javax.persistence.metamodel.SingularAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; import org.hibernate.ejb.criteria.FromImplementor; import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models a join based on a singular attribute @@ -117,12 +117,12 @@ public class SingularAttributeJoin extends AbstractJoinImpl { } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // do nothing... } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java index 1fa3863b51..aeee94870c 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java @@ -32,8 +32,8 @@ import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.SingularAttribute; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models a path for a {@link SingularAttribute} generally obtained from a @@ -109,7 +109,7 @@ public class SingularAttributePath extends AbstractPathImpl implements Ser original.criteriaBuilder(), treatAsType, original.getPathSource(), - (SingularAttribute) original.getAttribute() + (SingularAttribute) original.getAttribute() ); this.original = original; this.treatAsType = treatAsType; @@ -121,12 +121,12 @@ public class SingularAttributePath extends AbstractPathImpl implements Ser } @Override - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + public void prepareAlias(RenderingContext renderingContext) { // do nothing... } @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BetweenPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BetweenPredicate.java index 382af3ff23..37c642a4c6 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BetweenPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BetweenPredicate.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models a BETWEEN {@link javax.persistence.criteria.Predicate}. @@ -85,7 +85,7 @@ public class BetweenPredicate Helper.possibleParameter( getUpperBound(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { final String operator = isNegated() ? " not between " : " between "; return ( (Renderable) getExpression() ).render( renderingContext ) + operator @@ -94,7 +94,7 @@ public class BetweenPredicate + ( (Renderable) getUpperBound() ).render( renderingContext ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java index a0842ff782..af7aa0d197 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Predicate to assert the explicit value of a boolean expression:

    @@ -74,7 +74,7 @@ public class BooleanAssertionPredicate /** * {@inheritDoc} */ - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { final String operator = isNegated() ? " <> " : " = "; final String assertionLiteral = assertedValue ? "true" : "false"; @@ -86,7 +86,7 @@ public class BooleanAssertionPredicate /** * {@inheritDoc} */ - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanExpressionPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanExpressionPredicate.java index 79a848a1f2..e6af9f0bbd 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanExpressionPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanExpressionPredicate.java @@ -28,9 +28,9 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Defines a {@link Predicate} used to wrap an {@link Expression Expression<Boolean>}. @@ -60,11 +60,11 @@ public class BooleanExpressionPredicate Helper.possibleParameter(expression, registry); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return ( (Renderable) getExpression() ).render( renderingContext ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanStaticAssertionPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanStaticAssertionPredicate.java index 24ada02831..11933aa932 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanStaticAssertionPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanStaticAssertionPredicate.java @@ -26,8 +26,8 @@ package org.hibernate.ejb.criteria.predicate; import java.io.Serializable; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Predicate used to assert a static boolean condition. @@ -60,7 +60,7 @@ public class BooleanStaticAssertionPredicate /** * {@inheritDoc} */ - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { boolean isTrue = getAssertedValue(); if ( isNegated() ) { isTrue = !isTrue; @@ -74,7 +74,7 @@ public class BooleanStaticAssertionPredicate /** * {@inheritDoc} */ - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ComparisonPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ComparisonPredicate.java index 09809a4eae..9d6d258496 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ComparisonPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ComparisonPredicate.java @@ -27,10 +27,10 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; import org.hibernate.ejb.criteria.ValueHandlerFactory; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.BinaryOperatorExpression; import org.hibernate.ejb.criteria.expression.LiteralExpression; @@ -174,13 +174,13 @@ public class ComparisonPredicate public abstract String rendered(); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return ( (Renderable) getLeftHandOperand() ).render( renderingContext ) + getComparisonOperator().rendered() + ( (Renderable) getRightHandOperand() ).render( renderingContext ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/CompoundPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/CompoundPredicate.java index 874b019010..6721ea0888 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/CompoundPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/CompoundPredicate.java @@ -31,9 +31,9 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * A compound {@link Predicate predicate} is a grouping of other {@link Predicate predicates} in order to convert @@ -114,7 +114,7 @@ public class CompoundPredicate } } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { if ( getExpressions().size() == 0 ) { boolean implicitTrue = getOperator() == BooleanOperator.AND; if ( isNegated() ) { @@ -145,7 +145,7 @@ public class CompoundPredicate : " or "; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExistsPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExistsPredicate.java index 1c81c795b5..45dd18fffb 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExistsPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExistsPredicate.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Subquery; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * Models an EXISTS() predicate @@ -54,12 +54,12 @@ public class ExistsPredicate // nothing to do here } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return ( isNegated() ? "not " : "" ) + "exists " + ( (Renderable) getSubquery() ).render( renderingContext ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExplicitTruthValueCheck.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExplicitTruthValueCheck.java index 5c5cc43568..c554cacb27 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExplicitTruthValueCheck.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/ExplicitTruthValueCheck.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; /** * ANSI-SQL defines TRUE, FALSE and UNKNOWN as truth values. These @@ -66,13 +66,13 @@ public class ExplicitTruthValueCheck Helper.possibleParameter( getBooleanExpression(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return ( (Renderable) getBooleanExpression() ).render( renderingContext ) + " = " + ( getTruthValue() == TruthValue.TRUE ? "true" : "false" ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/InPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/InPredicate.java index 8b07c667ca..5004a84862 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/InPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/InPredicate.java @@ -32,10 +32,10 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.Subquery; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; import org.hibernate.ejb.criteria.ValueHandlerFactory; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.LiteralExpression; /** @@ -158,7 +158,7 @@ public class InPredicate } } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { StringBuilder buffer = new StringBuilder(); buffer.append( ( (Renderable) getExpression() ).render( renderingContext ) ); @@ -188,7 +188,7 @@ public class InPredicate return buffer.toString(); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java index 1bfb158645..fc4da8f4f7 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java @@ -27,8 +27,8 @@ import java.io.Serializable; import java.util.Collection; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.UnaryOperatorExpression; import org.hibernate.ejb.criteria.path.PluralAttributePath; @@ -58,12 +58,12 @@ public class IsEmptyPredicate // nothing to do } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { final String operator = isNegated() ? " is not empty" : " is empty"; return getOperand().render( renderingContext ) + operator; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/LikePredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/LikePredicate.java index 1b72291680..88ca8dc36f 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/LikePredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/LikePredicate.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.LiteralExpression; /** @@ -124,7 +124,7 @@ public class LikePredicate extends AbstractSimplePredicate implements Serializab Helper.possibleParameter( getPattern(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { final String operator = isNegated() ? " not like " : " like "; StringBuilder buffer = new StringBuilder(); buffer.append( ( (Renderable) getMatchExpression() ).render( renderingContext ) ) @@ -137,7 +137,7 @@ public class LikePredicate extends AbstractSimplePredicate implements Serializab return buffer.toString(); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java index 7d1d85c24a..191f9611fc 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java @@ -28,9 +28,9 @@ import java.util.Collection; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.LiteralExpression; import org.hibernate.ejb.criteria.path.PluralAttributePath; @@ -79,13 +79,13 @@ public class MemberOfPredicate> Helper.possibleParameter( getElementExpression(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return ( (Renderable) elementExpression ).render( renderingContext ) + ( isNegated() ? " not" : "" ) + " member of " + getCollectionPath().render( renderingContext ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/NullnessPredicate.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/NullnessPredicate.java index 052093a029..9f649c4331 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/NullnessPredicate.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/NullnessPredicate.java @@ -27,9 +27,9 @@ import java.io.Serializable; import javax.persistence.criteria.Expression; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.Renderable; +import org.hibernate.ejb.criteria.compile.RenderingContext; import org.hibernate.ejb.criteria.expression.UnaryOperatorExpression; /** @@ -67,7 +67,7 @@ public class NullnessPredicate Helper.possibleParameter( getOperand(), registry ); } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String render(RenderingContext renderingContext) { return ( (Renderable) operand ).render( renderingContext ) + check(); } @@ -77,7 +77,7 @@ public class NullnessPredicate : " is null"; } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); } } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/ManipulationCriteriaTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/ManipulationCriteriaTest.java new file mode 100644 index 0000000000..d55651b47d --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/ManipulationCriteriaTest.java @@ -0,0 +1,173 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.ejb.criteria; + +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.criteria.Root; + +import org.hibernate.ejb.metamodel.AbstractMetamodelSpecificTest; +import org.hibernate.ejb.metamodel.Customer; +import org.hibernate.ejb.metamodel.Customer_; + +import org.junit.Test; + +import static org.junit.Assert.fail; + +/** + * @author Steve Ebersole + */ +public class ManipulationCriteriaTest extends AbstractMetamodelSpecificTest { + @Test + public void basicTest() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilder builder = em.getCriteriaBuilder(); + + { + CriteriaDelete deleteCriteria = builder.createCriteriaDelete( Customer.class ); + deleteCriteria.from( Customer.class ); + em.createQuery( deleteCriteria ).executeUpdate(); + } + + { + CriteriaDelete deleteCriteria = builder.createCriteriaDelete( Customer.class ); + Root root = deleteCriteria.from( Customer.class ); + deleteCriteria.where( + builder.equal( + root.get( Customer_.name ), + "Acme" + ) + ); + em.createQuery( deleteCriteria ).executeUpdate(); + } + + { + CriteriaUpdate updateCriteria = builder.createCriteriaUpdate( Customer.class ); + updateCriteria.from( Customer.class ); + updateCriteria.set( Customer_.name, "Acme" ); + em.createQuery( updateCriteria ).executeUpdate(); + } + + { + CriteriaUpdate updateCriteria = builder.createCriteriaUpdate( Customer.class ); + Root root = updateCriteria.from( Customer.class ); + updateCriteria.set( Customer_.name, "Acme" ); + updateCriteria.where( + builder.equal( + root.get( Customer_.name ), + "Acme" + ) + ); + em.createQuery( updateCriteria ).executeUpdate(); + } + + em.getTransaction().commit(); + em.close(); + } + + @Test + public void testNoAssignments() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilder builder = em.getCriteriaBuilder(); + + try { + CriteriaUpdate updateCriteria = builder.createCriteriaUpdate( Customer.class ); + updateCriteria.from( Customer.class ); + em.createQuery( updateCriteria ).executeUpdate(); + fail( "Expecting failure due to no assignments" ); + } + catch (IllegalStateException ise) { + // expected + } + + em.getTransaction().commit(); + em.close(); + } + + @Test + public void testJoinsAndFetchesDisallowed() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilder builder = em.getCriteriaBuilder(); + + { + try { + CriteriaDelete deleteCriteria = builder.createCriteriaDelete( Customer.class ); + Root root = deleteCriteria.from( Customer.class ); + root.join( Customer_.spouse ); + em.createQuery( deleteCriteria ).executeUpdate(); + fail( "Expected failure dues to attempt to join" ); + } + catch (IllegalArgumentException expected) { + } + } + + { + try { + CriteriaDelete deleteCriteria = builder.createCriteriaDelete( Customer.class ); + Root root = deleteCriteria.from( Customer.class ); + root.fetch( Customer_.spouse ); + em.createQuery( deleteCriteria ).executeUpdate(); + fail( "Expected failure dues to attempt to fetch" ); + } + catch (IllegalArgumentException expected) { + } + } + + { + try { + CriteriaUpdate updateCriteria = builder.createCriteriaUpdate( Customer.class ); + Root root = updateCriteria.from( Customer.class ); + root.join( Customer_.spouse ); + em.createQuery( updateCriteria ).executeUpdate(); + fail( "Expected failure dues to attempt to join" ); + } + catch (IllegalArgumentException expected) { + } + } + + { + try { + CriteriaUpdate updateCriteria = builder.createCriteriaUpdate( Customer.class ); + Root root = updateCriteria.from( Customer.class ); + root.fetch( Customer_.spouse ); + em.createQuery( updateCriteria ).executeUpdate(); + fail( "Expected failure dues to attempt to fetch" ); + } + catch (IllegalArgumentException expected) { + } + } + + em.getTransaction().commit(); + em.close(); + + } +}