Package org.hibernate.ejb

Source Code of org.hibernate.ejb.QueryImpl$ParameterImpl

/*
* 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;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Parameter;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import static javax.persistence.TemporalType.DATE;
import static javax.persistence.TemporalType.TIME;
import static javax.persistence.TemporalType.TIMESTAMP;
import javax.persistence.TypedQuery;
import javax.persistence.PersistenceException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.QueryParameterException;
import org.hibernate.TypeMismatchException;
import org.hibernate.SQLQuery;
import org.hibernate.engine.query.NamedParameterDescriptor;
import org.hibernate.engine.query.OrdinalParameterDescriptor;
import org.hibernate.hql.QueryExecutionRequestException;
import org.hibernate.impl.AbstractQueryImpl;

/**
* Hibernate implementation of both the {@link Query} and {@link TypedQuery} contracts.
*
* @author <a href="mailto:gavin@hibernate.org">Gavin King</a>
* @author Emmanuel Bernard
* @author Steve Ebersole
*/
public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> implements TypedQuery<X>, HibernateQuery {
  private static final Logger log = LoggerFactory.getLogger( QueryImpl.class );

  private org.hibernate.Query query;
  private Set<Integer> jpaPositionalIndices;
  private Set<Parameter<?>> parameters;

  public QueryImpl(org.hibernate.Query query, AbstractEntityManagerImpl em) {
    super( em );
    this.query = query;
    extractParameterInfo();
  }

  @SuppressWarnings({ "unchecked" })
  private void extractParameterInfo() {
    if ( ! AbstractQueryImpl.class.isInstance( query ) ) {
      throw new IllegalStateException( "Unknown query type for parameter extraction" );
    }

    HashSet<Parameter<?>> parameters = new HashSet<Parameter<?>>();
    AbstractQueryImpl queryImpl = AbstractQueryImpl.class.cast( query );

    // extract named params
    for ( String name : (Set<String>) queryImpl.getParameterMetadata().getNamedParameterNames() ) {
      final NamedParameterDescriptor descriptor =
          queryImpl.getParameterMetadata().getNamedParameterDescriptor( name );
      final ParameterImpl parameter = new ParameterImpl(
          name,
          descriptor.getExpectedType() == null
              ? null
              : descriptor.getExpectedType().getReturnedClass()
      );
      parameters.add( parameter );
      if ( descriptor.isJpaStyle() ) {
        if ( jpaPositionalIndices == null ) {
          jpaPositionalIndices = new HashSet<Integer>();
        }
        jpaPositionalIndices.add( Integer.valueOf( name ) );
      }
    }

    // extract positional parameters
    for ( int i = 0, max = queryImpl.getParameterMetadata().getOrdinalParameterCount(); i < max; i++ ) {
      final OrdinalParameterDescriptor descriptor =
          queryImpl.getParameterMetadata().getOrdinalParameterDescriptor( i+1 );
      ParameterImpl parameter = new ParameterImpl(
          descriptor.getOrdinalPosition() + 1,
          descriptor.getExpectedType() == null
              ? null
              : descriptor.getExpectedType().getReturnedClass()
      );
      parameters.add( parameter );
      Integer position = descriptor.getOrdinalPosition();
      if ( jpaPositionalIndices != null && jpaPositionalIndices.contains( position ) ) {
        log.warn( "Parameter position [" + position + "] occurred as both JPA and Hibernate positional parameter" );
      }
    }

    this.parameters = java.util.Collections.unmodifiableSet( parameters );
  }

  private static class ParameterImpl implements Parameter {
    private final String name;
    private final Integer position;
    private final Class javaType;

    private ParameterImpl(String name, Class javaType) {
      this.name = name;
      this.javaType = javaType;
      this.position = null;
    }

    private ParameterImpl(Integer position, Class javaType) {
      this.position = position;
      this.javaType = javaType;
      this.name = null;
    }

    public String getName() {
      return name;
    }

    public Integer getPosition() {
      return position;
    }

    public Class getParameterType() {
      return javaType;
    }
  }

  public org.hibernate.Query getHibernateQuery() {
    return query;
  }

  protected int internalExecuteUpdate() {
    return query.executeUpdate();
  }

  protected void applyMaxResults(int maxResults) {
    query.setMaxResults( maxResults );
  }

  protected void applyFirstResult(int firstResult) {
    query.setFirstResult( firstResult );
  }

  protected void applyTimeout(int timeout) {
    query.setTimeout( timeout );
  }

  protected void applyComment(String comment) {
    query.setComment( comment );
  }

  protected void applyFetchSize(int fetchSize) {
    query.setFetchSize( fetchSize );
  }

  protected void applyCacheable(boolean isCacheable) {
    query.setCacheable( isCacheable );
  }

  protected void applyCacheRegion(String regionName) {
    query.setCacheRegion( regionName );
  }

  protected void applyReadOnly(boolean isReadOnly) {
    query.setReadOnly( isReadOnly );
  }

  protected void applyCacheMode(CacheMode cacheMode) {
    query.setCacheMode( cacheMode );
  }

  protected void applyFlushMode(FlushMode flushMode) {
    query.setFlushMode( flushMode );
  }

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings({ "unchecked" })
  public List<X> getResultList() {
    try {
      return (List<X>) query.list();
    }
    catch (QueryExecutionRequestException he) {
      throw new IllegalStateException(he);
    }
    catch( TypeMismatchException e ) {
      throw new IllegalArgumentException(e);
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings({ "unchecked" })
  public X getSingleResult() {
    try {
      boolean mucked = false;
      // IMPL NOTE : the mucking with max results here is attempting to help the user from shooting themselves
      //    in the foot in the case where they have a large query by limiting the query results to 2 max
      //    SQLQuery cannot be safely paginated, leaving the user's choice here.
      if ( getSpecifiedMaxResults() != 1 &&
          ! ( SQLQuery.class.isAssignableFrom( query.getClass() ) ) ) {
        mucked = true;
        query.setMaxResults( 2 ); //avoid OOME if the list is huge
      }
      List<X> result = (List<X>) query.list();
      if ( mucked ) {
        query.setMaxResults( getSpecifiedMaxResults() );
      }

      if ( result.size() == 0 ) {
        NoResultException nre = new NoResultException( "No entity found for query" );
        getEntityManager().handlePersistenceException( nre );
        throw nre;
      }
      else if ( result.size() > 1 ) {
        Set<X> uniqueResult = new HashSet<X>(result);
        if ( uniqueResult.size() > 1 ) {
          NonUniqueResultException nure = new NonUniqueResultException( "result returns more than one elements" );
          getEntityManager().handlePersistenceException( nure );
          throw nure;
        }
        else {
          return uniqueResult.iterator().next();
        }

      }
      else {
        return result.get( 0 );
      }
    }
    catch (QueryExecutionRequestException he) {
      throw new IllegalStateException(he);
    }
    catch( TypeMismatchException e ) {
      throw new IllegalArgumentException(e);
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  public <T> TypedQuery<X> setParameter(Parameter<T> param, T value) {
    if ( ! parameters.contains( param ) ) {
      throw new IllegalArgumentException( "Specified parameter was not found in query" );
    }
    if ( param.getName() != null ) {
      // a named param, for not delegate out.  Eventually delegate *into* this method...
      setParameter( param.getName(), value );
    }
    else {
      setParameter( param.getPosition(), value );
    }
    return this;
  }

  public TypedQuery<X> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
    if ( ! parameters.contains( param ) ) {
      throw new IllegalArgumentException( "Specified parameter was not found in query" );
    }
    if ( param.getName() != null ) {
      // a named param, for not delegate out.  Eventually delegate *into* this method...
      setParameter( param.getName(), value, temporalType );
    }
    else {
      setParameter( param.getPosition(), value, temporalType );
    }
    return this;
  }

  public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
    if ( ! parameters.contains( param ) ) {
      throw new IllegalArgumentException( "Specified parameter was not found in query" );
    }
    if ( param.getName() != null ) {
      // a named param, for not delegate out.  Eventually delegate *into* this method...
      setParameter( param.getName(), value, temporalType );
    }
    else {
      setParameter( param.getPosition(), value, temporalType );
    }
    return this;
  }

  /**
   * {@inheritDoc}
   */
  public TypedQuery<X> setParameter(String name, Object value) {
    try {
      if ( value instanceof Collection ) {
        query.setParameterList( name, (Collection) value );
      }
      else {
        query.setParameter( name, value );
      }
      registerParameterBinding( getParameter( name ), value );
      return this;
    }
    catch (QueryParameterException e) {
      throw new IllegalArgumentException( e );
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  /**
   * {@inheritDoc}
   */
  public TypedQuery<X> setParameter(String name, Date value, TemporalType temporalType) {
    try {
      if ( temporalType == DATE ) {
        query.setDate( name, value );
      }
      else if ( temporalType == TIME ) {
        query.setTime( name, value );
      }
      else if ( temporalType == TIMESTAMP ) {
        query.setTimestamp( name, value );
      }
      registerParameterBinding( getParameter( name ), value );
      return this;
    }
    catch (QueryParameterException e) {
      throw new IllegalArgumentException( e );
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  /**
   * {@inheritDoc}
   */
  public TypedQuery<X> setParameter(String name, Calendar value, TemporalType temporalType) {
    try {
      if ( temporalType == DATE ) {
        query.setCalendarDate( name, value );
      }
      else if ( temporalType == TIME ) {
        throw new IllegalArgumentException( "not yet implemented" );
      }
      else if ( temporalType == TIMESTAMP ) {
        query.setCalendar( name, value );
      }
      registerParameterBinding( getParameter(name), value );
      return this;
    }
    catch (QueryParameterException e) {
      throw new IllegalArgumentException( e );
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  /**
   * {@inheritDoc}
   */
  public TypedQuery<X> setParameter(int position, Object value) {
    try {
      if ( isJpaPositionalParameter( position ) ) {
        this.setParameter( Integer.toString( position ), value );
      }
      else {
        query.setParameter( position - 1, value );
        registerParameterBinding( getParameter( position ), value );
      }
      return this;
    }
    catch (QueryParameterException e) {
      throw new IllegalArgumentException( e );
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  private boolean isJpaPositionalParameter(int position) {
    return jpaPositionalIndices != null && jpaPositionalIndices.contains( position );
  }

  /**
   * {@inheritDoc}
   */
  public TypedQuery<X> setParameter(int position, Date value, TemporalType temporalType) {
    try {
      if ( isJpaPositionalParameter( position ) ) {
        String name = Integer.toString( position );
        this.setParameter( name, value, temporalType );
      }
      else {
        if ( temporalType == DATE ) {
          query.setDate( position - 1, value );
        }
        else if ( temporalType == TIME ) {
          query.setTime( position - 1, value );
        }
        else if ( temporalType == TIMESTAMP ) {
          query.setTimestamp( position - 1, value );
        }
        registerParameterBinding( getParameter( position ), value );
      }
      return this;
    }
    catch (QueryParameterException e) {
      throw new IllegalArgumentException( e );
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  /**
   * {@inheritDoc}
   */
  public TypedQuery<X> setParameter(int position, Calendar value, TemporalType temporalType) {
    try {
      if ( isJpaPositionalParameter( position ) ) {
        String name = Integer.toString( position );
        this.setParameter( name, value, temporalType );
      }
      else {
        if ( temporalType == DATE ) {
          query.setCalendarDate( position - 1, value );
        }
        else if ( temporalType == TIME ) {
          throw new IllegalArgumentException( "not yet implemented" );
        }
        else if ( temporalType == TIMESTAMP ) {
          query.setCalendar( position - 1, value );
        }
        registerParameterBinding( getParameter( position ), value );
      }
      return this;
    }
    catch (QueryParameterException e) {
      throw new IllegalArgumentException( e );
    }
    catch (HibernateException he) {
      throw getEntityManager().convert( he );
    }
  }

  /**
   * {@inheritDoc}
   */
  public Set<Parameter<?>> getParameters() {
    return parameters;
  }

  /**
   * {@inheritDoc}
   */
  public Parameter<?> getParameter(String name) {
    if ( name == null ) {
      throw new IllegalArgumentException( "Name of parameter to locate cannot be null" );
    }
    for ( Parameter parameter : parameters ) {
      if ( name.equals( parameter.getName() ) ) {
        return parameter;
      }
    }
    throw new IllegalArgumentException( "Unable to locate parameter named [" + name + "]" );
  }

  /**
   * {@inheritDoc}
   */
  public Parameter<?> getParameter(int position) {
    if ( isJpaPositionalParameter( position ) ) {
      return getParameter( Integer.toString( position ) );
    }
    else {
      for ( Parameter parameter : parameters ) {
        if ( parameter.getPosition() != null && position == parameter.getPosition() ) {
          return parameter;
        }
      }
      throw new IllegalArgumentException( "Unable to locate parameter with position [" + position + "]" );
    }
  }

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings({ "unchecked" })
  public <T> Parameter<T> getParameter(String name, Class<T> type) {
    Parameter param = getParameter( name );
    if ( param.getParameterType() != null ) {
      // we were able to determine the expected type during analysis, so validate it here
      throw new IllegalArgumentException(
          "Parameter type [" + param.getParameterType().getName() +
              "] is not assignment compatible with requested type [" +
              type.getName() + "]"
      );
    }
    return param;
  }

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings({ "unchecked" })
  public <T> Parameter<T> getParameter(int position, Class<T> type) {
    Parameter param = getParameter( position );
    if ( param.getParameterType() != null ) {
      // we were able to determine the expected type during analysis, so validate it here
      throw new IllegalArgumentException(
          "Parameter type [" + param.getParameterType().getName() +
              "] is not assignment compatible with requested type [" +
              type.getName() + "]"
      );
    }
    return param;
  }

  /**
   * {@inheritDoc}
   */
  public TypedQuery<X> setLockMode(LockModeType lockModeType) {
    // TODO : aye aye aye
    throw new UnsupportedOperationException( "Not yet implemented" );
  }

  /**
   * {@inheritDoc}
   */
  public LockModeType getLockMode() {
    return LockModeType.NONE;
  }

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings({ "unchecked" })
  public <T> T unwrap(Class<T> tClass) {
    if ( org.hibernate.Query.class.isAssignableFrom( tClass ) ) {
      return (T) query;
    }
    else {
      try {
        return (T) this;
      }
      catch ( ClassCastException cce ) {
        PersistenceException pe = new PersistenceException(
            "Unsupported unwrap target type [" + tClass.getName() + "]"
        );
        getEntityManager().handlePersistenceException( pe );
        throw pe;
      }
    }
  }
}
TOP

Related Classes of org.hibernate.ejb.QueryImpl$ParameterImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.