Package org.hibernate.cfg.annotations

Source Code of org.hibernate.cfg.annotations.QueryBinder

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.cfg.annotations;
import java.util.HashMap;
import javax.persistence.LockModeType;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.QueryHint;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.SqlResultSetMappings;

import org.jboss.logging.Logger;

import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.annotations.CacheModeType;
import org.hibernate.annotations.FlushModeType;
import org.hibernate.annotations.QueryHints;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.Mappings;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.LockModeConverter;

/**
* Query binder
*
* @author Emmanuel Bernard
*/
public abstract class QueryBinder {
    private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, QueryBinder.class.getName());

  public static void bindQuery(NamedQuery queryAnn, Mappings mappings, boolean isDefault) {
    if ( queryAnn == null ) return;
    if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
      throw new AnnotationException( "A named query must have a name when used in class or package level" );
    }
    //EJBQL Query
    QueryHint[] hints = queryAnn.hints();
    String queryName = queryAnn.query();
    NamedQueryDefinition queryDefinition = new NamedQueryDefinitionBuilder( queryAnn.name() )
        .setLockOptions( determineLockOptions( queryAnn, hints ) )
        .setQuery( queryName )
        .setCacheable( getBoolean( queryName, "org.hibernate.cacheable", hints ) )
        .setCacheRegion( getString( queryName, "org.hibernate.cacheRegion", hints ) )
        .setTimeout( getTimeout( queryName, hints ) )
        .setFetchSize( getInteger( queryName, "org.hibernate.fetchSize", hints ) )
        .setFlushMode( getFlushMode( queryName, hints ) )
        .setCacheMode( getCacheMode( queryName, hints ) )
        .setReadOnly( getBoolean( queryName, "org.hibernate.readOnly", hints ) )
        .setComment( getString( queryName, "org.hibernate.comment", hints ) )
        .setParameterTypes( null )
        .createNamedQueryDefinition();

    if ( isDefault ) {
      mappings.addDefaultQuery( queryDefinition.getName(), queryDefinition );
    }
    else {
      mappings.addQuery( queryDefinition.getName(), queryDefinition );
    }
    if ( LOG.isDebugEnabled() ) {
      LOG.debugf( "Binding named query: %s => %s", queryDefinition.getName(), queryDefinition.getQueryString() );
    }
  }

  private static LockOptions determineLockOptions(NamedQuery namedQueryAnnotation, QueryHint[] hints) {
    LockModeType lockModeType = namedQueryAnnotation.lockMode();
    Integer lockTimeoutHint = getInteger( namedQueryAnnotation.name(), "javax.persistence.lock.timeout", hints );

    LockOptions lockOptions = new LockOptions( LockModeConverter.convertToLockMode( lockModeType ) );
    if ( lockTimeoutHint != null ) {
      lockOptions.setTimeOut( lockTimeoutHint );
    }

    return lockOptions;
  }

  public static void bindNativeQuery(NamedNativeQuery queryAnn, Mappings mappings, boolean isDefault) {
    if ( queryAnn == null ) return;
    //ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
    if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
      throw new AnnotationException( "A named query must have a name when used in class or package level" );
    }
    String resultSetMapping = queryAnn.resultSetMapping();
    QueryHint[] hints = queryAnn.hints();
    String queryName = queryAnn.query();
   
    NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder( queryAnn.name() )
        .setQuery( queryName )
        .setQuerySpaces( null )
        .setCacheable( getBoolean( queryName, "org.hibernate.cacheable", hints ) )
        .setCacheRegion( getString( queryName, "org.hibernate.cacheRegion", hints ) )
        .setTimeout( getTimeout( queryName, hints ) )
        .setFetchSize( getInteger( queryName, "org.hibernate.fetchSize", hints ) )
        .setFlushMode( getFlushMode( queryName, hints ) )
        .setCacheMode( getCacheMode( queryName, hints ) )
        .setReadOnly( getBoolean( queryName, "org.hibernate.readOnly", hints ) )
        .setComment( getString( queryName, "org.hibernate.comment", hints ) )
        .setParameterTypes( null )
        .setCallable( getBoolean( queryName, "org.hibernate.callable", hints ) );
   
    if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
      //sql result set usage
      builder.setResultSetRef( resultSetMapping )
          .createNamedQueryDefinition();
    }
    else if ( !void.class.equals( queryAnn.resultClass() ) ) {
      //class mapping usage
      //FIXME should be done in a second pass due to entity name?
      final NativeSQLQueryRootReturn entityQueryReturn =
          new NativeSQLQueryRootReturn( "alias1", queryAnn.resultClass().getName(), new HashMap(), LockMode.READ );
      builder.setQueryReturns( new NativeSQLQueryReturn[] {entityQueryReturn} );
    }
    else {
      builder.setQueryReturns( new NativeSQLQueryReturn[0] );
    }
   
    NamedSQLQueryDefinition query = builder.createNamedQueryDefinition();
   
    if ( isDefault ) {
      mappings.addDefaultSQLQuery( query.getName(), query );
    }
    else {
      mappings.addSQLQuery( query.getName(), query );
    }
    if ( LOG.isDebugEnabled() ) {
      LOG.debugf( "Binding named native query: %s => %s", queryAnn.name(), queryAnn.query() );
    }
  }

  public static void bindNativeQuery(org.hibernate.annotations.NamedNativeQuery queryAnn, Mappings mappings) {
    if ( queryAnn == null ) return;
    //ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
    if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
      throw new AnnotationException( "A named query must have a name when used in class or package level" );
    }
    NamedSQLQueryDefinition query;
    String resultSetMapping = queryAnn.resultSetMapping();
    if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
      //sql result set usage
      query = new NamedSQLQueryDefinitionBuilder().setName( queryAnn.name() )
          .setQuery( queryAnn.query() )
          .setResultSetRef( resultSetMapping )
          .setQuerySpaces( null )
          .setCacheable( queryAnn.cacheable() )
          .setCacheRegion(
              BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ?
                  null :
                  queryAnn.cacheRegion()
          )
          .setTimeout( queryAnn.timeout() < 0 ? null : queryAnn.timeout() )
          .setFetchSize( queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize() )
          .setFlushMode( getFlushMode( queryAnn.flushMode() ) )
          .setCacheMode( getCacheMode( queryAnn.cacheMode() ) )
          .setReadOnly( queryAnn.readOnly() )
          .setComment( BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment() )
          .setParameterTypes( null )
          .setCallable( queryAnn.callable() )
          .createNamedQueryDefinition();
    }
    else if ( !void.class.equals( queryAnn.resultClass() ) ) {
      //class mapping usage
      //FIXME should be done in a second pass due to entity name?
      final NativeSQLQueryRootReturn entityQueryReturn =
          new NativeSQLQueryRootReturn( "alias1", queryAnn.resultClass().getName(), new HashMap(), LockMode.READ );
      query = new NamedSQLQueryDefinitionBuilder().setName( queryAnn.name() )
          .setQuery( queryAnn.query() )
          .setQueryReturns( new NativeSQLQueryReturn[] {entityQueryReturn} )
          .setQuerySpaces( null )
          .setCacheable( queryAnn.cacheable() )
          .setCacheRegion(
              BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ?
                  null :
                  queryAnn.cacheRegion()
          )
          .setTimeout( queryAnn.timeout() < 0 ? null : queryAnn.timeout() )
          .setFetchSize( queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize() )
          .setFlushMode( getFlushMode( queryAnn.flushMode() ) )
          .setCacheMode( getCacheMode( queryAnn.cacheMode() ) )
          .setReadOnly( queryAnn.readOnly() )
          .setComment( BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment() )
          .setParameterTypes( null )
          .setCallable( queryAnn.callable() )
          .createNamedQueryDefinition();
    }
    else {
      throw new NotYetImplementedException( "Pure native scalar queries are not yet supported" );
    }
    mappings.addSQLQuery( query.getName(), query );
    if ( LOG.isDebugEnabled() ) {
      LOG.debugf( "Binding named native query: %s => %s", query.getName(), queryAnn.query() );
    }
  }

  public static void bindQueries(NamedQueries queriesAnn, Mappings mappings, boolean isDefault) {
    if ( queriesAnn == null ) return;
    for (NamedQuery q : queriesAnn.value()) {
      bindQuery( q, mappings, isDefault );
    }
  }

  public static void bindNativeQueries(NamedNativeQueries queriesAnn, Mappings mappings, boolean isDefault) {
    if ( queriesAnn == null ) return;
    for (NamedNativeQuery q : queriesAnn.value()) {
      bindNativeQuery( q, mappings, isDefault );
    }
  }

  public static void bindNativeQueries(
      org.hibernate.annotations.NamedNativeQueries queriesAnn, Mappings mappings
  ) {
    if ( queriesAnn == null ) return;
    for (org.hibernate.annotations.NamedNativeQuery q : queriesAnn.value()) {
      bindNativeQuery( q, mappings );
    }
  }

  public static void bindQuery(org.hibernate.annotations.NamedQuery queryAnn, Mappings mappings) {
    if ( queryAnn == null ) return;
    if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
      throw new AnnotationException( "A named query must have a name when used in class or package level" );
    }
    FlushMode flushMode;
    flushMode = getFlushMode( queryAnn.flushMode() );

    NamedQueryDefinition query = new NamedQueryDefinitionBuilder().setName( queryAnn.name() )
        .setQuery( queryAnn.query() )
        .setCacheable( queryAnn.cacheable() )
        .setCacheRegion(
            BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ?
                null :
                queryAnn.cacheRegion()
        )
        .setTimeout( queryAnn.timeout() < 0 ? null : queryAnn.timeout() )
        .setFetchSize( queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize() )
        .setFlushMode( flushMode )
        .setCacheMode( getCacheMode( queryAnn.cacheMode() ) )
        .setReadOnly( queryAnn.readOnly() )
        .setComment( BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment() )
        .setParameterTypes( null )
        .createNamedQueryDefinition();

    mappings.addQuery( query.getName(), query );
    if ( LOG.isDebugEnabled() ) {
      LOG.debugf( "Binding named query: %s => %s", query.getName(), query.getQueryString() );
    }
  }

  private static FlushMode getFlushMode(FlushModeType flushModeType) {
    FlushMode flushMode;
    switch ( flushModeType ) {
      case ALWAYS:
        flushMode = FlushMode.ALWAYS;
        break;
      case AUTO:
        flushMode = FlushMode.AUTO;
        break;
      case COMMIT:
        flushMode = FlushMode.COMMIT;
        break;
      case NEVER:
        flushMode = FlushMode.MANUAL;
        break;
      case MANUAL:
        flushMode = FlushMode.MANUAL;
        break;
      case PERSISTENCE_CONTEXT:
        flushMode = null;
        break;
      default:
        throw new AssertionFailure( "Unknown flushModeType: " + flushModeType );
    }
    return flushMode;
  }

  private static CacheMode getCacheMode(CacheModeType cacheModeType) {
    switch ( cacheModeType ) {
      case GET:
        return CacheMode.GET;
      case IGNORE:
        return CacheMode.IGNORE;
      case NORMAL:
        return CacheMode.NORMAL;
      case PUT:
        return CacheMode.PUT;
      case REFRESH:
        return CacheMode.REFRESH;
      default:
        throw new AssertionFailure( "Unknown cacheModeType: " + cacheModeType );
    }
  }


  public static void bindQueries(org.hibernate.annotations.NamedQueries queriesAnn, Mappings mappings) {
    if ( queriesAnn == null ) return;
    for (org.hibernate.annotations.NamedQuery q : queriesAnn.value()) {
      bindQuery( q, mappings );
    }
  }

  public static void bindSqlResultsetMappings(SqlResultSetMappings ann, Mappings mappings, boolean isDefault) {
    if ( ann == null ) return;
    for (SqlResultSetMapping rs : ann.value()) {
      //no need to handle inSecondPass
      mappings.addSecondPass( new ResultsetMappingSecondPass( rs, mappings, true ) );
    }
  }

  public static void bindSqlResultsetMapping(SqlResultSetMapping ann, Mappings mappings, boolean isDefault) {
    //no need to handle inSecondPass
    mappings.addSecondPass( new ResultsetMappingSecondPass( ann, mappings, isDefault ) );
  }

  private static CacheMode getCacheMode(String query, QueryHint[] hints) {
    for (QueryHint hint : hints) {
      if ( "org.hibernate.cacheMode".equals( hint.name() ) ) {
        if ( hint.value().equalsIgnoreCase( CacheMode.GET.toString() ) ) {
          return CacheMode.GET;
        }
        else if ( hint.value().equalsIgnoreCase( CacheMode.IGNORE.toString() ) ) {
          return CacheMode.IGNORE;
        }
        else if ( hint.value().equalsIgnoreCase( CacheMode.NORMAL.toString() ) ) {
          return CacheMode.NORMAL;
        }
        else if ( hint.value().equalsIgnoreCase( CacheMode.PUT.toString() ) ) {
          return CacheMode.PUT;
        }
        else if ( hint.value().equalsIgnoreCase( CacheMode.REFRESH.toString() ) ) {
          return CacheMode.REFRESH;
        }
        else {
          throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + hint.name() );
        }
      }
    }
    return null;
  }

  private static FlushMode getFlushMode(String query, QueryHint[] hints) {
    for (QueryHint hint : hints) {
      if ( "org.hibernate.flushMode".equals( hint.name() ) ) {
        if ( hint.value().equalsIgnoreCase( FlushMode.ALWAYS.toString() ) ) {
          return FlushMode.ALWAYS;
        }
        else if ( hint.value().equalsIgnoreCase( FlushMode.AUTO.toString() ) ) {
          return FlushMode.AUTO;
        }
        else if ( hint.value().equalsIgnoreCase( FlushMode.COMMIT.toString() ) ) {
          return FlushMode.COMMIT;
        }
        else if ( hint.value().equalsIgnoreCase( FlushMode.NEVER.toString() ) ) {
          return FlushMode.MANUAL;
        }
        else if ( hint.value().equalsIgnoreCase( FlushMode.MANUAL.toString() ) ) {
          return FlushMode.MANUAL;
        }
        else {
          throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + hint.name() );
        }
      }
    }
    return null;
  }

  private static boolean getBoolean(String query, String hintName, QueryHint[] hints) {
    for (QueryHint hint : hints) {
      if ( hintName.equals( hint.name() ) ) {
        if ( hint.value().equalsIgnoreCase( "true" ) ) {
          return true;
        }
        else if ( hint.value().equalsIgnoreCase( "false" ) ) {
          return false;
        }
        else {
          throw new AnnotationException( "Not a boolean in hint: " + query + ":" + hint.name() );
        }
      }
    }
    return false;
  }

  private static String getString(String query, String hintName, QueryHint[] hints) {
    for (QueryHint hint : hints) {
      if ( hintName.equals( hint.name() ) ) {
        return hint.value();
      }
    }
    return null;
  }

  private static Integer getInteger(String query, String hintName, QueryHint[] hints) {
    for (QueryHint hint : hints) {
      if ( hintName.equals( hint.name() ) ) {
        try {
          return Integer.decode( hint.value() );
        }
        catch (NumberFormatException nfe) {
          throw new AnnotationException( "Not an integer in hint: " + query + ":" + hint.name(), nfe );
        }
      }
    }
    return null;
  }

  private static Integer getTimeout(String queryName, QueryHint[] hints) {
    Integer timeout = getInteger( queryName, "javax.persistence.query.timeout", hints );

    if ( timeout != null ) {
      // convert milliseconds to seconds
      timeout = (int)Math.round(timeout.doubleValue() / 1000.0 );
    }
    else {
      // timeout is already in seconds
      timeout = getInteger( queryName, "org.hibernate.timeout", hints );
    }
    return timeout;
  }
}
TOP

Related Classes of org.hibernate.cfg.annotations.QueryBinder

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.