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()); }