private NamedSQLQueryDefinition extractSqlQueryDefinition(
     org.hibernate.SQLQuery nativeSqlQuery, String name) {
   final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder(name);
   fillInNamedQueryBuilder(builder, nativeSqlQuery);
   builder
       .setCallable(nativeSqlQuery.isCallable())
       .setQuerySpaces(nativeSqlQuery.getSynchronizedQuerySpaces())
       .setQueryReturns(nativeSqlQuery.getQueryReturns());
   return builder.createNamedQueryDefinition();
 }
  private static boolean processNamedQueryContentItem(
      Object content,
      NamedSQLQueryDefinitionBuilder builder,
      ImplicitResultSetMappingDefinition.Builder implicitResultSetMappingBuilder,
      JaxbHbmNamedNativeQueryType namedQueryBinding,
      HbmLocalMetadataBuildingContext context) {
    if (String.class.isInstance(content)) {
      // Especially when the query string is wrapped in CDATA we will get
      // "extra" Strings here containing just spaces and/or newlines.  This
      // bit tries to account for them.
      final String contentString = StringHelper.nullIfEmpty(((String) content).trim());
      if (contentString != null) {
        builder.setQuery((String) content);
        return true;
      } else {
        return false;
      }
    } else if (JAXBElement.class.isInstance(content)) {
      return processNamedQueryContentItem(
          ((JAXBElement) content).getValue(),
          builder,
          implicitResultSetMappingBuilder,
          namedQueryBinding,
          context);
    }

    if (JaxbHbmQueryParamType.class.isInstance(content)) {
      final JaxbHbmQueryParamType paramTypeBinding = (JaxbHbmQueryParamType) content;
      builder.addParameterType(paramTypeBinding.getName(), paramTypeBinding.getType());
    } else if (JaxbHbmSynchronizeType.class.isInstance(content)) {
      final JaxbHbmSynchronizeType synchronizedSpace = (JaxbHbmSynchronizeType) content;
      builder.addSynchronizedQuerySpace(synchronizedSpace.getTable());
    } else if (JaxbHbmNativeQueryScalarReturnType.class.isInstance(content)) {
      implicitResultSetMappingBuilder.addReturn((JaxbHbmNativeQueryScalarReturnType) content);
    } else if (JaxbHbmNativeQueryReturnType.class.isInstance(content)) {
      implicitResultSetMappingBuilder.addReturn((JaxbHbmNativeQueryReturnType) content);
    } else if (JaxbHbmNativeQueryJoinReturnType.class.isInstance(content)) {
      implicitResultSetMappingBuilder.addReturn((JaxbHbmNativeQueryJoinReturnType) content);
    } else if (JaxbHbmNativeQueryCollectionLoadReturnType.class.isInstance(content)) {
      implicitResultSetMappingBuilder.addReturn(
          (JaxbHbmNativeQueryCollectionLoadReturnType) content);
    } else {
      throw new org.hibernate.boot.MappingException(
          String.format(
              Locale.ENGLISH,
              "Encountered unexpected content type [%s] for named native query [%s] : [%s]",
              content.getClass().getName(),
              namedQueryBinding.getName(),
              content.toString()),
          context.getOrigin());
    }

    return false;
  }
  public static void processNamedNativeQuery(
      final HbmLocalMetadataBuildingContext context,
      JaxbHbmNamedNativeQueryType namedQueryBinding,
      String prefix) {
    final String queryName = prefix + namedQueryBinding.getName();
    final NamedSQLQueryDefinitionBuilder builder =
        new NamedSQLQueryDefinitionBuilder()
            .setName(queryName)
            .setComment(namedQueryBinding.getComment())
            .setCacheable(namedQueryBinding.isCacheable())
            .setCacheMode(namedQueryBinding.getCacheMode())
            .setCacheRegion(namedQueryBinding.getCacheRegion())
            .setTimeout(namedQueryBinding.getTimeout())
            .setReadOnly(namedQueryBinding.isReadOnly())
            .setFlushMode(namedQueryBinding.getFlushMode())
            .setFetchSize(namedQueryBinding.getFetchSize())
            .setCallable(namedQueryBinding.isCallable())
            .setResultSetRef(namedQueryBinding.getResultsetRef());

    final ImplicitResultSetMappingDefinition.Builder implicitResultSetMappingBuilder =
        new ImplicitResultSetMappingDefinition.Builder(queryName);

    boolean foundQuery = false;

    for (Object content : namedQueryBinding.getContent()) {
      final boolean wasQuery =
          processNamedQueryContentItem(
              content, builder, implicitResultSetMappingBuilder, namedQueryBinding, context);
      if (wasQuery) {
        foundQuery = true;
      }
    }

    if (!foundQuery) {
      throw new org.hibernate.boot.MappingException(
          String.format(
              "Named native query [%s] did not specify query string", namedQueryBinding.getName()),
          context.getOrigin());
    }

    if (implicitResultSetMappingBuilder.hasAnyReturns()) {
      if (StringHelper.isNotEmpty(namedQueryBinding.getResultsetRef())) {
        throw new org.hibernate.boot.MappingException(
            String.format(
                "Named native query [%s] specified both a resultset-ref and an inline mapping of results",
                namedQueryBinding.getName()),
            context.getOrigin());
      }

      // Building a ResultSet mapping needs access to entity bindings for any entity
      // returns it defines.  But binding for those entities may have not been
      // completed yet.  For "normal" ResultSet mappings, this is already handled by
      // the fact that MetadataSourceProcessor#processResultSetMappings() is called
      // afterQuery all entity hierarchies have been processed.  However, here we are in
      // the middle of processing named-queries (either top-level or entity-level)
      // and have no guarantee that any entity bindings we may need here are bound.
      // So we add the second-pass to bind the implicit resultSet mapping.
      //
      // It is possible to know here whether the second-pass is needed or whether we
      // can immediately bind the ResultSet mapping.
      // todo : consider implementing this (^^) checking

      final ImplicitResultSetMappingDefinition implicitResultSetMappingDefinition =
          implicitResultSetMappingBuilder.build();
      builder.setResultSetRef(implicitResultSetMappingDefinition.getName());
      context
          .getMetadataCollector()
          .addSecondPass(
              new SecondPass() {
                @Override
                public void doSecondPass(Map persistentClasses) throws MappingException {
                  final ResultSetMappingDefinition resultSetMappingDefinition =
                      ResultSetMappingBinder.bind(implicitResultSetMappingDefinition, context);
                  context.getMetadataCollector().addResultSetMapping(resultSetMappingDefinition);
                  NativeSQLQueryReturn[] newQueryReturns =
                      resultSetMappingDefinition.getQueryReturns();
                  final NamedSQLQueryDefinition queryDefinition =
                      context.getMetadataCollector().getNamedNativeQueryDefinition(queryName);
                  if (queryDefinition != null) {
                    queryDefinition.addQueryReturns(newQueryReturns);
                  }
                }
              });
    }

    context.getMetadataCollector().addNamedNativeQuery(builder.createNamedQueryDefinition());
  }