HHH-8211 - Checkstyle and FindBugs fix-ups
This commit is contained in:
parent
f2073113fc
commit
286800ec34
|
@ -62,7 +62,7 @@ public class CollectionLoadContext {
|
|||
|
||||
private final LoadContexts loadContexts;
|
||||
private final ResultSet resultSet;
|
||||
private Set localLoadingCollectionKeys = new HashSet();
|
||||
private Set<CollectionKey> localLoadingCollectionKeys = new HashSet<CollectionKey>();
|
||||
|
||||
/**
|
||||
* Creates a collection load context for the given result set.
|
||||
|
@ -119,12 +119,13 @@ public class CollectionLoadContext {
|
|||
if ( collection != null ) {
|
||||
if ( collection.wasInitialized() ) {
|
||||
LOG.trace( "Collection already initialized; ignoring" );
|
||||
return null; // ignore this row of results! Note the early exit
|
||||
// ignore this row of results! Note the early exit
|
||||
return null;
|
||||
}
|
||||
LOG.trace( "Collection not yet initialized; initializing" );
|
||||
}
|
||||
else {
|
||||
Object owner = loadContexts.getPersistenceContext().getCollectionOwner( key, persister );
|
||||
final Object owner = loadContexts.getPersistenceContext().getCollectionOwner( key, persister );
|
||||
final boolean newlySavedEntity = owner != null
|
||||
&& loadContexts.getPersistenceContext().getEntry( owner ).getStatus() != Status.LOADING;
|
||||
if ( newlySavedEntity ) {
|
||||
|
@ -162,7 +163,7 @@ public class CollectionLoadContext {
|
|||
* @param persister The persister for which to complete loading.
|
||||
*/
|
||||
public void endLoadingCollections(CollectionPersister persister) {
|
||||
SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
|
||||
final SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
|
||||
if ( !loadContexts.hasLoadingCollectionEntries()
|
||||
&& localLoadingCollectionKeys.isEmpty() ) {
|
||||
return;
|
||||
|
@ -174,17 +175,17 @@ public class CollectionLoadContext {
|
|||
// internal loadingCollections map for matches and store those matches
|
||||
// in a temp collection. the temp collection is then used to "drive"
|
||||
// the #endRead processing.
|
||||
List matches = null;
|
||||
Iterator iter = localLoadingCollectionKeys.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
final CollectionKey collectionKey = (CollectionKey) iter.next();
|
||||
List<LoadingCollectionEntry> matches = null;
|
||||
final Iterator itr = localLoadingCollectionKeys.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final CollectionKey collectionKey = (CollectionKey) itr.next();
|
||||
final LoadingCollectionEntry lce = loadContexts.locateLoadingCollectionEntry( collectionKey );
|
||||
if ( lce == null ) {
|
||||
LOG.loadingCollectionKeyNotFound( collectionKey );
|
||||
}
|
||||
else if ( lce.getResultSet() == resultSet && lce.getPersister() == persister ) {
|
||||
if ( matches == null ) {
|
||||
matches = new ArrayList();
|
||||
matches = new ArrayList<LoadingCollectionEntry>();
|
||||
}
|
||||
matches.add( lce );
|
||||
if ( lce.getCollection().getOwner() == null ) {
|
||||
|
@ -201,7 +202,7 @@ public class CollectionLoadContext {
|
|||
|
||||
// todo : i'd much rather have this done from #endLoadingCollection(CollectionPersister,LoadingCollectionEntry)...
|
||||
loadContexts.unregisterLoadingCollectionXRef( collectionKey );
|
||||
iter.remove();
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,29 +218,35 @@ public class CollectionLoadContext {
|
|||
}
|
||||
}
|
||||
|
||||
private void endLoadingCollections(CollectionPersister persister, List matchedCollectionEntries) {
|
||||
private void endLoadingCollections(CollectionPersister persister, List<LoadingCollectionEntry> matchedCollectionEntries) {
|
||||
final boolean debugEnabled = LOG.isDebugEnabled();
|
||||
if ( matchedCollectionEntries == null ) {
|
||||
if ( debugEnabled ) LOG.debugf( "No collections were found in result set for role: %s", persister.getRole() );
|
||||
if ( debugEnabled ) {
|
||||
LOG.debugf( "No collections were found in result set for role: %s", persister.getRole() );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final int count = matchedCollectionEntries.size();
|
||||
if ( debugEnabled ) LOG.debugf("%s collections were found in result set for role: %s", count, persister.getRole());
|
||||
|
||||
for ( int i = 0; i < count; i++ ) {
|
||||
LoadingCollectionEntry lce = ( LoadingCollectionEntry ) matchedCollectionEntries.get( i );
|
||||
endLoadingCollection( lce, persister );
|
||||
if ( debugEnabled ) {
|
||||
LOG.debugf( "%s collections were found in result set for role: %s", count, persister.getRole() );
|
||||
}
|
||||
|
||||
if ( debugEnabled ) LOG.debugf( "%s collections initialized for role: %s", count, persister.getRole() );
|
||||
for ( LoadingCollectionEntry matchedCollectionEntry : matchedCollectionEntries ) {
|
||||
endLoadingCollection( matchedCollectionEntry, persister );
|
||||
}
|
||||
|
||||
if ( debugEnabled ) {
|
||||
LOG.debugf( "%s collections initialized for role: %s", count, persister.getRole() );
|
||||
}
|
||||
}
|
||||
|
||||
private void endLoadingCollection(LoadingCollectionEntry lce, CollectionPersister persister) {
|
||||
LOG.tracev( "Ending loading collection [{0}]", lce );
|
||||
final SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
|
||||
|
||||
boolean hasNoQueuedAdds = lce.getCollection().endRead(); // warning: can cause a recursive calls! (proxy initialization)
|
||||
// warning: can cause a recursive calls! (proxy initialization)
|
||||
final boolean hasNoQueuedAdds = lce.getCollection().endRead();
|
||||
|
||||
if ( persister.getCollectionType().hasHolder() ) {
|
||||
getLoadContext().getPersistenceContext().addCollectionHolder( lce.getCollection() );
|
||||
|
@ -255,13 +262,16 @@ public class CollectionLoadContext {
|
|||
// getLoadContext().getPersistenceContext().getBatchFetchQueue().removeBatchLoadableCollection(ce);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean addToCache = hasNoQueuedAdds && // there were no queued additions
|
||||
persister.hasCache() && // and the role has a cache
|
||||
session.getCacheMode().isPutEnabled() &&
|
||||
!ce.isDoremove(); // and this is not a forced initialization during flush
|
||||
// add to cache if:
|
||||
boolean addToCache =
|
||||
// there were no queued additions
|
||||
hasNoQueuedAdds
|
||||
// and the role has a cache
|
||||
&& persister.hasCache()
|
||||
// and this is not a forced initialization during flush
|
||||
&& session.getCacheMode().isPutEnabled() && !ce.isDoremove();
|
||||
if ( addToCache ) {
|
||||
addCollectionToCache( lce, persister );
|
||||
}
|
||||
|
@ -269,11 +279,11 @@ public class CollectionLoadContext {
|
|||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf(
|
||||
"Collection fully initialized: %s",
|
||||
MessageHelper.collectionInfoString(persister, lce.getCollection(), lce.getKey(), session)
|
||||
MessageHelper.collectionInfoString( persister, lce.getCollection(), lce.getKey(), session )
|
||||
);
|
||||
}
|
||||
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
session.getFactory().getStatisticsImplementor().loadCollection(persister.getRole());
|
||||
session.getFactory().getStatisticsImplementor().loadCollection( persister.getRole() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +312,8 @@ public class CollectionLoadContext {
|
|||
// currently this works in conjuction with the check on
|
||||
// DefaultInitializeCollectionEventHandler.initializeCollectionFromCache() (which makes sure to not read from
|
||||
// cache with enabled filters).
|
||||
return; // EARLY EXIT!!!!!
|
||||
// EARLY EXIT!!!!!
|
||||
return;
|
||||
}
|
||||
|
||||
final Object version;
|
||||
|
@ -315,7 +326,7 @@ public class CollectionLoadContext {
|
|||
// about its owner, that owner should be the same instance as associated with the PC, but we do the
|
||||
// resolution against the PC anyway just to be safe since the lookup should not be costly.
|
||||
if ( lce.getCollection() != null ) {
|
||||
Object linkedOwner = lce.getCollection().getOwner();
|
||||
final Object linkedOwner = lce.getCollection().getOwner();
|
||||
if ( linkedOwner != null ) {
|
||||
final Serializable ownerKey = persister.getOwnerEntityPersister().getIdentifier( linkedOwner, session );
|
||||
collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner( ownerKey, persister );
|
||||
|
@ -335,11 +346,11 @@ public class CollectionLoadContext {
|
|||
version = null;
|
||||
}
|
||||
|
||||
CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
|
||||
CacheKey cacheKey = session.generateCacheKey( lce.getKey(), persister.getKeyType(), persister.getRole() );
|
||||
boolean put = persister.getCacheAccessStrategy().putFromLoad(
|
||||
final CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
|
||||
final CacheKey cacheKey = session.generateCacheKey( lce.getKey(), persister.getKeyType(), persister.getRole() );
|
||||
final boolean put = persister.getCacheAccessStrategy().putFromLoad(
|
||||
cacheKey,
|
||||
persister.getCacheEntryStructure().structure(entry),
|
||||
persister.getCacheEntryStructure().structure( entry ),
|
||||
session.getTimestamp(),
|
||||
version,
|
||||
factory.getSettings().isMinimalPutsEnabled() && session.getCacheMode()!= CacheMode.REFRESH
|
||||
|
@ -360,7 +371,7 @@ public class CollectionLoadContext {
|
|||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString() {
|
||||
return super.toString() + "<rs=" + resultSet + ">";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ public class EntityLoadContext {
|
|||
|
||||
private final LoadContexts loadContexts;
|
||||
private final ResultSet resultSet;
|
||||
private final List hydratingEntities = new ArrayList( 20 ); // todo : need map? the prob is a proper key, right?
|
||||
// todo : need map? the prob is a proper key, right?
|
||||
private final List hydratingEntities = new ArrayList( 20 );
|
||||
|
||||
public EntityLoadContext(LoadContexts loadContexts, ResultSet resultSet) {
|
||||
this.loadContexts = loadContexts;
|
||||
|
|
|
@ -30,24 +30,18 @@ import java.util.IdentityHashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.IdentityMap;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
|
||||
/**
|
||||
* Maps {@link ResultSet result-sets} to specific contextual data related to processing that result set
|
||||
* <p/>
|
||||
* Implementation note: internally an {@link IdentityMap} is used to maintain the mappings mainly because I'd
|
||||
* rather not be dependent upon potentially bad {@link Object#equals} and {@link Object#hashCode} implementations on
|
||||
* the JDBC result sets
|
||||
* <p/>
|
||||
* Considering the JDBC-redesign work, would further like this contextual info not mapped separately, but available
|
||||
* based on the result set being processed. This would also allow maintaining a single mapping as we could reliably
|
||||
* get notification of the result-set closing...
|
||||
|
@ -55,8 +49,7 @@ import org.hibernate.pretty.MessageHelper;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LoadContexts {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, LoadContexts.class.getName());
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( LoadContexts.class );
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
private Map<ResultSet,CollectionLoadContext> collectionLoadContexts;
|
||||
|
@ -101,11 +94,11 @@ public class LoadContexts {
|
|||
*/
|
||||
public void cleanup(ResultSet resultSet) {
|
||||
if ( collectionLoadContexts != null ) {
|
||||
CollectionLoadContext collectionLoadContext = collectionLoadContexts.remove( resultSet );
|
||||
final CollectionLoadContext collectionLoadContext = collectionLoadContexts.remove( resultSet );
|
||||
collectionLoadContext.cleanup();
|
||||
}
|
||||
if ( entityLoadContexts != null ) {
|
||||
EntityLoadContext entityLoadContext = entityLoadContexts.remove( resultSet );
|
||||
final EntityLoadContext entityLoadContext = entityLoadContexts.remove( resultSet );
|
||||
entityLoadContext.cleanup();
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +184,7 @@ public class LoadContexts {
|
|||
* @return The loading collection, or null if not found.
|
||||
*/
|
||||
public PersistentCollection locateLoadingCollection(CollectionPersister persister, Serializable ownerKey) {
|
||||
LoadingCollectionEntry lce = locateLoadingCollectionEntry( new CollectionKey( persister, ownerKey ) );
|
||||
final LoadingCollectionEntry lce = locateLoadingCollectionEntry( new CollectionKey( persister, ownerKey ) );
|
||||
if ( lce != null ) {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracef(
|
||||
|
@ -246,13 +239,13 @@ public class LoadContexts {
|
|||
if ( !hasRegisteredLoadingCollectionEntries() ) {
|
||||
return;
|
||||
}
|
||||
xrefLoadingCollectionEntries.remove(key);
|
||||
}
|
||||
xrefLoadingCollectionEntries.remove( key );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
Map getLoadingCollectionXRefs() {
|
||||
return xrefLoadingCollectionEntries;
|
||||
}
|
||||
return xrefLoadingCollectionEntries;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -271,7 +264,7 @@ public class LoadContexts {
|
|||
return null;
|
||||
}
|
||||
LOG.tracev( "Attempting to locate loading collection entry [{0}] in any result-set context", key );
|
||||
LoadingCollectionEntry rtn = xrefLoadingCollectionEntries.get( key );
|
||||
final LoadingCollectionEntry rtn = xrefLoadingCollectionEntries.get( key );
|
||||
if ( rtn == null ) {
|
||||
LOG.tracev( "Collection [{0}] not located in load context", key );
|
||||
}
|
||||
|
@ -291,6 +284,13 @@ public class LoadContexts {
|
|||
// Entity load contexts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// * currently, not yet used...
|
||||
|
||||
/**
|
||||
* Currently unused
|
||||
*
|
||||
* @param resultSet The result set
|
||||
*
|
||||
* @return The entity load context
|
||||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public EntityLoadContext getEntityLoadContext(ResultSet resultSet) {
|
||||
EntityLoadContext context = null;
|
||||
|
|
|
@ -41,7 +41,7 @@ public class LoadingCollectionEntry {
|
|||
private final Serializable key;
|
||||
private final PersistentCollection collection;
|
||||
|
||||
public LoadingCollectionEntry(
|
||||
LoadingCollectionEntry(
|
||||
ResultSet resultSet,
|
||||
CollectionPersister persister,
|
||||
Serializable key,
|
||||
|
@ -68,6 +68,7 @@ public class LoadingCollectionEntry {
|
|||
return collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "<rs=" + resultSet + ", coll=" + MessageHelper.collectionInfoString( persister.getRole(), key ) + ">@" + Integer.toHexString( hashCode() );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Internal classes used to track loading of data, potentially across multiple ResultSets
|
||||
*/
|
||||
package org.hibernate.engine.loading.internal;
|
|
@ -34,6 +34,12 @@ public class Association {
|
|||
private final String associationPath;
|
||||
private final String role;
|
||||
|
||||
/**
|
||||
* Constructs a association defining what is to be fetched.
|
||||
*
|
||||
* @param owner The entity owning the association
|
||||
* @param associationPath The path of the association, from the entity
|
||||
*/
|
||||
public Association(EntityPersister owner, String associationPath) {
|
||||
this.owner = owner;
|
||||
this.associationPath = associationPath;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.engine.profile;
|
||||
|
||||
|
||||
/**
|
||||
* Models an individual fetch within a profile.
|
||||
*
|
||||
|
@ -33,6 +32,12 @@ public class Fetch {
|
|||
private final Association association;
|
||||
private final Style style;
|
||||
|
||||
/**
|
||||
* Constructs a Fetch
|
||||
*
|
||||
* @param association The association to be fetched
|
||||
* @param style How to fetch it
|
||||
*/
|
||||
public Fetch(Association association, Style style) {
|
||||
this.association = association;
|
||||
this.style = style;
|
||||
|
@ -54,7 +59,13 @@ public class Fetch {
|
|||
* needed for other things as well anyway).
|
||||
*/
|
||||
public enum Style {
|
||||
/**
|
||||
* Fetch via a join
|
||||
*/
|
||||
JOIN( "join" ),
|
||||
/**
|
||||
* Fetch via a subsequent select
|
||||
*/
|
||||
SELECT( "select" );
|
||||
|
||||
private final String name;
|
||||
|
@ -63,10 +74,18 @@ public class Fetch {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a style given an externalized string representation
|
||||
*
|
||||
* @param name The externalized representation
|
||||
*
|
||||
* @return The style; {@link #JOIN} is returned if not recognized
|
||||
*/
|
||||
public static Style parse(String name) {
|
||||
if ( SELECT.name.equals( name ) ) {
|
||||
return SELECT;
|
||||
|
@ -78,6 +97,7 @@ public class Fetch {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Fetch[" + style + "{" + association.getRole() + "}]";
|
||||
}
|
||||
|
|
|
@ -22,12 +22,11 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.profile;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.type.BagType;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -41,21 +40,17 @@ import org.hibernate.type.Type;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FetchProfile {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, FetchProfile.class.getName());
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( FetchProfile.class );
|
||||
|
||||
private final String name;
|
||||
private Map<String,Fetch> fetches = new HashMap<String,Fetch>();
|
||||
|
||||
private boolean containsJoinFetchedCollection = false;
|
||||
private boolean containsJoinFetchedBag = false;
|
||||
private boolean containsJoinFetchedCollection;
|
||||
private boolean containsJoinFetchedBag;
|
||||
private Fetch bagJoinFetch;
|
||||
|
||||
/**
|
||||
* A 'fetch profile' is uniquely named within a
|
||||
* {@link SessionFactoryImplementor SessionFactory}, thus it is also
|
||||
* uniquely and easily identifiable within that
|
||||
* {@link SessionFactoryImplementor SessionFactory}.
|
||||
* Constructs a FetchProfile, supplying its unique name (unique within the SessionFactory).
|
||||
*
|
||||
* @param name The name under which we are bound in the sessionFactory
|
||||
*/
|
||||
|
@ -91,7 +86,7 @@ public class FetchProfile {
|
|||
*/
|
||||
public void addFetch(final Fetch fetch) {
|
||||
final String fetchAssociactionRole = fetch.getAssociation().getRole();
|
||||
Type associationType = fetch.getAssociation().getOwner().getPropertyType( fetch.getAssociation().getAssociationPath() );
|
||||
final Type associationType = fetch.getAssociation().getOwner().getPropertyType( fetch.getAssociation().getAssociationPath() );
|
||||
if ( associationType.isCollectionType() ) {
|
||||
LOG.tracev( "Handling request to add collection fetch [{0}]", fetchAssociactionRole );
|
||||
|
||||
|
@ -103,7 +98,8 @@ public class FetchProfile {
|
|||
if ( BagType.class.isInstance( associationType ) ) {
|
||||
if ( containsJoinFetchedCollection ) {
|
||||
LOG.containsJoinFetchedCollection( fetchAssociactionRole );
|
||||
return; // EARLY EXIT!!!
|
||||
// EARLY EXIT!!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,6 +140,13 @@ public class FetchProfile {
|
|||
return fetches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the fetch associated with the given role.
|
||||
*
|
||||
* @param role The role identifying the fetch
|
||||
*
|
||||
* @return The fetch, or {@code null} if a matching one was not found
|
||||
*/
|
||||
public Fetch getFetchByRole(String role) {
|
||||
return fetches.get( role );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Models the fetch profiles defined by the application
|
||||
*/
|
||||
package org.hibernate.engine.profile;
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, 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 Middleware LLC.
|
||||
* 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
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.engine.query.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -38,12 +38,21 @@ public class FilterQueryPlan extends HQLQueryPlan implements Serializable {
|
|||
|
||||
private final String collectionRole;
|
||||
|
||||
/**
|
||||
* Constructs a query plan for an HQL filter
|
||||
*
|
||||
* @param hql The HQL fragment
|
||||
* @param collectionRole The collection role being filtered
|
||||
* @param shallow Is the query shallow?
|
||||
* @param enabledFilters All enabled filters from the Session
|
||||
* @param factory The factory
|
||||
*/
|
||||
public FilterQueryPlan(
|
||||
String hql,
|
||||
String collectionRole,
|
||||
boolean shallow,
|
||||
Map enabledFilters,
|
||||
SessionFactoryImplementor factory) {
|
||||
String collectionRole,
|
||||
boolean shallow,
|
||||
Map enabledFilters,
|
||||
SessionFactoryImplementor factory) {
|
||||
super( hql, collectionRole, shallow, enabledFilters, factory );
|
||||
this.collectionRole = collectionRole;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.ScrollableResults;
|
||||
|
@ -47,6 +46,7 @@ import org.hibernate.hql.spi.FilterTranslator;
|
|||
import org.hibernate.hql.spi.ParameterTranslations;
|
||||
import org.hibernate.hql.spi.QueryTranslator;
|
||||
import org.hibernate.hql.spi.QueryTranslatorFactory;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.collections.EmptyIterator;
|
||||
|
@ -60,11 +60,10 @@ import org.hibernate.type.Type;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class HQLQueryPlan implements Serializable {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( HQLQueryPlan.class );
|
||||
|
||||
// TODO : keep separate notions of QT[] here for shallow/non-shallow queries...
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, HQLQueryPlan.class.getName());
|
||||
|
||||
private final String sourceQuery;
|
||||
private final QueryTranslator[] translators;
|
||||
private final String[] sqlStrings;
|
||||
|
@ -73,17 +72,32 @@ public class HQLQueryPlan implements Serializable {
|
|||
private final ReturnMetadata returnMetadata;
|
||||
private final Set querySpaces;
|
||||
|
||||
private final Set enabledFilterNames;
|
||||
private final Set<String> enabledFilterNames;
|
||||
private final boolean shallow;
|
||||
|
||||
public HQLQueryPlan(String hql, boolean shallow, Map enabledFilters, SessionFactoryImplementor factory) {
|
||||
/**
|
||||
* Constructs a HQLQueryPlan
|
||||
*
|
||||
* @param hql The HQL query
|
||||
* @param shallow Whether the execution is to be shallow or not
|
||||
* @param enabledFilters The enabled filters (we only keep the names)
|
||||
* @param factory The factory
|
||||
*/
|
||||
public HQLQueryPlan(String hql, boolean shallow, Map<String,Filter> enabledFilters, SessionFactoryImplementor factory) {
|
||||
this( hql, null, shallow, enabledFilters, factory );
|
||||
}
|
||||
|
||||
protected HQLQueryPlan(String hql, String collectionRole, boolean shallow, Map enabledFilters, SessionFactoryImplementor factory){
|
||||
@SuppressWarnings("unchecked")
|
||||
protected HQLQueryPlan(
|
||||
String hql,
|
||||
String collectionRole,
|
||||
boolean shallow,
|
||||
Map<String,Filter> enabledFilters,
|
||||
SessionFactoryImplementor factory) {
|
||||
this.sourceQuery = hql;
|
||||
this.shallow = shallow;
|
||||
Set copy = new HashSet();
|
||||
|
||||
final Set<String> copy = new HashSet<String>();
|
||||
copy.addAll( enabledFilters.keySet() );
|
||||
this.enabledFilterNames = java.util.Collections.unmodifiableSet( copy );
|
||||
|
||||
|
@ -91,8 +105,8 @@ public class HQLQueryPlan implements Serializable {
|
|||
final int length = concreteQueryStrings.length;
|
||||
this.translators = new QueryTranslator[length];
|
||||
|
||||
List<String> sqlStringList = new ArrayList<String>();
|
||||
Set combinedQuerySpaces = new HashSet();
|
||||
final List<String> sqlStringList = new ArrayList<String>();
|
||||
final Set combinedQuerySpaces = new HashSet();
|
||||
|
||||
final boolean hasCollectionRole = (collectionRole == null);
|
||||
final Map querySubstitutions = factory.getSettings().getQuerySubstitutions();
|
||||
|
@ -107,7 +121,7 @@ public class HQLQueryPlan implements Serializable {
|
|||
else {
|
||||
translators[i] = queryTranslatorFactory
|
||||
.createFilterTranslator( hql, concreteQueryStrings[i], enabledFilters, factory );
|
||||
( ( FilterTranslator ) translators[i] ).compile( collectionRole, querySubstitutions, shallow );
|
||||
( (FilterTranslator) translators[i] ).compile( collectionRole, querySubstitutions, shallow );
|
||||
}
|
||||
combinedQuerySpaces.addAll( translators[i].getQuerySpaces() );
|
||||
sqlStringList.addAll( translators[i].collectSqlStrings() );
|
||||
|
@ -165,20 +179,33 @@ public class HQLQueryPlan implements Serializable {
|
|||
return shallow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinates the efforts to perform a list across all the included query translators.
|
||||
*
|
||||
* @param queryParameters The query parameters
|
||||
* @param session The session
|
||||
*
|
||||
* @return The query result list
|
||||
*
|
||||
* @throws HibernateException Indicates a problem performing the query
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List performList(
|
||||
QueryParameters queryParameters,
|
||||
SessionImplementor session) throws HibernateException {
|
||||
SessionImplementor session) throws HibernateException {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Find: {0}", getSourceQuery() );
|
||||
queryParameters.traceParameters( session.getFactory() );
|
||||
}
|
||||
boolean hasLimit = queryParameters.getRowSelection() != null &&
|
||||
queryParameters.getRowSelection().definesLimits();
|
||||
boolean needsLimit = hasLimit && translators.length > 1;
|
||||
QueryParameters queryParametersToUse;
|
||||
|
||||
final boolean hasLimit = queryParameters.getRowSelection() != null
|
||||
&& queryParameters.getRowSelection().definesLimits();
|
||||
final boolean needsLimit = hasLimit && translators.length > 1;
|
||||
|
||||
final QueryParameters queryParametersToUse;
|
||||
if ( needsLimit ) {
|
||||
LOG.needsLimit();
|
||||
RowSelection selection = new RowSelection();
|
||||
final RowSelection selection = new RowSelection();
|
||||
selection.setFetchSize( queryParameters.getRowSelection().getFetchSize() );
|
||||
selection.setTimeout( queryParameters.getRowSelection().getTimeout() );
|
||||
queryParametersToUse = queryParameters.createCopyUsing( selection );
|
||||
|
@ -187,12 +214,12 @@ public class HQLQueryPlan implements Serializable {
|
|||
queryParametersToUse = queryParameters;
|
||||
}
|
||||
|
||||
List combinedResults = new ArrayList();
|
||||
IdentitySet distinction = new IdentitySet();
|
||||
final List combinedResults = new ArrayList();
|
||||
final IdentitySet distinction = new IdentitySet();
|
||||
int includedCount = -1;
|
||||
translator_loop:
|
||||
for ( QueryTranslator translator : translators ) {
|
||||
List tmp = translator.list( session, queryParametersToUse );
|
||||
final List tmp = translator.list( session, queryParametersToUse );
|
||||
if ( needsLimit ) {
|
||||
// NOTE : firstRow is zero-based
|
||||
final int first = queryParameters.getRowSelection().getFirstRow() == null
|
||||
|
@ -223,9 +250,20 @@ public class HQLQueryPlan implements Serializable {
|
|||
return combinedResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinates the efforts to perform an iterate across all the included query translators.
|
||||
*
|
||||
* @param queryParameters The query parameters
|
||||
* @param session The session
|
||||
*
|
||||
* @return The query result iterator
|
||||
*
|
||||
* @throws HibernateException Indicates a problem performing the query
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator performIterate(
|
||||
QueryParameters queryParameters,
|
||||
EventSource session) throws HibernateException {
|
||||
EventSource session) throws HibernateException {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Iterate: {0}", getSourceQuery() );
|
||||
queryParameters.traceParameters( session.getFactory() );
|
||||
|
@ -234,8 +272,8 @@ public class HQLQueryPlan implements Serializable {
|
|||
return EmptyIterator.INSTANCE;
|
||||
}
|
||||
|
||||
final boolean many = translators.length > 1;
|
||||
Iterator[] results = null;
|
||||
boolean many = translators.length > 1;
|
||||
if ( many ) {
|
||||
results = new Iterator[translators.length];
|
||||
}
|
||||
|
@ -248,12 +286,22 @@ public class HQLQueryPlan implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
return many ? new JoinedIterator(results) : result;
|
||||
return many ? new JoinedIterator( results ) : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinates the efforts to perform a scroll across all the included query translators.
|
||||
*
|
||||
* @param queryParameters The query parameters
|
||||
* @param session The session
|
||||
*
|
||||
* @return The query result iterator
|
||||
*
|
||||
* @throws HibernateException Indicates a problem performing the query
|
||||
*/
|
||||
public ScrollableResults performScroll(
|
||||
QueryParameters queryParameters,
|
||||
SessionImplementor session) throws HibernateException {
|
||||
SessionImplementor session) throws HibernateException {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Iterate: {0}", getSourceQuery() );
|
||||
queryParameters.traceParameters( session.getFactory() );
|
||||
|
@ -268,6 +316,16 @@ public class HQLQueryPlan implements Serializable {
|
|||
return translators[0].scroll( queryParameters, session );
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinates the efforts to perform an execution across all the included query translators.
|
||||
*
|
||||
* @param queryParameters The query parameters
|
||||
* @param session The session
|
||||
*
|
||||
* @return The aggregated "affected row" count
|
||||
*
|
||||
* @throws HibernateException Indicates a problem performing the execution
|
||||
*/
|
||||
public int performExecuteUpdate(QueryParameters queryParameters, SessionImplementor session)
|
||||
throws HibernateException {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
|
@ -285,32 +343,34 @@ public class HQLQueryPlan implements Serializable {
|
|||
}
|
||||
|
||||
private ParameterMetadata buildParameterMetadata(ParameterTranslations parameterTranslations, String hql) {
|
||||
long start = System.currentTimeMillis();
|
||||
ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( hql );
|
||||
long end = System.currentTimeMillis();
|
||||
final long start = System.currentTimeMillis();
|
||||
final ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( hql );
|
||||
final long end = System.currentTimeMillis();
|
||||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "HQL param location recognition took {0} mills ({1})", ( end - start ), hql );
|
||||
}
|
||||
|
||||
int ordinalParamCount = parameterTranslations.getOrdinalParameterCount();
|
||||
int[] locations = ArrayHelper.toIntArray( recognizer.getOrdinalParameterLocationList() );
|
||||
final int[] locations = ArrayHelper.toIntArray( recognizer.getOrdinalParameterLocationList() );
|
||||
if ( parameterTranslations.supportsOrdinalParameterMetadata() && locations.length != ordinalParamCount ) {
|
||||
throw new HibernateException( "ordinal parameter mismatch" );
|
||||
}
|
||||
ordinalParamCount = locations.length;
|
||||
OrdinalParameterDescriptor[] ordinalParamDescriptors = new OrdinalParameterDescriptor[ordinalParamCount];
|
||||
|
||||
final OrdinalParameterDescriptor[] ordinalParamDescriptors = new OrdinalParameterDescriptor[ordinalParamCount];
|
||||
for ( int i = 1; i <= ordinalParamCount; i++ ) {
|
||||
ordinalParamDescriptors[ i - 1 ] = new OrdinalParameterDescriptor(
|
||||
i,
|
||||
parameterTranslations.supportsOrdinalParameterMetadata()
|
||||
? parameterTranslations.getOrdinalParameterExpectedType( i )
|
||||
: null,
|
||||
locations[ i - 1 ]
|
||||
parameterTranslations.supportsOrdinalParameterMetadata()
|
||||
? parameterTranslations.getOrdinalParameterExpectedType( i )
|
||||
: null,
|
||||
locations[ i - 1 ]
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
|
||||
Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
|
||||
final Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
|
||||
final Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
|
||||
for ( final String name : map.keySet() ) {
|
||||
final ParamLocationRecognizer.NamedParameterDescription description = map.get( name );
|
||||
namedParamDescriptorMap.put(
|
||||
|
@ -325,9 +385,15 @@ public class HQLQueryPlan implements Serializable {
|
|||
}
|
||||
return new ParameterMetadata( ordinalParamDescriptors, namedParamDescriptorMap );
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the underlying translators associated with this query
|
||||
*
|
||||
* @return The translators
|
||||
*/
|
||||
public QueryTranslator[] getTranslators() {
|
||||
QueryTranslator[] copy = new QueryTranslator[translators.length];
|
||||
System.arraycopy(translators, 0, copy, 0, copy.length);
|
||||
final QueryTranslator[] copy = new QueryTranslator[translators.length];
|
||||
System.arraycopy( translators, 0, copy, 0, copy.length );
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, 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 Middleware LLC.
|
||||
* 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
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.engine.query.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -38,6 +38,14 @@ public class NamedParameterDescriptor implements Serializable {
|
|||
private final int[] sourceLocations;
|
||||
private final boolean jpaStyle;
|
||||
|
||||
/**
|
||||
* Constructs a NamedParameterDescriptor
|
||||
*
|
||||
* @param name The name of the parameter
|
||||
* @param expectedType The expected type of the parameter, according to the translator
|
||||
* @param sourceLocations The locations of the named parameters (aye aye aye)
|
||||
* @param jpaStyle Was the parameter a JPA style "named parameter"?
|
||||
*/
|
||||
public NamedParameterDescriptor(String name, Type expectedType, int[] sourceLocations, boolean jpaStyle) {
|
||||
this.name = name;
|
||||
this.expectedType = expectedType;
|
||||
|
@ -61,6 +69,11 @@ public class NamedParameterDescriptor implements Serializable {
|
|||
return jpaStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameters expected type
|
||||
*
|
||||
* @param type The new expected type
|
||||
*/
|
||||
public void resetExpectedType(Type type) {
|
||||
this.expectedType = type;
|
||||
}
|
||||
|
|
|
@ -30,8 +30,6 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.action.internal.BulkOperationCleanupAction;
|
||||
|
@ -41,6 +39,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.loader.custom.sql.SQLCustomQuery;
|
||||
|
@ -52,10 +51,7 @@ import org.hibernate.type.Type;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NativeSQLQueryPlan implements Serializable {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
NativeSQLQueryPlan.class.getName()
|
||||
);
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( NativeSQLQueryPlan.class );
|
||||
|
||||
private final String sourceQuery;
|
||||
private final SQLCustomQuery customQuery;
|
||||
|
@ -87,7 +83,7 @@ public class NativeSQLQueryPlan implements Serializable {
|
|||
}
|
||||
|
||||
private int[] getNamedParameterLocs(String name) throws QueryException {
|
||||
Object loc = customQuery.getNamedParameterBindPoints().get( name );
|
||||
final Object loc = customQuery.getNamedParameterBindPoints().get( name );
|
||||
if ( loc == null ) {
|
||||
throw new QueryException(
|
||||
"Named parameter does not appear in Query: " + name,
|
||||
|
@ -154,60 +150,73 @@ public class NativeSQLQueryPlan implements Serializable {
|
|||
final SessionImplementor session) throws SQLException {
|
||||
if ( namedParams != null ) {
|
||||
// assumes that types are all of span 1
|
||||
Iterator iter = namedParams.entrySet().iterator();
|
||||
final Iterator iter = namedParams.entrySet().iterator();
|
||||
int result = 0;
|
||||
while ( iter.hasNext() ) {
|
||||
Map.Entry e = (Map.Entry) iter.next();
|
||||
String name = (String) e.getKey();
|
||||
TypedValue typedval = (TypedValue) e.getValue();
|
||||
int[] locs = getNamedParameterLocs( name );
|
||||
for (int i = 0; i < locs.length; i++) {
|
||||
LOG.debugf("bindNamedParameters() %s -> %s [%s]", typedval.getValue(), name, locs[i] + start);
|
||||
typedval.getType().nullSafeSet( ps, typedval.getValue(),
|
||||
locs[i] + start, session );
|
||||
final Map.Entry e = (Map.Entry) iter.next();
|
||||
final String name = (String) e.getKey();
|
||||
final TypedValue typedval = (TypedValue) e.getValue();
|
||||
final int[] locs = getNamedParameterLocs( name );
|
||||
for ( int loc : locs ) {
|
||||
LOG.debugf( "bindNamedParameters() %s -> %s [%s]", typedval.getValue(), name, loc + start );
|
||||
typedval.getType().nullSafeSet(
|
||||
ps,
|
||||
typedval.getValue(),
|
||||
loc + start,
|
||||
session
|
||||
);
|
||||
}
|
||||
result += locs.length;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void coordinateSharedCacheCleanup(SessionImplementor session) {
|
||||
BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, getCustomQuery().getQuerySpaces() );
|
||||
final BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, getCustomQuery().getQuerySpaces() );
|
||||
|
||||
if ( session.isEventSource() ) {
|
||||
( ( EventSource ) session ).getActionQueue().addAction( action );
|
||||
( (EventSource) session ).getActionQueue().addAction( action );
|
||||
}
|
||||
else {
|
||||
action.getAfterTransactionCompletionProcess().doAfterTransactionCompletion( true, session );
|
||||
}
|
||||
}
|
||||
|
||||
public int performExecuteUpdate(QueryParameters queryParameters,
|
||||
/**
|
||||
* Performs the execute query
|
||||
*
|
||||
* @param queryParameters The query parameters
|
||||
* @param session The session
|
||||
*
|
||||
* @return The number of affected rows as returned by the JDBC driver
|
||||
*
|
||||
* @throws HibernateException Indicates a problem performing the query execution
|
||||
*/
|
||||
public int performExecuteUpdate(
|
||||
QueryParameters queryParameters,
|
||||
SessionImplementor session) throws HibernateException {
|
||||
|
||||
coordinateSharedCacheCleanup( session );
|
||||
|
||||
if(queryParameters.isCallable()) {
|
||||
if ( queryParameters.isCallable() ) {
|
||||
throw new IllegalArgumentException("callable not yet supported for native queries");
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
PreparedStatement ps;
|
||||
try {
|
||||
queryParameters.processFilters( this.customQuery.getSQL(),
|
||||
session );
|
||||
String sql = queryParameters.getFilteredSQL();
|
||||
queryParameters.processFilters( this.customQuery.getSQL(), session );
|
||||
final String sql = queryParameters.getFilteredSQL();
|
||||
|
||||
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
|
||||
|
||||
try {
|
||||
int col = 1;
|
||||
col += bindPositionalParameters( ps, queryParameters, col,
|
||||
session );
|
||||
col += bindNamedParameters( ps, queryParameters
|
||||
.getNamedParameters(), col, session );
|
||||
col += bindPositionalParameters( ps, queryParameters, col, session );
|
||||
col += bindNamedParameters( ps, queryParameters.getNamedParameters(), col, session );
|
||||
result = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
|
||||
}
|
||||
finally {
|
||||
|
@ -218,7 +227,10 @@ public class NativeSQLQueryPlan implements Serializable {
|
|||
}
|
||||
catch (SQLException sqle) {
|
||||
throw session.getFactory().getSQLExceptionHelper().convert(
|
||||
sqle, "could not execute native bulk manipulation query", this.sourceQuery );
|
||||
sqle,
|
||||
"could not execute native bulk manipulation query",
|
||||
this.sourceQuery
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, 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 Middleware LLC.
|
||||
* 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
|
||||
|
@ -20,14 +20,16 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.engine.query.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Descriptor regarding an ordinal parameter.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class OrdinalParameterDescriptor implements Serializable {
|
||||
|
@ -35,6 +37,13 @@ public class OrdinalParameterDescriptor implements Serializable {
|
|||
private final Type expectedType;
|
||||
private final int sourceLocation;
|
||||
|
||||
/**
|
||||
* Constructs an ordinal parameter descriptor.
|
||||
*
|
||||
* @param ordinalPosition The ordinal position
|
||||
* @param expectedType The expected type of the parameter
|
||||
* @param sourceLocation The location of the parameter
|
||||
*/
|
||||
public OrdinalParameterDescriptor(int ordinalPosition, Type expectedType, int sourceLocation) {
|
||||
this.ordinalPosition = ordinalPosition;
|
||||
this.expectedType = expectedType;
|
||||
|
|
|
@ -38,12 +38,14 @@ import org.hibernate.internal.util.collections.ArrayHelper;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ParamLocationRecognizer implements ParameterParser.Recognizer {
|
||||
|
||||
/**
|
||||
* Internal representation of a recognized named parameter
|
||||
*/
|
||||
public static class NamedParameterDescription {
|
||||
private final boolean jpaStyle;
|
||||
private final List<Integer> positions = new ArrayList<Integer>();
|
||||
|
||||
public NamedParameterDescription(boolean jpaStyle) {
|
||||
NamedParameterDescription(boolean jpaStyle) {
|
||||
this.jpaStyle = jpaStyle;
|
||||
}
|
||||
|
||||
|
@ -71,7 +73,7 @@ public class ParamLocationRecognizer implements ParameterParser.Recognizer {
|
|||
* @return The generated recognizer, with journaled location info.
|
||||
*/
|
||||
public static ParamLocationRecognizer parseLocations(String query) {
|
||||
ParamLocationRecognizer recognizer = new ParamLocationRecognizer();
|
||||
final ParamLocationRecognizer recognizer = new ParamLocationRecognizer();
|
||||
ParameterParser.parse( query, recognizer );
|
||||
return recognizer;
|
||||
}
|
||||
|
@ -88,8 +90,8 @@ public class ParamLocationRecognizer implements ParameterParser.Recognizer {
|
|||
|
||||
/**
|
||||
* Returns the list of ordinal parameter locations. The list elements
|
||||
* are Integers, representing the location for that given ordinal. Thus
|
||||
* {@link #getOrdinalParameterLocationList()}.elementAt(n) represents the
|
||||
* are Integers, representing the location for that given ordinal. Thus calling
|
||||
* {@code getOrdinalParameterLocationList().elementAt(n)} represents the
|
||||
* location for the nth parameter.
|
||||
*
|
||||
* @return The list of ordinal parameter locations.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, 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 Middleware LLC.
|
||||
* 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
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.engine.query.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -37,33 +37,35 @@ import org.hibernate.type.Type;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ParameterMetadata implements Serializable {
|
||||
|
||||
private static final OrdinalParameterDescriptor[] EMPTY_ORDINALS = new OrdinalParameterDescriptor[0];
|
||||
|
||||
private final OrdinalParameterDescriptor[] ordinalDescriptors;
|
||||
private final Map namedDescriptorMap;
|
||||
private final Map<String,NamedParameterDescriptor> namedDescriptorMap;
|
||||
|
||||
/**
|
||||
* Instantiates a ParameterMetadata container.
|
||||
*
|
||||
* @param ordinalDescriptors
|
||||
* @param namedDescriptorMap
|
||||
* @param ordinalDescriptors Descriptors of the ordinal parameters
|
||||
* @param namedDescriptorMap Descriptors of the named parameters
|
||||
*/
|
||||
public ParameterMetadata(OrdinalParameterDescriptor[] ordinalDescriptors, Map namedDescriptorMap) {
|
||||
public ParameterMetadata(
|
||||
OrdinalParameterDescriptor[] ordinalDescriptors,
|
||||
Map<String,NamedParameterDescriptor> namedDescriptorMap) {
|
||||
if ( ordinalDescriptors == null ) {
|
||||
this.ordinalDescriptors = EMPTY_ORDINALS;
|
||||
}
|
||||
else {
|
||||
OrdinalParameterDescriptor[] copy = new OrdinalParameterDescriptor[ ordinalDescriptors.length ];
|
||||
final OrdinalParameterDescriptor[] copy = new OrdinalParameterDescriptor[ ordinalDescriptors.length ];
|
||||
System.arraycopy( ordinalDescriptors, 0, copy, 0, ordinalDescriptors.length );
|
||||
this.ordinalDescriptors = copy;
|
||||
}
|
||||
|
||||
if ( namedDescriptorMap == null ) {
|
||||
this.namedDescriptorMap = java.util.Collections.EMPTY_MAP;
|
||||
this.namedDescriptorMap = java.util.Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
int size = ( int ) ( ( namedDescriptorMap.size() / .75 ) + 1 );
|
||||
Map copy = new HashMap( size );
|
||||
final int size = (int) ( ( namedDescriptorMap.size() / .75 ) + 1 );
|
||||
final Map<String,NamedParameterDescriptor> copy = new HashMap<String,NamedParameterDescriptor>( size );
|
||||
copy.putAll( namedDescriptorMap );
|
||||
this.namedDescriptorMap = java.util.Collections.unmodifiableMap( copy );
|
||||
}
|
||||
|
@ -73,39 +75,107 @@ public class ParameterMetadata implements Serializable {
|
|||
return ordinalDescriptors.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the descriptor for an ordinal parameter given its position
|
||||
*
|
||||
* @param position The position (1 based)
|
||||
*
|
||||
* @return The ordinal parameter descriptor
|
||||
*
|
||||
* @throws QueryParameterException If the position is out of range
|
||||
*/
|
||||
public OrdinalParameterDescriptor getOrdinalParameterDescriptor(int position) {
|
||||
if ( position < 1 || position > ordinalDescriptors.length ) {
|
||||
String error = "Position beyond number of declared ordinal parameters. " +
|
||||
"Remember that ordinal parameters are 1-based! Position: " + position;
|
||||
throw new QueryParameterException( error );
|
||||
throw new QueryParameterException(
|
||||
"Position beyond number of declared ordinal parameters. " +
|
||||
"Remember that ordinal parameters are 1-based! Position: " + position
|
||||
);
|
||||
}
|
||||
return ordinalDescriptors[position - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @param position The position
|
||||
*
|
||||
* @return The type
|
||||
*
|
||||
* @deprecated Use {@link OrdinalParameterDescriptor#getExpectedType()} from the
|
||||
* {@link #getOrdinalParameterDescriptor} return instead
|
||||
*/
|
||||
@Deprecated
|
||||
public Type getOrdinalParameterExpectedType(int position) {
|
||||
return getOrdinalParameterDescriptor( position ).getExpectedType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @param position The position
|
||||
*
|
||||
* @return The source location
|
||||
*
|
||||
* @deprecated Use {@link OrdinalParameterDescriptor#getSourceLocation()} from the
|
||||
* {@link #getOrdinalParameterDescriptor} return instead
|
||||
*/
|
||||
@Deprecated
|
||||
public int getOrdinalParameterSourceLocation(int position) {
|
||||
return getOrdinalParameterDescriptor( position ).getSourceLocation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the names of all named parameters
|
||||
*
|
||||
* @return The named parameter names
|
||||
*/
|
||||
public Set getNamedParameterNames() {
|
||||
return namedDescriptorMap.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the descriptor for a named parameter given the name
|
||||
*
|
||||
* @param name The name of the parameter to locate
|
||||
*
|
||||
* @return The named parameter descriptor
|
||||
*
|
||||
* @throws QueryParameterException If the name could not be resolved to a named parameter
|
||||
*/
|
||||
public NamedParameterDescriptor getNamedParameterDescriptor(String name) {
|
||||
NamedParameterDescriptor meta = ( NamedParameterDescriptor ) namedDescriptorMap.get( name );
|
||||
final NamedParameterDescriptor meta = namedDescriptorMap.get( name );
|
||||
if ( meta == null ) {
|
||||
throw new QueryParameterException( "could not locate named parameter [" + name + "]" );
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @param name The name of the parameter
|
||||
*
|
||||
* @return The type
|
||||
*
|
||||
* @deprecated Use {@link NamedParameterDescriptor#getExpectedType()} from the
|
||||
* {@link #getNamedParameterDescriptor} return instead
|
||||
*/
|
||||
@Deprecated
|
||||
public Type getNamedParameterExpectedType(String name) {
|
||||
return getNamedParameterDescriptor( name ).getExpectedType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @param name The name of the parameter
|
||||
*
|
||||
* @return The type
|
||||
*
|
||||
* @deprecated Use {@link NamedParameterDescriptor#getSourceLocations()} from the
|
||||
* {@link #getNamedParameterDescriptor} return instead
|
||||
*/
|
||||
@Deprecated
|
||||
public int[] getNamedParameterSourceLocations(String name) {
|
||||
return getNamedParameterDescriptor( name ).getSourceLocations();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, 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 Middleware LLC.
|
||||
* 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
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.engine.query.spi;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.hql.internal.classic.ParserHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
@ -36,12 +36,45 @@ import org.hibernate.internal.util.StringHelper;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ParameterParser {
|
||||
|
||||
/**
|
||||
* Maybe better named a Journaler. Essentially provides a callback contract for things that recognize parameters
|
||||
*/
|
||||
public static interface Recognizer {
|
||||
/**
|
||||
* Called when an output parameter is recognized
|
||||
*
|
||||
* @param position The position within the query
|
||||
*/
|
||||
public void outParameter(int position);
|
||||
|
||||
/**
|
||||
* Called when an ordinal parameter is recognized
|
||||
*
|
||||
* @param position The position within the query
|
||||
*/
|
||||
public void ordinalParameter(int position);
|
||||
|
||||
/**
|
||||
* Called when a named parameter is recognized
|
||||
*
|
||||
* @param name The recognized parameter name
|
||||
* @param position The position within the query
|
||||
*/
|
||||
public void namedParameter(String name, int position);
|
||||
|
||||
/**
|
||||
* Called when a JPA-style named parameter is recognized
|
||||
*
|
||||
* @param name The name of the JPA-style parameter
|
||||
* @param position The position within the query
|
||||
*/
|
||||
public void jpaPositionalParameter(String name, int position);
|
||||
|
||||
/**
|
||||
* Called when a character that is not a parameter (or part of a parameter dfinition) is recognized.
|
||||
*
|
||||
* @param character The recognized character
|
||||
*/
|
||||
public void other(char character);
|
||||
}
|
||||
|
||||
|
@ -64,13 +97,13 @@ public class ParameterParser {
|
|||
* @throws QueryException Indicates unexpected parameter conditions.
|
||||
*/
|
||||
public static void parse(String sqlString, Recognizer recognizer) throws QueryException {
|
||||
boolean hasMainOutputParameter = startsWithEscapeCallTemplate( sqlString );
|
||||
final boolean hasMainOutputParameter = startsWithEscapeCallTemplate( sqlString );
|
||||
boolean foundMainOutputParam = false;
|
||||
|
||||
int stringLength = sqlString.length();
|
||||
final int stringLength = sqlString.length();
|
||||
boolean inQuote = false;
|
||||
for ( int indx = 0; indx < stringLength; indx++ ) {
|
||||
char c = sqlString.charAt( indx );
|
||||
final char c = sqlString.charAt( indx );
|
||||
if ( inQuote ) {
|
||||
if ( '\'' == c ) {
|
||||
inQuote = false;
|
||||
|
@ -88,9 +121,9 @@ public class ParameterParser {
|
|||
else {
|
||||
if ( c == ':' ) {
|
||||
// named parameter
|
||||
int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS_BITSET, indx + 1 );
|
||||
int chopLocation = right < 0 ? sqlString.length() : right;
|
||||
String param = sqlString.substring( indx + 1, chopLocation );
|
||||
final int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS_BITSET, indx + 1 );
|
||||
final int chopLocation = right < 0 ? sqlString.length() : right;
|
||||
final String param = sqlString.substring( indx + 1, chopLocation );
|
||||
if ( StringHelper.isEmpty( param ) ) {
|
||||
throw new QueryException(
|
||||
"Space is not allowed after parameter prefix ':' [" + sqlString + "]"
|
||||
|
@ -103,12 +136,12 @@ public class ParameterParser {
|
|||
// could be either an ordinal or JPA-positional parameter
|
||||
if ( indx < stringLength - 1 && Character.isDigit( sqlString.charAt( indx + 1 ) ) ) {
|
||||
// a peek ahead showed this as an JPA-positional parameter
|
||||
int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS, indx + 1 );
|
||||
int chopLocation = right < 0 ? sqlString.length() : right;
|
||||
String param = sqlString.substring( indx + 1, chopLocation );
|
||||
final int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS, indx + 1 );
|
||||
final int chopLocation = right < 0 ? sqlString.length() : right;
|
||||
final String param = sqlString.substring( indx + 1, chopLocation );
|
||||
// make sure this "name" is an integral
|
||||
try {
|
||||
Integer.valueOf( param );
|
||||
Integer.valueOf( param );
|
||||
}
|
||||
catch( NumberFormatException e ) {
|
||||
throw new QueryException( "JPA-style positional param was not an integral ordinal" );
|
||||
|
@ -133,12 +166,19 @@ public class ParameterParser {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposed as public solely for use from tests
|
||||
*
|
||||
* @param sqlString The SQL string to check
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean startsWithEscapeCallTemplate(String sqlString) {
|
||||
if ( ! ( sqlString.startsWith( "{" ) && sqlString.endsWith( "}" ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int chopLocation = sqlString.indexOf( "call" );
|
||||
final int chopLocation = sqlString.indexOf( "call" );
|
||||
if ( chopLocation <= 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
@ -147,7 +187,8 @@ public class ParameterParser {
|
|||
final String fixture = "?=call";
|
||||
int fixturePosition = 0;
|
||||
boolean matches = true;
|
||||
for ( int i = 0, max = checkString.length(); i < max; i++ ) {
|
||||
final int max = checkString.length();
|
||||
for ( int i = 0; i < max; i++ ) {
|
||||
final char c = Character.toLowerCase( checkString.charAt( i ) );
|
||||
if ( Character.isWhitespace( c ) ) {
|
||||
continue;
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.engine.query.spi;
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Defines metadata regarding a translated HQL or native-SQL query.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QueryMetadata implements Serializable {
|
||||
private final String sourceQuery;
|
||||
private final ParameterMetadata parameterMetadata;
|
||||
private final String[] returnAliases;
|
||||
private final Type[] returnTypes;
|
||||
private final Set querySpaces;
|
||||
|
||||
public QueryMetadata(
|
||||
String sourceQuery,
|
||||
ParameterMetadata parameterMetadata,
|
||||
String[] returnAliases,
|
||||
Type[] returnTypes,
|
||||
Set querySpaces) {
|
||||
this.sourceQuery = sourceQuery;
|
||||
this.parameterMetadata = parameterMetadata;
|
||||
this.returnAliases = returnAliases;
|
||||
this.returnTypes = returnTypes;
|
||||
this.querySpaces = querySpaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source HQL or native-SQL query.
|
||||
*
|
||||
* @return The source query.
|
||||
*/
|
||||
public String getSourceQuery() {
|
||||
return sourceQuery;
|
||||
}
|
||||
|
||||
public ParameterMetadata getParameterMetadata() {
|
||||
return parameterMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return source query select clause aliases (if any)
|
||||
*
|
||||
* @return an array of aliases as strings.
|
||||
*/
|
||||
public String[] getReturnAliases() {
|
||||
return returnAliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of types describing the returns of the source query.
|
||||
*
|
||||
* @return The return type array.
|
||||
*/
|
||||
public Type[] getReturnTypes() {
|
||||
return returnTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* The set of query spaces affected by this source query.
|
||||
*
|
||||
* @return The set of query spaces.
|
||||
*/
|
||||
public Set getQuerySpaces() {
|
||||
return querySpaces;
|
||||
}
|
||||
}
|
|
@ -28,17 +28,16 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.FilterImpl;
|
||||
import org.hibernate.internal.util.collections.BoundedConcurrentHashMap;
|
||||
|
@ -54,9 +53,8 @@ import org.hibernate.internal.util.config.ConfigurationHelper;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QueryPlanCache implements Serializable {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QueryPlanCache.class );
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, QueryPlanCache.class.getName());
|
||||
|
||||
/**
|
||||
* The default strong reference count.
|
||||
*/
|
||||
|
@ -65,11 +63,14 @@ public class QueryPlanCache implements Serializable {
|
|||
* The default soft reference count.
|
||||
*/
|
||||
public static final int DEFAULT_QUERY_PLAN_MAX_COUNT = 2048;
|
||||
|
||||
private final SessionFactoryImplementor factory;
|
||||
|
||||
/**
|
||||
* the cache of the actual plans...
|
||||
*/
|
||||
private final BoundedConcurrentHashMap queryPlanCache;
|
||||
|
||||
/**
|
||||
* simple cache of param metadata based on query string. Ideally, the original "user-supplied query"
|
||||
* string should be used to obtain this metadata (i.e., not the para-list-expanded query string) to avoid
|
||||
|
@ -80,6 +81,12 @@ public class QueryPlanCache implements Serializable {
|
|||
*/
|
||||
private final BoundedConcurrentHashMap<String,ParameterMetadata> parameterMetadataCache;
|
||||
|
||||
/**
|
||||
* Constructs the QueryPlanCache to be used by the given SessionFactory
|
||||
*
|
||||
* @param factory The SessionFactory
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public QueryPlanCache(final SessionFactoryImplementor factory) {
|
||||
this.factory = factory;
|
||||
|
||||
|
@ -135,15 +142,17 @@ public class QueryPlanCache implements Serializable {
|
|||
}
|
||||
|
||||
private ParameterMetadata buildParameterMetadata(String query){
|
||||
ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( query );
|
||||
final ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( query );
|
||||
|
||||
final int size = recognizer.getOrdinalParameterLocationList().size();
|
||||
OrdinalParameterDescriptor[] ordinalDescriptors = new OrdinalParameterDescriptor[ size ];
|
||||
final OrdinalParameterDescriptor[] ordinalDescriptors = new OrdinalParameterDescriptor[ size ];
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
final Integer position = recognizer.getOrdinalParameterLocationList().get( i );
|
||||
ordinalDescriptors[i] = new OrdinalParameterDescriptor( i, null, position );
|
||||
}
|
||||
Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
|
||||
Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
|
||||
|
||||
final Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
|
||||
final Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
|
||||
for ( final String name : map.keySet() ) {
|
||||
final ParamLocationRecognizer.NamedParameterDescription description = map.get( name );
|
||||
namedParamDescriptorMap.put(
|
||||
|
@ -159,9 +168,22 @@ public class QueryPlanCache implements Serializable {
|
|||
return new ParameterMetadata( ordinalDescriptors, namedParamDescriptorMap );
|
||||
}
|
||||
|
||||
public HQLQueryPlan getHQLQueryPlan( String queryString, boolean shallow, Map enabledFilters)
|
||||
/**
|
||||
* Get the query plan for the given HQL query, creating it and caching it if not already cached
|
||||
*
|
||||
* @param queryString The HQL query string
|
||||
* @param shallow Whether the execution will be shallow
|
||||
* @param enabledFilters The filters enabled on the Session
|
||||
*
|
||||
* @return The query plan
|
||||
*
|
||||
* @throws QueryException Indicates a problem translating the query
|
||||
* @throws MappingException Indicates a problem translating the query
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public HQLQueryPlan getHQLQueryPlan(String queryString, boolean shallow, Map<String,Filter> enabledFilters)
|
||||
throws QueryException, MappingException {
|
||||
HQLQueryPlanKey key = new HQLQueryPlanKey( queryString, shallow, enabledFilters );
|
||||
final HQLQueryPlanKey key = new HQLQueryPlanKey( queryString, shallow, enabledFilters );
|
||||
HQLQueryPlan value = (HQLQueryPlan) queryPlanCache.get( key );
|
||||
if ( value == null ) {
|
||||
LOG.tracev( "Unable to locate HQL query plan in cache; generating ({0})", queryString );
|
||||
|
@ -173,37 +195,69 @@ public class QueryPlanCache implements Serializable {
|
|||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public FilterQueryPlan getFilterQueryPlan(String filterString, String collectionRole, boolean shallow, Map enabledFilters)
|
||||
throws QueryException, MappingException {
|
||||
FilterQueryPlanKey key = new FilterQueryPlanKey( filterString, collectionRole, shallow, enabledFilters );
|
||||
/**
|
||||
* Get the query plan for the given collection HQL filter fragment, creating it and caching it if not already cached
|
||||
*
|
||||
* @param filterString The HQL filter fragment
|
||||
* @param collectionRole The collection being filtered
|
||||
* @param shallow Whether the execution will be shallow
|
||||
* @param enabledFilters The filters enabled on the Session
|
||||
*
|
||||
* @return The query plan
|
||||
*
|
||||
* @throws QueryException Indicates a problem translating the query
|
||||
* @throws MappingException Indicates a problem translating the query
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public FilterQueryPlan getFilterQueryPlan(
|
||||
String filterString,
|
||||
String collectionRole,
|
||||
boolean shallow,
|
||||
Map<String,Filter> enabledFilters) throws QueryException, MappingException {
|
||||
final FilterQueryPlanKey key = new FilterQueryPlanKey( filterString, collectionRole, shallow, enabledFilters );
|
||||
FilterQueryPlan value = (FilterQueryPlan) queryPlanCache.get( key );
|
||||
if(value == null){
|
||||
LOG.tracev( "Unable to locate collection-filter query plan in cache; generating ({0} : {1} )",
|
||||
collectionRole, filterString );
|
||||
if ( value == null ) {
|
||||
LOG.tracev(
|
||||
"Unable to locate collection-filter query plan in cache; generating ({0} : {1} )",
|
||||
collectionRole,
|
||||
filterString
|
||||
);
|
||||
value = new FilterQueryPlan( filterString, collectionRole, shallow, enabledFilters,factory );
|
||||
queryPlanCache.putIfAbsent( key, value );
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
LOG.tracev( "Located collection-filter query plan in cache ({0} : {1})", collectionRole, filterString );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query plan for a native SQL query, creating it and caching it if not already cached
|
||||
*
|
||||
* @param spec The native SQL query specification
|
||||
*
|
||||
* @return The query plan
|
||||
*
|
||||
* @throws QueryException Indicates a problem translating the query
|
||||
* @throws MappingException Indicates a problem translating the query
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public NativeSQLQueryPlan getNativeSQLQueryPlan(final NativeSQLQuerySpecification spec) {
|
||||
NativeSQLQueryPlan value = (NativeSQLQueryPlan) queryPlanCache.get( spec );
|
||||
if(value == null){
|
||||
if ( value == null ) {
|
||||
LOG.tracev( "Unable to locate native-sql query plan in cache; generating ({0})", spec.getQueryString() );
|
||||
value = new NativeSQLQueryPlan( spec, factory);
|
||||
queryPlanCache.putIfAbsent( spec, value );
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
LOG.tracev( "Located native-sql query plan in cache ({0})", spec.getQueryString() );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
//clean up QueryPlanCache when Sessionfactory is closed
|
||||
/**
|
||||
* clean up QueryPlanCache when SessionFactory is closed
|
||||
*/
|
||||
public void cleanup() {
|
||||
LOG.trace( "Cleaning QueryPlan Cache" );
|
||||
queryPlanCache.clear();
|
||||
|
@ -223,7 +277,7 @@ public class QueryPlanCache implements Serializable {
|
|||
filterKeys = Collections.emptySet();
|
||||
}
|
||||
else {
|
||||
Set<DynamicFilterKey> tmp = new HashSet<DynamicFilterKey>(
|
||||
final Set<DynamicFilterKey> tmp = new HashSet<DynamicFilterKey>(
|
||||
CollectionHelper.determineProperSizing( enabledFilters ),
|
||||
CollectionHelper.LOAD_FACTOR
|
||||
);
|
||||
|
@ -248,7 +302,7 @@ public class QueryPlanCache implements Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
final HQLQueryPlanKey that = ( HQLQueryPlanKey ) o;
|
||||
final HQLQueryPlanKey that = (HQLQueryPlanKey) o;
|
||||
|
||||
return shallow == that.shallow
|
||||
&& filterKeys.equals( that.filterKeys )
|
||||
|
@ -306,8 +360,7 @@ public class QueryPlanCache implements Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
DynamicFilterKey that = ( DynamicFilterKey ) o;
|
||||
|
||||
final DynamicFilterKey that = (DynamicFilterKey) o;
|
||||
return filterName.equals( that.filterName )
|
||||
&& parameterMetadata.equals( that.parameterMetadata );
|
||||
|
||||
|
@ -336,7 +389,7 @@ public class QueryPlanCache implements Serializable {
|
|||
this.filterNames = Collections.emptySet();
|
||||
}
|
||||
else {
|
||||
Set<String> tmp = new HashSet<String>();
|
||||
final Set<String> tmp = new HashSet<String>();
|
||||
tmp.addAll( enabledFilters.keySet() );
|
||||
this.filterNames = Collections.unmodifiableSet( tmp );
|
||||
|
||||
|
@ -358,8 +411,7 @@ public class QueryPlanCache implements Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
final FilterQueryPlanKey that = ( FilterQueryPlanKey ) o;
|
||||
|
||||
final FilterQueryPlanKey that = (FilterQueryPlanKey) o;
|
||||
return shallow == that.shallow
|
||||
&& filterNames.equals( that.filterNames )
|
||||
&& query.equals( that.query )
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, 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 Middleware LLC.
|
||||
* 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
|
||||
|
@ -20,21 +20,23 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.engine.query.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Metadata about the query return(s).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ReturnMetadata implements Serializable {
|
||||
private final String[] returnAliases;
|
||||
private final Type[] returnTypes;
|
||||
|
||||
public ReturnMetadata(String[] returnAliases, Type[] returnTypes) {
|
||||
ReturnMetadata(String[] returnAliases, Type[] returnTypes) {
|
||||
this.returnAliases = returnAliases;
|
||||
this.returnTypes = returnTypes;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Defines support for query plans and stored metadata about queries
|
||||
*/
|
||||
package org.hibernate.engine.query.spi;
|
Loading…
Reference in New Issue