HHH-4203 - Implement JPA 2.0 criteria apis (compiling)
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17772 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
7daebe4992
commit
694a694d5d
|
@ -42,7 +42,7 @@ import javax.persistence.Query;
|
|||
import javax.persistence.TransactionRequiredException;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.QueryBuilder;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
import javax.transaction.Status;
|
||||
|
@ -72,6 +72,7 @@ import org.hibernate.UnresolvableObjectException;
|
|||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.ejb.transaction.JoinableCMTTransaction;
|
||||
import org.hibernate.ejb.util.ConfigurationHelper;
|
||||
import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
@ -148,38 +149,13 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
|||
}
|
||||
}
|
||||
|
||||
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
|
||||
// TODO-STEVE : here is the interpretation/compilation portion.
|
||||
// One option is to build on top of the existing
|
||||
// org.hibernate.loader.custom.CustomQuery infastructure
|
||||
// (which is how native sql queries are implemented e.g.).
|
||||
// If so, then here we could interpret the criteria into
|
||||
// a CustomQuery instance which is passed into the
|
||||
// Query instance returned here. We would then call into
|
||||
// the various SessionImplementor methods for execution
|
||||
// such as #listCustomQuery and #scrollCustomQuery.
|
||||
//
|
||||
// The drawback to this (^^) approach is that CustomQuery +
|
||||
// SessionImplementor combo does not support #executeUpdate
|
||||
// processing...
|
||||
throw new UnsupportedOperationException( "Not yet implemented!" );
|
||||
}
|
||||
private CriteriaQueryCompiler criteriaQueryCompiler;
|
||||
|
||||
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery, Class<T> resultClass) {
|
||||
// TODO-STEVE : here is the interpretation/compilation portion.
|
||||
// One option is to build on top of the existing
|
||||
// org.hibernate.loader.custom.CustomQuery infastructure
|
||||
// (which is how native sql queries are implemented e.g.).
|
||||
// If so, then here we could interpret the criteria into
|
||||
// a CustomQuery instance which is passed into the
|
||||
// Query instance returned here. We would then call into
|
||||
// the various SessionImplementor methods for execution
|
||||
// such as #listCustomQuery and #scrollCustomQuery.
|
||||
//
|
||||
// The drawback to this (^^) approach is that CustomQuery +
|
||||
// SessionImplementor combo does not support #executeUpdate
|
||||
// processing...
|
||||
throw new UnsupportedOperationException( "Not yet implemented!" );
|
||||
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
|
||||
if ( criteriaQueryCompiler == null ) {
|
||||
criteriaQueryCompiler = new CriteriaQueryCompiler( this );
|
||||
}
|
||||
return criteriaQueryCompiler.compile( criteriaQuery );
|
||||
}
|
||||
|
||||
public Query createNamedQuery(String name) {
|
||||
|
@ -481,8 +457,8 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public QueryBuilder getQueryBuilder() {
|
||||
return getEntityManagerFactory().getQueryBuilder();
|
||||
public CriteriaBuilder getCriteriaBuilder() {
|
||||
return getEntityManagerFactory().getCriteriaBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -672,13 +648,13 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
|||
}
|
||||
catch ( SystemException se ) {
|
||||
log.error( "could not determine transaction status", se );
|
||||
//throwPersistenceException will mark the transaction as rollbacked
|
||||
throwPersistenceException(
|
||||
new PersistenceException(
|
||||
"could not determine transaction status in beforeCompletion()",
|
||||
se
|
||||
)
|
||||
PersistenceException pe = new PersistenceException(
|
||||
"could not determine transaction status in beforeCompletion()",
|
||||
se
|
||||
);
|
||||
// handlePersistenceException will mark the transaction as rollbacked
|
||||
handlePersistenceException( pe );
|
||||
throw pe;
|
||||
}
|
||||
catch ( HibernateException he ) {
|
||||
throwPersistenceException( he );
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
//$Id$
|
||||
package org.hibernate.ejb;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
@ -150,7 +148,7 @@ public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> impleme
|
|||
return position;
|
||||
}
|
||||
|
||||
public Class getJavaType() {
|
||||
public Class getParameterType() {
|
||||
return javaType;
|
||||
}
|
||||
}
|
||||
|
@ -521,10 +519,10 @@ public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> impleme
|
|||
@SuppressWarnings({ "unchecked" })
|
||||
public <T> Parameter<T> getParameter(String name, Class<T> type) {
|
||||
Parameter param = getParameter( name );
|
||||
if ( param.getJavaType() != null ) {
|
||||
if ( param.getParameterType() != null ) {
|
||||
// we were able to determine the expected type during analysis, so validate it here
|
||||
throw new IllegalArgumentException(
|
||||
"Parameter type [" + param.getJavaType().getName() +
|
||||
"Parameter type [" + param.getParameterType().getName() +
|
||||
"] is not assignment compatible with requested type [" +
|
||||
type.getName() + "]"
|
||||
);
|
||||
|
@ -538,10 +536,10 @@ public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> impleme
|
|||
@SuppressWarnings({ "unchecked" })
|
||||
public <T> Parameter<T> getParameter(int position, Class<T> type) {
|
||||
Parameter param = getParameter( position );
|
||||
if ( param.getJavaType() != null ) {
|
||||
if ( param.getParameterType() != null ) {
|
||||
// we were able to determine the expected type during analysis, so validate it here
|
||||
throw new IllegalArgumentException(
|
||||
"Parameter type [" + param.getJavaType().getName() +
|
||||
"Parameter type [" + param.getParameterType().getName() +
|
||||
"] is not assignment compatible with requested type [" +
|
||||
type.getName() + "]"
|
||||
);
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.util.Set;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.ParameterExpression;
|
||||
|
||||
import org.hibernate.ejb.HibernateEntityManagerImplementor;
|
||||
|
||||
/**
|
||||
* Compiles a JPA criteria query into an executable {@link TypedQuery}. Its single contract is the {@link #compile}
|
||||
* method.
|
||||
* <p/>
|
||||
* NOTE : This is a temporay 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 {
|
||||
private final HibernateEntityManagerImplementor entityManager;
|
||||
|
||||
public CriteriaQueryCompiler(HibernateEntityManagerImplementor entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
public <T> TypedQuery<T> compile(CriteriaQuery<T> criteriaQuery) {
|
||||
CriteriaQueryImpl<T> criteriaQueryImpl = ( CriteriaQueryImpl<T> ) criteriaQuery;
|
||||
|
||||
criteriaQueryImpl.validate();
|
||||
Set<ParameterExpression<?>> explicitParameters = criteriaQueryImpl.getParameters();
|
||||
// todo : implicit parameter handling (handling literal as param, etc).
|
||||
String jpaqlEquivalent = criteriaQueryImpl.render();
|
||||
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -293,4 +293,44 @@ public class CriteriaQueryImpl<T> extends AbstractNode implements CriteriaQuery<
|
|||
return queryStructure.subquery( subqueryType );
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
// getRoots() is explicitly supposed to return empty if none defined, no need to check for null
|
||||
if ( getRoots().isEmpty() ) {
|
||||
throw new IllegalStateException( "No criteria query roots were specified" );
|
||||
}
|
||||
|
||||
// if there is not an explicit selection, there is an *implicit* selection of the root entity provided only
|
||||
// a single query root was defined.
|
||||
if ( getSelection() == null && !hasImplicitSelection() ) {
|
||||
throw new IllegalStateException( "No explicit selection and an implicit one cold not be determined" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If no explicit selection was defined, we have a condition called an implicit selection if the query specified
|
||||
* a single {@link Root} and the java type of that {@link Root root's} model is the same as this criteria's
|
||||
* {@link #getResultType() result type}.
|
||||
*
|
||||
* @return True if there is an explicit selection; false otherwise.
|
||||
*/
|
||||
private boolean hasImplicitSelection() {
|
||||
if ( getRoots().size() != 1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Root root = getRoots().iterator().next();
|
||||
if ( root.getModel().getJavaType() != returnType ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we get here, the query defined no selection but defined a single root of the same type as the
|
||||
// criteria query return, so we use that as the implicit selection
|
||||
//
|
||||
// todo : should we put an implicit marker in the selection to this fact to make later processing easier?
|
||||
return true;
|
||||
}
|
||||
|
||||
public String render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue