HHH-7387 - Integrate Draft 6 of the JPA 2.1 spec : addNamedQuery support

This commit is contained in:
Steve Ebersole 2012-06-20 17:43:43 -05:00
parent 00059fee2f
commit 3edb72db48
24 changed files with 1548 additions and 510 deletions

View File

@ -20,10 +20,11 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate;
import org.hibernate.tool.hbm2ddl.SchemaExportTask;
/**
* Controls how the session interacts with the second-level
* cache and query cache.
@ -77,4 +78,28 @@ public enum CacheMode {
public boolean isPutEnabled() {
return isPutEnabled;
}
public static CacheMode interpretExternalSetting(String setting) {
if (setting == null) {
return null;
}
if ( GET.name().equalsIgnoreCase( setting ) ) {
return CacheMode.GET;
}
if ( IGNORE.name().equalsIgnoreCase( setting ) ) {
return CacheMode.IGNORE;
}
if ( NORMAL.name().equalsIgnoreCase( setting ) ) {
return CacheMode.NORMAL;
}
if ( PUT.name().equalsIgnoreCase( setting ) ) {
return CacheMode.PUT;
}
if ( REFRESH.name().equalsIgnoreCase( setting ) ) {
return CacheMode.REFRESH;
}
throw new MappingException( "Unknown Cache Mode: " + setting );
}
}

View File

@ -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 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,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate;
@ -84,4 +83,28 @@ public enum FlushMode {
public static boolean isManualFlushMode(FlushMode mode) {
return MANUAL.level == mode.level;
}
public static FlushMode interpretExternalSetting(String setting) {
if ( setting == null ) {
return null;
}
if ( AUTO.name().equalsIgnoreCase( setting ) ) {
return FlushMode.AUTO;
}
if ( COMMIT.name().equalsIgnoreCase( setting ) ) {
return FlushMode.COMMIT;
}
if ( NEVER.name().equalsIgnoreCase( setting ) ) {
return FlushMode.NEVER;
}
if ( MANUAL.name().equalsIgnoreCase( setting ) ) {
return FlushMode.MANUAL;
}
if ( ALWAYS.name().equalsIgnoreCase( setting ) ) {
return FlushMode.ALWAYS;
}
throw new MappingException( "unknown FlushMode : " + setting );
}
}

View File

@ -238,6 +238,12 @@ public class LockOptions implements Serializable {
return this;
}
public LockOptions makeCopy() {
final LockOptions copy = new LockOptions();
copy( this, copy );
return copy;
}
/**
* Shallow copy From to Dest
*

View File

@ -74,6 +74,7 @@ import org.hibernate.type.Type;
*
* @see org.hibernate.Session#createQuery(java.lang.String)
* @see org.hibernate.ScrollableResults
*
* @author Gavin King
*/
public interface Query {
@ -83,96 +84,232 @@ public interface Query {
* @return the query string
*/
public String getQueryString();
/**
* Return the Hibernate types of the query result set.
* @return an array of types
*/
public Type[] getReturnTypes() throws HibernateException;
/**
* Return the HQL select clause aliases (if any)
* @return an array of aliases as strings
*/
public String[] getReturnAliases() throws HibernateException;
/**
* Return the names of all named parameters of the query.
* @return the parameter names, in no particular order
*/
public String[] getNamedParameters() throws HibernateException;
/**
* Return the query results as an <tt>Iterator</tt>. If the query
* contains multiple results pre row, the results are returned in
* an instance of <tt>Object[]</tt>.<br>
* <br>
* Entities returned as results are initialized on demand. The first
* SQL query returns identifiers only.<br>
*
* @return the result iterator
* @throws HibernateException
*/
public Iterator iterate() throws HibernateException;
/**
* Return the query results as <tt>ScrollableResults</tt>. The
* scrollability of the returned results depends upon JDBC driver
* support for scrollable <tt>ResultSet</tt>s.<br>
*
* @see ScrollableResults
* @return the result iterator
* @throws HibernateException
*/
public ScrollableResults scroll() throws HibernateException;
/**
* Return the query results as <tt>ScrollableResults</tt>. The
* scrollability of the returned results depends upon JDBC driver
* support for scrollable <tt>ResultSet</tt>s.<br>
*
* @see ScrollableResults
* @see ScrollMode
* @return the result iterator
* @throws HibernateException
*/
public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException;
/**
* Return the query results as a <tt>List</tt>. If the query contains
* multiple results pre row, the results are returned in an instance
* of <tt>Object[]</tt>.
*
* @return the result list
* @throws HibernateException
*/
public List list() throws HibernateException;
/**
* Convenience method to return a single instance that matches
* the query, or null if the query returns no results.
*
* @return the single result or <tt>null</tt>
* @throws NonUniqueResultException if there is more than one matching result
*/
public Object uniqueResult() throws HibernateException;
/**
* Execute the update or delete statement.
* </p>
* The semantics are compliant with the ejb3 Query.executeUpdate()
* method.
* Obtains the limit set on the maximum number of rows to retrieve. No set limit means there is no limit set
* on the number of rows returned. Technically both {@code null} and any negative values are interpreted as no
* limit; however, this method should always return null in such case.
*
* @return The number of entities updated or deleted.
* @throws HibernateException
* @return The
*/
public int executeUpdate() throws HibernateException;
public Integer getMaxResults();
/**
* Set the maximum number of rows to retrieve. If not set,
* there is no limit to the number of rows retrieved.
* Set the maximum number of rows to retrieve.
*
* @param maxResults the maximum number of rows
*
* @see #getMaxResults()
*/
public Query setMaxResults(int maxResults);
/**
* Set the first row to retrieve. If not set, rows will be
* retrieved beginnning from row <tt>0</tt>.
* Obtain the value specified (if any) for the first row to be returned from the query results; zero-based. Used,
* in conjunction with {@link #getMaxResults()} in "paginated queries". No value specified means the first result
* is returned. Zero and negative numbers are the same as no setting.
*
* @return The first result number.
*/
public Integer getFirstResult();
/**
* Set the first row to retrieve.
*
* @param firstResult a row number, numbered from <tt>0</tt>
*
* @see #getFirstResult()
*/
public Query setFirstResult(int firstResult);
/**
* Obtain the FlushMode in effect for this query. By default, the query inherits the FlushMode of the Session
* from which is originates.
*
* @return The query FlushMode.
*
* @see Session#getFlushMode()
* @see FlushMode
*/
public FlushMode getFlushMode();
/**
* (Re)set the current FlushMode in effect for this query.
*
* @param flushMode The new FlushMode to use.
*
* @see #getFlushMode()
*/
public Query setFlushMode(FlushMode flushMode);
/**
* Obtain the CacheMode in effect for this query. By default, the query inherits the CacheMode of the Session
* from which is originates.
*
* NOTE: The CacheMode here only effects reading/writing of the query cache, not the
* entity/collection caches.
*
* @return The query CacheMode.
*
* @see Session#getCacheMode()
* @see CacheMode
*/
public CacheMode getCacheMode();
/**
* (Re)set the current CacheMode in effect for this query.
*
* @param cacheMode The new CacheMode to use.
*
* @see #getCacheMode()
*/
public Query setCacheMode(CacheMode cacheMode);
/**
* Are the results of this query eligible for second level query caching? This is different that second level
* caching of any returned entities and collections.
*
* NOTE: the query being "eligible" for caching does not necessarily mean its results will be cached. Second level
* query caching still has to be enabled on the {@link SessionFactory} for this to happen. Usually that is
* controlled by the {@code hibernate.cache.use_query_cache} configuration setting.
*
* @return {@code true} if the query results are eligible for caching, {@code false} otherwise.
*
* @see org.hibernate.cfg.AvailableSettings#USE_QUERY_CACHE
*/
public boolean isCacheable();
/**
* Enable/disable second level query (result) caching for this query.
*
* @param cacheable Should the query results be cacheable?
*
* @see #isCacheable
*/
public Query setCacheable(boolean cacheable);
/**
* Obtain the name of the second level query cache region in which query results will be stored (if they are
* cached, see the discussion on {@link #isCacheable()} for more information). {@code null} indicates that the
* default region should be used.
*
* @return The specified cache region name into which query results should be placed; {@code null} indicates
* the default region.
*/
public String getCacheRegion();
/**
* Set the name of the cache region where query results should be cached (if cached at all).
*
* @param cacheRegion the name of a query cache region, or {@code null} to indicate that the default region
* should be used.
*
* @see #getCacheRegion()
*/
public Query setCacheRegion(String cacheRegion);
/**
* Obtain the query timeout <b>in seconds</b>. This value is eventually passed along to the JDBC query via
* {@link java.sql.Statement#setQueryTimeout(int)}. Zero indicates no timeout.
*
* @return The timeout <b>in seconds</b>
*
* @see java.sql.Statement#getQueryTimeout()
* @see java.sql.Statement#setQueryTimeout(int)
*/
public Integer getTimeout();
/**
* Set the query timeout <b>in seconds</b>.
*
* NOTE it is important to understand that any value set here is eventually passed directly through to the JDBC
* Statement which expressly disallows negative values. So negative values should be avoided as a general rule.
*
* @param timeout the timeout <b>in seconds</b>
*
* @see #getTimeout()
*/
public Query setTimeout(int timeout);
/**
* Obtain the JDBC fetch size hint in effect for this query. This value is eventually passed along to the JDBC
* query via {@link java.sql.Statement#setFetchSize(int)}. As defined b y JDBC, this value is a hint to the
* driver to indicate how many rows to fetch from the database when more rows are needed.
*
* NOTE : JDBC expressly defines this value as a hint. It may or may not have any effect on the actual
* query execution and ResultSet processing depending on the driver.
*
* @return The timeout <b>in seconds</b>
*
* @see java.sql.Statement#getFetchSize()
* @see java.sql.Statement#setFetchSize(int)
*/
public Integer getFetchSize();
/**
* Sets a JDBC fetch size hint for the query.
*
* @param fetchSize the fetch size hint
*
* @see #getFetchSize()
*/
public Query setFetchSize(int fetchSize);
/**
* Obtains the LockOptions in effect for this query.
*
* @return The LockOptions
*
* @see LockOptions
*/
public LockOptions getLockOptions();
/**
* Set the lock options for the query. Specifically only the following are taken into consideration:<ol>
* <li>{@link LockOptions#getLockMode()}</li>
* <li>{@link LockOptions#getScope()}</li>
* <li>{@link LockOptions#getTimeOut()}</li>
* </ol>
* For alias-specific locking, use {@link #setLockMode(String, LockMode)}.
*
* @see #getLockOptions()
*/
public Query setLockOptions(LockOptions lockOptions);
/**
* Set the LockMode to use for specific alias (as defined in the query's <tt>FROM</tt> clause).
*
* The alias-specific lock modes specified here are added to the query's internal
* {@link #getLockOptions() LockOptions}.
*
* The effect of these alias-specific LockModes is somewhat dependent on the driver/database in use. Generally
* speaking, for maximum portability, this method should only be used to mark that the rows corresponding to
* the given alias should be included in pessimistic locking ({@link LockMode#PESSIMISTIC_WRITE}).
*
* @param alias a query alias, or <tt>this</tt> for a collection filter
*
* @see #getLockOptions()
*/
public Query setLockMode(String alias, LockMode lockMode);
/**
* Obtain the comment currently associated with this query. Provided SQL commenting is enabled
* (generally by enabling the {@code hibernate.use_sql_comments} config setting), this comment will also be added
* to the SQL query sent to the database. Often useful for identifying the source of troublesome queries on the
* database side.
*
* @return The comment.
*/
public String getComment();
/**
* Set the comment for this query.
*
* @param comment The human-readable comment
*
* @see #getComment()
*/
public Query setComment(String comment);
/**
* Should entities and proxies loaded by this Query be put in read-only mode? If the
* read-only/modifiable setting was not initialized, then the default
@ -216,61 +353,88 @@ public interface Query {
public Query setReadOnly(boolean readOnly);
/**
* Enable caching of this query result set.
* @param cacheable Should the query results be cacheable?
* Return the Hibernate types of the query result set.
* @return an array of types
*/
public Query setCacheable(boolean cacheable);
public Type[] getReturnTypes() throws HibernateException;
/**
* Set the name of the cache region.
* @param cacheRegion the name of a query cache region, or <tt>null</tt>
* for the default query cache
* Return the HQL select clause aliases (if any)
* @return an array of aliases as strings
*/
public Query setCacheRegion(String cacheRegion);
public String[] getReturnAliases() throws HibernateException;
/**
* Set a timeout for the underlying JDBC query.
* @param timeout the timeout in seconds
* Return the names of all named parameters of the query.
* @return the parameter names, in no particular order
*/
public Query setTimeout(int timeout);
/**
* Set a fetch size for the underlying JDBC query.
* @param fetchSize the fetch size
*/
public Query setFetchSize(int fetchSize);
public String[] getNamedParameters() throws HibernateException;
/**
* Set the lock options for the objects idententified by the
* given alias that appears in the <tt>FROM</tt> clause.
* Return the query results as an <tt>Iterator</tt>. If the query
* contains multiple results pre row, the results are returned in
* an instance of <tt>Object[]</tt>.<br>
* <br>
* Entities returned as results are initialized on demand. The first
* SQL query returns identifiers only.<br>
*
* @return the result iterator
* @throws HibernateException
*/
public Query setLockOptions(LockOptions lockOptions);
public Iterator iterate() throws HibernateException;
/**
* Set the lockmode for the objects idententified by the
* given alias that appears in the <tt>FROM</tt> clause.
* @param alias a query alias, or <tt>this</tt> for a collection filter
* Return the query results as <tt>ScrollableResults</tt>. The
* scrollability of the returned results depends upon JDBC driver
* support for scrollable <tt>ResultSet</tt>s.<br>
*
* @see ScrollableResults
* @return the result iterator
* @throws HibernateException
*/
public Query setLockMode(String alias, LockMode lockMode);
public ScrollableResults scroll() throws HibernateException;
/**
* Add a comment to the generated SQL.
* @param comment a human-readable string
* Return the query results as <tt>ScrollableResults</tt>. The
* scrollability of the returned results depends upon JDBC driver
* support for scrollable <tt>ResultSet</tt>s.<br>
*
* @see ScrollableResults
* @see ScrollMode
* @return the result iterator
* @throws HibernateException
*/
public Query setComment(String comment);
public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException;
/**
* Override the current session flush mode, just for
* this query.
* @see org.hibernate.FlushMode
* Return the query results as a <tt>List</tt>. If the query contains
* multiple results pre row, the results are returned in an instance
* of <tt>Object[]</tt>.
*
* @return the result list
* @throws HibernateException
*/
public Query setFlushMode(FlushMode flushMode);
public List list() throws HibernateException;
/**
* Override the current session cache mode, just for
* this query.
* @see org.hibernate.CacheMode
* Convenience method to return a single instance that matches
* the query, or null if the query returns no results.
*
* @return the single result or <tt>null</tt>
* @throws NonUniqueResultException if there is more than one matching result
*/
public Query setCacheMode(CacheMode cacheMode);
public Object uniqueResult() throws HibernateException;
/**
* Execute the update or delete statement.
* </p>
* The semantics are compliant with the ejb3 Query.executeUpdate()
* method.
*
* @return The number of entities updated or deleted.
* @throws HibernateException
*/
public int executeUpdate() throws HibernateException;
/**
* Bind a value to a JDBC-style query parameter.
@ -280,6 +444,7 @@ public interface Query {
* @param type the Hibernate type
*/
public Query setParameter(int position, Object val, Type type);
/**
* Bind a value to a named query parameter.
* @param name the name of the parameter
@ -298,6 +463,7 @@ public interface Query {
* @throws org.hibernate.HibernateException if no type could be determined
*/
public Query setParameter(int position, Object val) throws HibernateException;
/**
* Bind a value to a named query parameter. The Hibernate type of the parameter is
* first detected via the usage/position in the query and if not sufficient secondly

View File

@ -22,6 +22,10 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate;
import java.util.Collection;
import java.util.List;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.type.Type;
/**
@ -45,6 +49,14 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
public interface SQLQuery extends Query {
/**
* Obtain the list of query spaces (table names) the query is synchronized on. These spaces affect the process
* of auto-flushing by determining which entities will be processed by auto-flush based on the table to
* which those entities are mapped and which are determined to have pending state changes.
*
* @return The list of query spaces upon which the query is synchronized.
*/
public Collection<String> getSynchronizedQuerySpaces();
/**
* Adds a query space (table name) for (a) auto-flush checking and (b) query result cache invalidation checking
@ -52,6 +64,8 @@ public interface SQLQuery extends Query {
* @param querySpace The query space to be auto-flushed for this query.
*
* @return this, for method chaining
*
* @see #getSynchronizedQuerySpaces()
*/
public SQLQuery addSynchronizedQuerySpace(String querySpace);
@ -64,6 +78,8 @@ public interface SQLQuery extends Query {
* @return this, for method chaining
*
* @throws MappingException Indicates the given name could not be resolved as an entity
*
* @see #getSynchronizedQuerySpaces()
*/
public SQLQuery addSynchronizedEntityName(String entityName) throws MappingException;
@ -76,6 +92,8 @@ public interface SQLQuery extends Query {
* @return this, for method chaining
*
* @throws MappingException Indicates the given class could not be resolved as an entity
*
* @see #getSynchronizedQuerySpaces()
*/
public SQLQuery addSynchronizedEntityClass(Class entityClass) throws MappingException;
@ -89,6 +107,15 @@ public interface SQLQuery extends Query {
*/
public SQLQuery setResultSetMapping(String name);
/**
* Is this native-SQL query known to be callable?
*
* @return {@code true} if the query is known to be callable; {@code false} otherwise.
*/
public boolean isCallable();
public List<NativeSQLQueryReturn> getQueryReturns();
/**
* Declare a scalar query result. Hibernate will attempt to automatically detect the underlying type.
* <p/>

View File

@ -45,6 +45,7 @@ import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
@ -2638,30 +2639,6 @@ public final class HbmBinder {
}
}
public static final FlushMode getFlushMode(String flushMode) {
if ( flushMode == null ) {
return null;
}
else if ( "auto".equals( flushMode ) ) {
return FlushMode.AUTO;
}
else if ( "commit".equals( flushMode ) ) {
return FlushMode.COMMIT;
}
else if ( "never".equals( flushMode ) ) {
return FlushMode.NEVER;
}
else if ( "manual".equals( flushMode ) ) {
return FlushMode.MANUAL;
}
else if ( "always".equals( flushMode ) ) {
return FlushMode.ALWAYS;
}
else {
throw new MappingException( "unknown flushmode" );
}
}
private static void bindNamedQuery(Element queryElem, String path, Mappings mappings) {
String queryName = queryElem.attributeValue( "name" );
if (path!=null) queryName = path + '.' + queryName;
@ -2681,33 +2658,22 @@ public final class HbmBinder {
Attribute cmAtt = queryElem.attribute( "comment" );
String comment = cmAtt == null ? null : cmAtt.getValue();
NamedQueryDefinition namedQuery = new NamedQueryDefinition(
queryName,
query,
cacheable,
region,
timeout,
fetchSize,
getFlushMode( queryElem.attributeValue( "flush-mode" ) ) ,
getCacheMode( cacheMode ),
readOnly,
comment,
getParameterTypes(queryElem)
);
NamedQueryDefinition namedQuery = new NamedQueryDefinitionBuilder().setName( queryName )
.setQuery( query )
.setCacheable( cacheable )
.setCacheRegion( region )
.setTimeout( timeout )
.setFetchSize( fetchSize )
.setFlushMode( FlushMode.interpretExternalSetting( queryElem.attributeValue( "flush-mode" ) ) )
.setCacheMode( CacheMode.interpretExternalSetting( cacheMode ) )
.setReadOnly( readOnly )
.setComment( comment )
.setParameterTypes( getParameterTypes( queryElem ) )
.createNamedQueryDefinition();
mappings.addQuery( namedQuery.getName(), namedQuery );
}
public static CacheMode getCacheMode(String cacheMode) {
if (cacheMode == null) return null;
if ( "get".equals( cacheMode ) ) return CacheMode.GET;
if ( "ignore".equals( cacheMode ) ) return CacheMode.IGNORE;
if ( "normal".equals( cacheMode ) ) return CacheMode.NORMAL;
if ( "put".equals( cacheMode ) ) return CacheMode.PUT;
if ( "refresh".equals( cacheMode ) ) return CacheMode.REFRESH;
throw new MappingException("Unknown Cache Mode: " + cacheMode);
}
public static java.util.Map getParameterTypes(Element queryElem) {
java.util.Map result = new java.util.LinkedHashMap();
Iterator iter = queryElem.elementIterator("query-param");

View File

@ -31,9 +31,12 @@ import org.dom4j.Attribute;
import org.dom4j.Element;
import org.jboss.logging.Logger;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.MappingException;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
@ -83,42 +86,40 @@ public class NamedSQLQuerySecondPass extends ResultSetMappingBinder implements Q
Attribute ref = queryElem.attribute( "resultset-ref" );
String resultSetRef = ref == null ? null : ref.getValue();
if ( StringHelper.isNotEmpty( resultSetRef ) ) {
namedQuery = new NamedSQLQueryDefinition(
queryName,
queryElem.getText(),
resultSetRef,
synchronizedTables,
cacheable,
region,
timeout,
fetchSize,
HbmBinder.getFlushMode( queryElem.attributeValue( "flush-mode" ) ),
HbmBinder.getCacheMode( cacheMode ),
readOnly,
comment,
HbmBinder.getParameterTypes( queryElem ),
callable
);
namedQuery = new NamedSQLQueryDefinitionBuilder().setName( queryName )
.setQuery( queryElem.getText() )
.setResultSetRef( resultSetRef )
.setQuerySpaces( synchronizedTables )
.setCacheable( cacheable )
.setCacheRegion( region )
.setTimeout( timeout )
.setFetchSize( fetchSize )
.setFlushMode( FlushMode.interpretExternalSetting( queryElem.attributeValue( "flush-mode" ) ) )
.setCacheMode( CacheMode.interpretExternalSetting( cacheMode ) )
.setReadOnly( readOnly )
.setComment( comment )
.setParameterTypes( HbmBinder.getParameterTypes( queryElem ) )
.setCallable( callable )
.createNamedQueryDefinition();
//TODO check there is no actual definition elemnents when a ref is defined
}
else {
ResultSetMappingDefinition definition = buildResultSetMappingDefinition( queryElem, path, mappings );
namedQuery = new NamedSQLQueryDefinition(
queryName,
queryElem.getText(),
definition.getQueryReturns(),
synchronizedTables,
cacheable,
region,
timeout,
fetchSize,
HbmBinder.getFlushMode( queryElem.attributeValue( "flush-mode" ) ),
HbmBinder.getCacheMode( cacheMode ),
readOnly,
comment,
HbmBinder.getParameterTypes( queryElem ),
callable
);
namedQuery = new NamedSQLQueryDefinitionBuilder().setName( queryName )
.setQuery( queryElem.getText() )
.setQueryReturns( definition.getQueryReturns() )
.setQuerySpaces( synchronizedTables )
.setCacheable( cacheable )
.setCacheRegion( region )
.setTimeout( timeout )
.setFetchSize( fetchSize )
.setFlushMode( FlushMode.interpretExternalSetting( queryElem.attributeValue( "flush-mode" ) ) )
.setCacheMode( CacheMode.interpretExternalSetting( cacheMode ) )
.setReadOnly( readOnly )
.setComment( comment )
.setParameterTypes( HbmBinder.getParameterTypes( queryElem ) )
.setCallable( callable )
.createNamedQueryDefinition();
}
if ( LOG.isDebugEnabled() ) {

View File

@ -23,6 +23,7 @@
*/
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;
@ -38,16 +39,21 @@ 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
@ -65,31 +71,43 @@ public abstract class QueryBinder {
//EJBQL Query
QueryHint[] hints = queryAnn.hints();
String queryName = queryAnn.query();
NamedQueryDefinition query = new NamedQueryDefinition(
queryAnn.name(),
queryName,
getBoolean( queryName, "org.hibernate.cacheable", hints ),
getString( queryName, "org.hibernate.cacheRegion", hints ),
getTimeout( queryName, hints ),
getInteger( queryName, "javax.persistence.lock.timeout", hints ),
getInteger( queryName, "org.hibernate.fetchSize", hints ),
getFlushMode( queryName, hints ),
getCacheMode( queryName, hints ),
getBoolean( queryName, "org.hibernate.readOnly", hints ),
getString( queryName, "org.hibernate.comment", hints ),
null
);
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( query.getName(), query );
mappings.addDefaultQuery( queryDefinition.getName(), queryDefinition );
}
else {
mappings.addQuery( query.getName(), query );
mappings.addQuery( queryDefinition.getName(), queryDefinition );
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Binding named query: %s => %s", query.getName(), query.getQueryString() );
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() );
@ -102,44 +120,42 @@ public abstract class QueryBinder {
String queryName = queryAnn.query();
if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
//sql result set usage
query = new NamedSQLQueryDefinition(
queryAnn.name(),
queryName,
resultSetMapping,
null,
getBoolean( queryName, "org.hibernate.cacheable", hints ),
getString( queryName, "org.hibernate.cacheRegion", hints ),
getTimeout( queryName, hints ),
getInteger( queryName, "org.hibernate.fetchSize", hints ),
getFlushMode( queryName, hints ),
getCacheMode( queryName, hints ),
getBoolean( queryName, "org.hibernate.readOnly", hints ),
getString( queryName, "org.hibernate.comment", hints ),
null,
getBoolean( queryName, "org.hibernate.callable", hints )
);
query = new NamedSQLQueryDefinitionBuilder( queryAnn.name() )
.setQuery( queryName )
.setResultSetRef( resultSetMapping )
.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 ) )
.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 NamedSQLQueryDefinition(
queryAnn.name(),
queryName,
new NativeSQLQueryReturn[] { entityQueryReturn },
null,
getBoolean( queryName, "org.hibernate.cacheable", hints ),
getString( queryName, "org.hibernate.cacheRegion", hints ),
getTimeout( queryName, hints ),
getInteger( queryName, "org.hibernate.fetchSize", hints ),
getFlushMode( queryName, hints ),
getCacheMode( queryName, hints ),
getBoolean( queryName, "org.hibernate.readOnly", hints ),
getString( queryName, "org.hibernate.comment", hints ),
null,
getBoolean( queryName, "org.hibernate.callable", hints )
);
query = new NamedSQLQueryDefinitionBuilder( queryAnn.name() )
.setQuery( queryName )
.setQueryReturns( new NativeSQLQueryReturn[] {entityQueryReturn} )
.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 ) )
.createNamedQueryDefinition();
}
else {
throw new NotYetImplementedException( "Pure native scalar queries are not yet supported" );
@ -165,44 +181,50 @@ public abstract class QueryBinder {
String resultSetMapping = queryAnn.resultSetMapping();
if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
//sql result set usage
query = new NamedSQLQueryDefinition(
queryAnn.name(),
queryAnn.query(),
resultSetMapping,
null,
queryAnn.cacheable(),
BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
getFlushMode( queryAnn.flushMode() ),
getCacheMode( queryAnn.cacheMode() ),
queryAnn.readOnly(),
BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment(),
null,
queryAnn.callable()
);
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 NamedSQLQueryDefinition(
queryAnn.name(),
queryAnn.query(),
new NativeSQLQueryReturn[] { entityQueryReturn },
null,
queryAnn.cacheable(),
BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
getFlushMode( queryAnn.flushMode() ),
getCacheMode( queryAnn.cacheMode() ),
queryAnn.readOnly(),
BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment(),
null,
queryAnn.callable()
);
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" );
@ -244,19 +266,22 @@ public abstract class QueryBinder {
FlushMode flushMode;
flushMode = getFlushMode( queryAnn.flushMode() );
NamedQueryDefinition query = new NamedQueryDefinition(
queryAnn.name(),
queryAnn.query(),
queryAnn.cacheable(),
BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
flushMode,
getCacheMode( queryAnn.cacheMode() ),
queryAnn.readOnly(),
BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment(),
null
);
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() ) {

View File

@ -31,9 +31,11 @@ import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
/**
* Definition of a named query, defined in the mapping metadata.
* Definition of a named query, defined in the mapping metadata. Additional, as of JPA 2.1, named query definition
* can also come from a compiled query.
*
* @author Gavin King
* @author Steve Ebersole
*/
public class NamedQueryDefinition implements Serializable {
private final String name;
@ -41,39 +43,38 @@ public class NamedQueryDefinition implements Serializable {
private final boolean cacheable;
private final String cacheRegion;
private final Integer timeout;
private final Integer lockTimeout;
private final LockOptions lockOptions;
private final Integer fetchSize;
private final FlushMode flushMode;
private final Map parameterTypes;
private CacheMode cacheMode;
private boolean readOnly;
private String comment;
private final CacheMode cacheMode;
private final boolean readOnly;
private final String comment;
// kept for backward compatibility until after the 3.1beta5 release of HA
// TODO: is this still needed?
public NamedQueryDefinition(
String query,
boolean cacheable,
String cacheRegion,
Integer timeout,
Integer fetchSize,
FlushMode flushMode,
Map parameterTypes) {
this(
null,
query,
cacheable,
cacheRegion,
timeout,
fetchSize,
flushMode,
null,
false,
null,
parameterTypes
);
}
// added for jpa 2.1
private final Integer firstResult;
private final Integer maxResults;
/**
* This form is used to bind named queries from Hibernate metadata, both {@code hbm.xml} files and
* {@link org.hibernate.annotations.NamedQuery} annotation.
*
* @param name The name under which to key/register the query
* @param query The query string.
* @param cacheable Is the query cacheable?
* @param cacheRegion If cacheable, was there a specific region named?
* @param timeout Query timeout, {@code null} indicates no timeout
* @param fetchSize Fetch size associated with the query, {@code null} indicates no limit
* @param flushMode Flush mode associated with query
* @param cacheMode Cache mode associated with query
* @param readOnly Should entities returned from this query (those not already associated with the Session anyway)
* be loaded as read-only?
* @param comment SQL comment to be used in the generated SQL, {@code null} indicates none
* @param parameterTypes (no idea, afaict this is always passed as null)
*
* @deprecated Use {@link NamedQueryDefinitionBuilder} instead.
*/
@Deprecated
public NamedQueryDefinition(
String name,
String query,
@ -86,11 +87,42 @@ public class NamedQueryDefinition implements Serializable {
boolean readOnly,
String comment,
Map parameterTypes) {
this(name, query, cacheable, cacheRegion,
timeout, LockOptions.WAIT_FOREVER, fetchSize,
flushMode, cacheMode, readOnly, comment, parameterTypes);
this(
name,
query,
cacheable,
cacheRegion,
timeout,
LockOptions.WAIT_FOREVER,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes
);
}
/**
* This version is used to bind named queries defined via {@link javax.persistence.NamedQuery}.
*
* @param name The name under which to key/register the query
* @param query The query string.
* @param cacheable Is the query cacheable?
* @param cacheRegion If cacheable, was there a specific region named?
* @param timeout Query timeout, {@code null} indicates no timeout
* @param lockTimeout Specifies the lock timeout for queries that apply lock modes.
* @param fetchSize Fetch size associated with the query, {@code null} indicates no limit
* @param flushMode Flush mode associated with query
* @param cacheMode Cache mode associated with query
* @param readOnly Should entities returned from this query (those not already associated with the Session anyway)
* be loaded as read-only?
* @param comment SQL comment to be used in the generated SQL, {@code null} indicates none
* @param parameterTypes (no idea, afaict this is always passed as null)
*
* @deprecated Use {@link NamedQueryDefinitionBuilder} instead.
*/
@Deprecated
public NamedQueryDefinition(
String name,
String query,
@ -104,18 +136,54 @@ public class NamedQueryDefinition implements Serializable {
boolean readOnly,
String comment,
Map parameterTypes) {
this(
name,
query,
cacheable,
cacheRegion,
timeout,
new LockOptions().setTimeOut( lockTimeout ),
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes,
null, // firstResult
null // maxResults
);
}
NamedQueryDefinition(
String name,
String query,
boolean cacheable,
String cacheRegion,
Integer timeout,
LockOptions lockOptions,
Integer fetchSize,
FlushMode flushMode,
CacheMode cacheMode,
boolean readOnly,
String comment,
Map parameterTypes,
Integer firstResult,
Integer maxResults) {
this.name = name;
this.query = query;
this.cacheable = cacheable;
this.cacheRegion = cacheRegion;
this.timeout = timeout;
this.lockTimeout = lockTimeout;
this.lockOptions = lockOptions;
this.fetchSize = fetchSize;
this.flushMode = flushMode;
this.parameterTypes = parameterTypes;
this.cacheMode = cacheMode;
this.readOnly = readOnly;
this.comment = comment;
this.firstResult = firstResult;
this.maxResults = maxResults;
}
public String getName() {
@ -146,11 +214,8 @@ public class NamedQueryDefinition implements Serializable {
return flushMode;
}
public String toString() {
return getClass().getName() + '(' + query + ')';
}
public Map getParameterTypes() {
// todo : currently these are never used...
return parameterTypes;
}
@ -170,7 +235,20 @@ public class NamedQueryDefinition implements Serializable {
return comment;
}
public Integer getLockTimeout() {
return lockTimeout;
public LockOptions getLockOptions() {
return lockOptions;
}
public Integer getFirstResult() {
return firstResult;
}
public Integer getMaxResults() {
return maxResults;
}
@Override
public String toString() {
return getClass().getName() + '(' + name + " [" + query + "])";
}
}

View File

@ -0,0 +1,143 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.engine.spi;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
public class NamedQueryDefinitionBuilder {
protected String name;
protected String query;
protected boolean cacheable;
protected String cacheRegion;
protected Integer timeout;
protected Integer fetchSize;
protected FlushMode flushMode;
protected CacheMode cacheMode;
protected boolean readOnly;
protected String comment;
protected Map parameterTypes;
protected LockOptions lockOptions;
protected Integer firstResult;
protected Integer maxResults;
public NamedQueryDefinitionBuilder() {
}
public NamedQueryDefinitionBuilder(String name) {
this.name = name;
}
public NamedQueryDefinitionBuilder setName(String name) {
this.name = name;
return this;
}
public NamedQueryDefinitionBuilder setQuery(String query) {
this.query = query;
return this;
}
public NamedQueryDefinitionBuilder setCacheable(boolean cacheable) {
this.cacheable = cacheable;
return this;
}
public NamedQueryDefinitionBuilder setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
return this;
}
public NamedQueryDefinitionBuilder setTimeout(Integer timeout) {
this.timeout = timeout;
return this;
}
public NamedQueryDefinitionBuilder setFetchSize(Integer fetchSize) {
this.fetchSize = fetchSize;
return this;
}
public NamedQueryDefinitionBuilder setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
return this;
}
public NamedQueryDefinitionBuilder setCacheMode(CacheMode cacheMode) {
this.cacheMode = cacheMode;
return this;
}
public NamedQueryDefinitionBuilder setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
return this;
}
public NamedQueryDefinitionBuilder setComment(String comment) {
this.comment = comment;
return this;
}
public NamedQueryDefinitionBuilder setParameterTypes(Map parameterTypes) {
this.parameterTypes = parameterTypes;
return this;
}
public NamedQueryDefinitionBuilder setLockOptions(LockOptions lockOptions) {
this.lockOptions = lockOptions;
return this;
}
public NamedQueryDefinitionBuilder setFirstResult(Integer firstResult) {
this.firstResult = firstResult;
return this;
}
public NamedQueryDefinitionBuilder setMaxResults(Integer maxResults) {
this.maxResults = maxResults;
return this;
}
public NamedQueryDefinition createNamedQueryDefinition() {
return new NamedQueryDefinition(
name,
query,
cacheable,
cacheRegion,
timeout,
lockOptions,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes,
firstResult,
maxResults
);
}
}

View File

@ -34,6 +34,7 @@ import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
* Definition of a named native SQL query, defined in the mapping metadata.
*
* @author Max Andersen
* @author Steve Ebersole
*/
public class NamedSQLQueryDefinition extends NamedQueryDefinition {
@ -43,9 +44,9 @@ public class NamedSQLQueryDefinition extends NamedQueryDefinition {
private String resultSetRef;
/**
* This form used to construct a NamedSQLQueryDefinition from the binder
* code when a the result-set mapping information is explicitly
* provided in the query definition (i.e., no resultset-mapping used)
* This form was initially used to construct a NamedSQLQueryDefinition from the binder code when a the
* result-set mapping information is not explicitly provided in the query definition
* (i.e., no resultset-mapping used).
*
* @param name The name of named query
* @param query The sql query string
@ -61,7 +62,10 @@ public class NamedSQLQueryDefinition extends NamedQueryDefinition {
* @param comment Any sql comment to be applied to the query
* @param parameterTypes parameter type map
* @param callable Does the query string represent a callable object (i.e., proc)
*
* @deprecated Use {@link NamedSQLQueryDefinitionBuilder} instead.
*/
@Deprecated
public NamedSQLQueryDefinition(
String name,
String query,
@ -77,9 +81,9 @@ public class NamedSQLQueryDefinition extends NamedQueryDefinition {
String comment,
Map parameterTypes,
boolean callable) {
super(
this(
name,
query.trim(), /* trim done to workaround stupid oracle bug that cant handle whitespaces before a { in a sp */
query,
cacheable,
cacheRegion,
timeout,
@ -88,16 +92,19 @@ public class NamedSQLQueryDefinition extends NamedQueryDefinition {
cacheMode,
readOnly,
comment,
parameterTypes
parameterTypes,
null, // firstResult
null, // maxResults
null, // resultSetRef
querySpaces,
callable,
queryReturns
);
this.queryReturns = queryReturns;
this.querySpaces = querySpaces;
this.callable = callable;
}
/**
* This form used to construct a NamedSQLQueryDefinition from the binder
* code when a resultset-mapping reference is used.
* This form was initially used to construct a NamedSQLQueryDefinition from the binder code when a
* resultset-mapping reference is used.
*
* @param name The name of named query
* @param query The sql query string
@ -113,7 +120,10 @@ public class NamedSQLQueryDefinition extends NamedQueryDefinition {
* @param comment Any sql comment to be applied to the query
* @param parameterTypes parameter type map
* @param callable Does the query string represent a callable object (i.e., proc)
*
* @deprecated Use {@link NamedSQLQueryDefinitionBuilder} instead.
*/
@Deprecated
public NamedSQLQueryDefinition(
String name,
String query,
@ -129,9 +139,10 @@ public class NamedSQLQueryDefinition extends NamedQueryDefinition {
String comment,
Map parameterTypes,
boolean callable) {
super(
this(
name,
query.trim(), /* trim done to workaround stupid oracle bug that cant handle whitespaces before a { in a sp */
query,
cacheable,
cacheRegion,
timeout,
@ -140,59 +151,54 @@ public class NamedSQLQueryDefinition extends NamedQueryDefinition {
cacheMode,
readOnly,
comment,
parameterTypes
parameterTypes,
null, // firstResult
null, // maxResults
resultSetRef,
querySpaces,
callable,
null // queryReturns
);
this.resultSetRef = resultSetRef;
this.querySpaces = querySpaces;
this.callable = callable;
}
/**
* This form used from annotations (?). Essentially the same as the above using a
* resultset-mapping reference, but without cacheMode, readOnly, and comment.
*
* FIXME: annotations do not use it, so it can be remove from my POV
* @deprecated
*
*
* @param query The sql query string
* @param resultSetRef The result-set-mapping name
* @param querySpaces Any specified query spaces (used for auto-flushing)
* @param cacheable Whether the query results are cacheable
* @param cacheRegion If cacheable, the region into which to store the results
* @param timeout A JDBC-level timeout to be applied
* @param fetchSize A JDBC-level fetch-size to be applied
* @param flushMode The flush mode to use for this query
* @param parameterTypes parameter type map
* @param callable Does the query string represent a callable object (i.e., proc)
*/
public NamedSQLQueryDefinition(
NamedSQLQueryDefinition(
String name,
String query,
String resultSetRef,
List<String> querySpaces,
boolean cacheable,
String cacheRegion,
Integer timeout,
Integer fetchSize,
FlushMode flushMode,
CacheMode cacheMode,
boolean readOnly,
String comment,
Map parameterTypes,
boolean callable) {
this(
null,
query,
resultSetRef,
querySpaces,
Integer firstResult,
Integer maxResults,
String resultSetRef,
List<String> querySpaces,
boolean callable,
NativeSQLQueryReturn[] queryReturns) {
super(
name,
query.trim(), /* trim done to workaround stupid oracle bug that cant handle whitespaces before a { in a sp */
cacheable,
cacheRegion,
timeout,
null, // lockOptions
fetchSize,
flushMode,
null,
false,
null,
cacheMode,
readOnly,
comment,
parameterTypes,
callable
firstResult,
maxResults
);
this.resultSetRef = resultSetRef;
this.querySpaces = querySpaces;
this.callable = callable;
this.queryReturns = queryReturns;
}
public NativeSQLQueryReturn[] getQueryReturns() {

View File

@ -0,0 +1,184 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.engine.spi;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
public class NamedSQLQueryDefinitionBuilder extends NamedQueryDefinitionBuilder {
private NativeSQLQueryReturn[] queryReturns;
private Collection<String> querySpaces;
private boolean callable;
private String resultSetRef;
public NamedSQLQueryDefinitionBuilder() {
}
public NamedSQLQueryDefinitionBuilder(String name) {
super( name );
}
public NamedSQLQueryDefinitionBuilder setQueryReturns(NativeSQLQueryReturn[] queryReturns) {
this.queryReturns = queryReturns;
return this;
}
public NamedSQLQueryDefinitionBuilder setQueryReturns(List<NativeSQLQueryReturn> queryReturns) {
if ( queryReturns != null ) {
this.queryReturns = queryReturns.toArray( new NativeSQLQueryReturn[ queryReturns.size() ] );
}
else {
this.queryReturns = null;
}
return this;
}
public NamedSQLQueryDefinitionBuilder setQuerySpaces(List<String> querySpaces) {
this.querySpaces = querySpaces;
return this;
}
public NamedSQLQueryDefinitionBuilder setQuerySpaces(Collection<String> synchronizedQuerySpaces) {
this.querySpaces = synchronizedQuerySpaces;
return this;
}
public NamedSQLQueryDefinitionBuilder setResultSetRef(String resultSetRef) {
this.resultSetRef = resultSetRef;
return this;
}
public NamedSQLQueryDefinitionBuilder setCallable(boolean callable) {
this.callable = callable;
return this;
}
@Override
public NamedSQLQueryDefinitionBuilder setName(String name) {
return (NamedSQLQueryDefinitionBuilder) super.setName( name );
}
@Override
public NamedSQLQueryDefinitionBuilder setQuery(String query) {
return (NamedSQLQueryDefinitionBuilder) super.setQuery( query );
}
@Override
public NamedSQLQueryDefinitionBuilder setCacheable(boolean cacheable) {
return (NamedSQLQueryDefinitionBuilder) super.setCacheable( cacheable );
}
@Override
public NamedSQLQueryDefinitionBuilder setCacheRegion(String cacheRegion) {
return (NamedSQLQueryDefinitionBuilder) super.setCacheRegion( cacheRegion );
}
@Override
public NamedSQLQueryDefinitionBuilder setTimeout(Integer timeout) {
return (NamedSQLQueryDefinitionBuilder) super.setTimeout( timeout );
}
@Override
public NamedSQLQueryDefinitionBuilder setFetchSize(Integer fetchSize) {
return (NamedSQLQueryDefinitionBuilder) super.setFetchSize( fetchSize );
}
@Override
public NamedSQLQueryDefinitionBuilder setFlushMode(FlushMode flushMode) {
return (NamedSQLQueryDefinitionBuilder) super.setFlushMode( flushMode );
}
@Override
public NamedSQLQueryDefinitionBuilder setCacheMode(CacheMode cacheMode) {
return (NamedSQLQueryDefinitionBuilder) super.setCacheMode( cacheMode );
}
@Override
public NamedSQLQueryDefinitionBuilder setReadOnly(boolean readOnly) {
return (NamedSQLQueryDefinitionBuilder) super.setReadOnly( readOnly );
}
@Override
public NamedSQLQueryDefinitionBuilder setComment(String comment) {
return (NamedSQLQueryDefinitionBuilder) super.setComment( comment );
}
@Override
public NamedSQLQueryDefinitionBuilder setParameterTypes(Map parameterTypes) {
return (NamedSQLQueryDefinitionBuilder) super.setParameterTypes( parameterTypes );
}
@Override
public NamedSQLQueryDefinitionBuilder setLockOptions(LockOptions lockOptions) {
// todo : maybe throw an exception here instead? since this is not valid for native-0sql queries?
return (NamedSQLQueryDefinitionBuilder) super.setLockOptions( lockOptions );
}
@Override
public NamedSQLQueryDefinitionBuilder setFirstResult(Integer firstResult) {
return (NamedSQLQueryDefinitionBuilder) super.setFirstResult( firstResult );
}
@Override
public NamedSQLQueryDefinitionBuilder setMaxResults(Integer maxResults) {
return (NamedSQLQueryDefinitionBuilder) super.setMaxResults( maxResults );
}
@Override
public NamedSQLQueryDefinition createNamedQueryDefinition() {
return new NamedSQLQueryDefinition(
name,
query,
cacheable,
cacheRegion,
timeout,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes,
firstResult,
maxResults,
resultSetRef,
querySpacesCopy(),
callable,
queryReturns
);
}
private List<String> querySpacesCopy() {
return querySpaces == null
? null
: new ArrayList<String>( querySpaces );
}
}

View File

@ -184,7 +184,13 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory {
public StatisticsImplementor getStatisticsImplementor();
public NamedQueryDefinition getNamedQuery(String queryName);
public void registerNamedQueryDefinition(String name, NamedQueryDefinition definition);
public NamedSQLQueryDefinition getNamedSQLQuery(String queryName);
public void registerNamedSQLQueryDefinition(String name, NamedSQLQueryDefinition definition);
public ResultSetMappingDefinition getResultSetMapping(String name);
/**

View File

@ -120,54 +120,90 @@ public abstract class AbstractQueryImpl implements Query {
return parameterMetadata;
}
@Override
public String toString() {
return StringHelper.unqualify( getClass().getName() ) + '(' + queryString + ')';
}
@Override
public final String getQueryString() {
return queryString;
}
//TODO: maybe call it getRowSelection() ?
public RowSelection getSelection() {
return selection;
}
public Query setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
return this;
}
public Query setCacheMode(CacheMode cacheMode) {
this.cacheMode = cacheMode;
return this;
}
public CacheMode getCacheMode() {
return cacheMode;
@Override
public boolean isCacheable() {
return cacheable;
}
@Override
public Query setCacheable(boolean cacheable) {
this.cacheable = cacheable;
return this;
}
@Override
public String getCacheRegion() {
return cacheRegion;
}
@Override
public Query setCacheRegion(String cacheRegion) {
if (cacheRegion != null)
if (cacheRegion != null) {
this.cacheRegion = cacheRegion.trim();
}
return this;
}
@Override
public FlushMode getFlushMode() {
return flushMode;
}
@Override
public Query setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
return this;
}
@Override
public CacheMode getCacheMode() {
return cacheMode;
}
@Override
public Query setCacheMode(CacheMode cacheMode) {
this.cacheMode = cacheMode;
return this;
}
@Override
public String getComment() {
return comment;
}
@Override
public Query setComment(String comment) {
this.comment = comment;
return this;
}
@Override
public Integer getFirstResult() {
return selection.getFirstRow();
}
@Override
public Query setFirstResult(int firstResult) {
selection.setFirstRow( firstResult);
return this;
}
@Override
public Integer getMaxResults() {
return selection.getMaxRows();
}
@Override
public Query setMaxResults(int maxResults) {
if ( maxResults < 0 ) {
// treat negatives specically as meaning no limit...
@ -179,10 +215,23 @@ public abstract class AbstractQueryImpl implements Query {
return this;
}
@Override
public Integer getTimeout() {
return selection.getTimeout();
}
@Override
public Query setTimeout(int timeout) {
selection.setTimeout( timeout);
return this;
}
@Override
public Integer getFetchSize() {
return selection.getFetchSize();
}
@Override
public Query setFetchSize(int fetchSize) {
selection.setFetchSize( fetchSize);
return this;
@ -920,7 +969,7 @@ public abstract class AbstractQueryImpl implements Query {
valueArray(),
namedParams,
getLockOptions(),
getSelection(),
getRowSelection(),
true,
isReadOnly(),
cacheable,

View File

@ -142,8 +142,8 @@ public abstract class AbstractSessionImpl implements Serializable, SharedSession
getHQLQueryPlan( queryString, false ).getParameterMetadata()
);
query.setComment( "named HQL query " + queryName );
if ( nqd.getLockTimeout() != null ) {
( (QueryImpl) query ).getLockOptions().setTimeOut( nqd.getLockTimeout() );
if ( nqd.getLockOptions() != null ) {
query.setLockOptions( nqd.getLockOptions() );
}
}
else {
@ -181,14 +181,34 @@ public abstract class AbstractSessionImpl implements Serializable, SharedSession
return query;
}
@SuppressWarnings("UnnecessaryUnboxing")
private void initQuery(Query query, NamedQueryDefinition nqd) {
// todo : cacheable and readonly should be Boolean rather than boolean...
query.setCacheable( nqd.isCacheable() );
query.setCacheRegion( nqd.getCacheRegion() );
if ( nqd.getTimeout()!=null ) query.setTimeout( nqd.getTimeout().intValue() );
if ( nqd.getFetchSize()!=null ) query.setFetchSize( nqd.getFetchSize().intValue() );
if ( nqd.getCacheMode() != null ) query.setCacheMode( nqd.getCacheMode() );
query.setReadOnly( nqd.isReadOnly() );
if ( nqd.getComment() != null ) query.setComment( nqd.getComment() );
if ( nqd.getTimeout() != null ) {
query.setTimeout( nqd.getTimeout().intValue() );
}
if ( nqd.getFetchSize() != null ) {
query.setFetchSize( nqd.getFetchSize().intValue() );
}
if ( nqd.getCacheMode() != null ) {
query.setCacheMode( nqd.getCacheMode() );
}
if ( nqd.getComment() != null ) {
query.setComment( nqd.getComment() );
}
if ( nqd.getFirstResult() != null ) {
query.setFirstResult( nqd.getFirstResult() );
}
if ( nqd.getMaxResults() != null ) {
query.setMaxResults( nqd.getMaxResults() );
}
if ( nqd.getFlushMode() != null ) {
query.setFlushMode( nqd.getFlushMode() );
}
}
@Override

View File

@ -141,10 +141,23 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
callable = false;
}
private NativeSQLQueryReturn[] getQueryReturns() {
return queryReturns.toArray( new NativeSQLQueryReturn[queryReturns.size()] );
@Override
public List<NativeSQLQueryReturn> getQueryReturns() {
prepareQueryReturnsIfNecessary();
return queryReturns;
}
@Override
public Collection<String> getSynchronizedQuerySpaces() {
return querySpaces;
}
@Override
public boolean isCallable() {
return callable;
}
@Override
public List list() throws HibernateException {
verifyParameters();
before();
@ -163,7 +176,7 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
private NativeSQLQuerySpecification generateQuerySpecification(Map namedParams) {
return new NativeSQLQuerySpecification(
expandParameterLists(namedParams),
getQueryReturns(),
queryReturns.toArray( new NativeSQLQueryReturn[queryReturns.size()] ),
querySpaces
);
}
@ -206,7 +219,7 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
protected void verifyParameters() {
// verifyParameters is called at the start of all execution type methods, so we use that here to perform
// some preparation work.
prepare();
prepareQueryReturnsIfNecessary();
verifyParameters( callable );
boolean noReturns = queryReturns==null || queryReturns.isEmpty();
if ( noReturns ) {
@ -225,7 +238,7 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
}
}
private void prepare() {
private void prepareQueryReturnsIfNecessary() {
if ( queryReturnBuilders != null ) {
if ( ! queryReturnBuilders.isEmpty() ) {
if ( queryReturns != null ) {

View File

@ -23,6 +23,8 @@
*/
package org.hibernate.internal;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
@ -38,9 +40,6 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import org.jboss.logging.Logger;
@ -59,8 +58,6 @@ import org.hibernate.Session;
import org.hibernate.SessionBuilder;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.engine.spi.CacheImplementor;
import org.hibernate.engine.spi.SessionOwner;
import org.hibernate.StatelessSession;
import org.hibernate.StatelessSessionBuilder;
import org.hibernate.TypeHelper;
@ -98,12 +95,14 @@ import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.query.spi.QueryPlanCache;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.spi.CacheImplementor;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.SessionBuilderImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionOwner;
import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.exception.spi.SQLExceptionConverter;
@ -112,7 +111,6 @@ import org.hibernate.id.UUIDGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.integrator.spi.IntegratorService;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
@ -1160,10 +1158,35 @@ public final class SessionFactoryImpl
);
}
public void registerNamedQueryDefinition(String name, NamedQueryDefinition definition) {
if ( NamedSQLQueryDefinition.class.isInstance( definition ) ) {
throw new IllegalArgumentException( "NamedSQLQueryDefinition instance incorrectly passed to registerNamedQueryDefinition" );
}
final NamedQueryDefinition previous = namedQueries.put( name, definition );
if ( previous != null ) {
LOG.debugf(
"registering named query definition [%s] overriding previously registered definition [%s]",
name,
previous
);
}
}
public NamedQueryDefinition getNamedQuery(String queryName) {
return namedQueries.get( queryName );
}
public void registerNamedSQLQueryDefinition(String name, NamedSQLQueryDefinition definition) {
final NamedSQLQueryDefinition previous = namedSqlQueries.put( name, definition );
if ( previous != null ) {
LOG.debugf(
"registering named SQL query definition [%s] overriding previously registered definition [%s]",
name,
previous
);
}
}
public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) {
return namedSqlQueries.get( queryName );
}

View File

@ -0,0 +1,105 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.internal.util;
import javax.persistence.LockModeType;
import org.hibernate.AssertionFailure;
import org.hibernate.LockMode;
/**
* Helper to deal with conversions (both directions) between {@link org.hibernate.LockMode} and
* {@link javax.persistence.LockModeType}.
*
* @author Steve Ebersole
*/
public class LockModeConverter {
/**
* Convert from the Hibernate specific LockMode to the JPA defined LockModeType.
*
* @param lockMode The Hibernate LockMode.
*
* @return The JPA LockModeType
*/
public static LockModeType convertToLockModeType(LockMode lockMode) {
if ( lockMode == LockMode.NONE ) {
return LockModeType.NONE;
}
else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ ) {
return LockModeType.OPTIMISTIC;
}
else if ( lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT || lockMode == LockMode.WRITE ) {
return LockModeType.OPTIMISTIC_FORCE_INCREMENT;
}
else if ( lockMode == LockMode.PESSIMISTIC_READ ) {
return LockModeType.PESSIMISTIC_READ;
}
else if ( lockMode == LockMode.PESSIMISTIC_WRITE
|| lockMode == LockMode.UPGRADE
|| lockMode == LockMode.UPGRADE_NOWAIT ) {
return LockModeType.PESSIMISTIC_WRITE;
}
else if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT
|| lockMode == LockMode.FORCE ) {
return LockModeType.PESSIMISTIC_FORCE_INCREMENT;
}
throw new AssertionFailure( "unhandled lock mode " + lockMode );
}
/**
* Convert from JPA defined LockModeType to Hibernate specific LockMode.
*
* @param lockMode The JPA LockModeType
*
* @return The Hibernate LockMode.
*/
public static LockMode convertToLockMode(LockModeType lockMode) {
switch ( lockMode ) {
case READ:
case OPTIMISTIC: {
return LockMode.OPTIMISTIC;
}
case OPTIMISTIC_FORCE_INCREMENT:
case WRITE: {
return LockMode.OPTIMISTIC_FORCE_INCREMENT;
}
case PESSIMISTIC_READ: {
return LockMode.PESSIMISTIC_READ;
}
case PESSIMISTIC_WRITE: {
return LockMode.PESSIMISTIC_WRITE;
}
case PESSIMISTIC_FORCE_INCREMENT: {
return LockMode.PESSIMISTIC_FORCE_INCREMENT;
}
case NONE: {
return LockMode.NONE;
}
default: {
throw new AssertionFailure( "Unknown LockModeType: " + lockMode );
}
}
}
}

View File

@ -41,8 +41,9 @@ import org.hibernate.LockMode;
import org.hibernate.annotations.QueryHints;
import org.hibernate.cfg.NotYetImplementedException;
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.StringHelper;
import org.hibernate.metamodel.source.MetadataImplementor;
@ -163,13 +164,21 @@ public class QueryBinder {
}
metadata.addNamedQuery(
new NamedQueryDefinition(
name,
query, getBoolean( hints, QueryHints.CACHEABLE, name ), cacheRegion,
timeout, fetchSize, getFlushMode( hints, QueryHints.FLUSH_MODE, name ),
getCacheMode( hints, QueryHints.CACHE_MODE, name ),
getBoolean( hints, QueryHints.READ_ONLY, name ), comment, null
new NamedQueryDefinitionBuilder().setName( name ).setQuery( query ).setCacheable(
getBoolean(
hints,
QueryHints.CACHEABLE,
name
)
).setCacheRegion( cacheRegion ).setTimeout( timeout ).setFetchSize( fetchSize ).setFlushMode(
getFlushMode( hints, QueryHints.FLUSH_MODE, name )
).setCacheMode( getCacheMode( hints, QueryHints.CACHE_MODE, name ) ).setReadOnly(
getBoolean(
hints,
QueryHints.READ_ONLY,
name
)
).setComment( comment ).setParameterTypes( null ).createNamedQueryDefinition()
);
LOG.debugf( "Binding named query: %s => %s", name, query );
}
@ -215,13 +224,23 @@ public class QueryBinder {
boolean callable = getBoolean( hints, QueryHints.CALLABLE, name );
NamedSQLQueryDefinition def;
if ( StringHelper.isNotEmpty( resultSetMapping ) ) {
def = new NamedSQLQueryDefinition(
name,
query, resultSetMapping, null, cacheable,
cacheRegion, timeout, fetchSize,
flushMode, cacheMode, readOnly, comment,
null, callable
);
def = new NamedSQLQueryDefinitionBuilder().setName( name )
.setQuery( query )
.setResultSetRef(
resultSetMapping
)
.setQuerySpaces( null )
.setCacheable( cacheable )
.setCacheRegion( cacheRegion )
.setTimeout( timeout )
.setFetchSize( fetchSize )
.setFlushMode( flushMode )
.setCacheMode( cacheMode )
.setReadOnly( readOnly )
.setComment( comment )
.setParameterTypes( null )
.setCallable( callable )
.createNamedQueryDefinition();
}
else {
AnnotationValue annotationValue = annotation.value( "resultClass" );
@ -236,22 +255,21 @@ public class QueryBinder {
LockMode.READ
)
};
def = new NamedSQLQueryDefinition(
name,
query,
queryRoots,
null,
cacheable,
cacheRegion,
timeout,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
null,
callable
);
def = new NamedSQLQueryDefinitionBuilder().setName( name )
.setQuery( query )
.setQueryReturns( queryRoots )
.setQuerySpaces( null )
.setCacheable( cacheable )
.setCacheRegion( cacheRegion )
.setTimeout( timeout )
.setFetchSize( fetchSize )
.setFlushMode( flushMode )
.setCacheMode( cacheMode )
.setReadOnly( readOnly )
.setComment( comment )
.setParameterTypes( null )
.setCallable( callable )
.createNamedQueryDefinition();
}
metadata.addNamedNativeQuery( def );
LOG.debugf( "Binding named native query: %s => %s", name, query );

View File

@ -53,6 +53,10 @@ import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
import org.hibernate.ejb.internal.EntityManagerFactoryRegistry;
import org.hibernate.ejb.metamodel.MetamodelImpl;
import org.hibernate.ejb.util.PersistenceUtilHelper;
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.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.UUIDGenerator;
@ -228,12 +232,47 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
throw new PersistenceException( "Cannot use query non-Hibernate EntityManager query as basis for named query" );
}
// the spec requires that we keep information such as max results, hints etc. Currently the information
// stored about a named query does not contain all that information (see org.hibernate.engine.spi.NamedQueryDefinition)
//
// the most simple solution is to just add these needed values to org.hibernate.engine.spi.NamedQueryDefinition
// create and register the proper NamedQueryDefinition...
final org.hibernate.Query hibernateQuery = ( (HibernateQuery) query ).getHibernateQuery();
if ( org.hibernate.SQLQuery.class.isInstance( hibernateQuery ) ) {
final NamedSQLQueryDefinition namedQueryDefinition = extractSqlQueryDefinition( ( org.hibernate.SQLQuery ) hibernateQuery, name );
sessionFactory.registerNamedSQLQueryDefinition( name, namedQueryDefinition );
}
else {
final NamedQueryDefinition namedQueryDefinition = extractHqlQueryDefinition( hibernateQuery, name );
sessionFactory.registerNamedQueryDefinition( name, namedQueryDefinition );
}
}
throw new NotYetImplementedException();
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 NamedQueryDefinition extractHqlQueryDefinition(org.hibernate.Query hqlQuery, String name) {
final NamedQueryDefinitionBuilder builder = new NamedQueryDefinitionBuilder( name );
fillInNamedQueryBuilder( builder, hqlQuery );
// LockOptions only valid for HQL/JPQL queries...
builder.setLockOptions( hqlQuery.getLockOptions().makeCopy() );
return builder.createNamedQueryDefinition();
}
private void fillInNamedQueryBuilder(NamedQueryDefinitionBuilder builder, org.hibernate.Query query) {
builder.setQuery( query.getQueryString() )
.setComment( query.getComment() )
.setCacheable( query.isCacheable() )
.setCacheRegion( query.getCacheRegion() )
.setCacheMode( query.getCacheMode() )
.setTimeout( query.getTimeout() )
.setFetchSize( query.getFetchSize() )
.setFirstResult( query.getFirstResult() )
.setMaxResults( query.getMaxResults() )
.setReadOnly( query.isReadOnly() )
.setFlushMode( query.getFlushMode() );
}
@Override

View File

@ -22,8 +22,21 @@
* Boston, MA 02110-1301 USA\
*/
package org.hibernate.ejb;
import javax.persistence.Query;
/**
* Marker interface for Hibernate generated JPA queries so that we can access the underlying Hibernate query objects.
*
* @author Gavin King
* @author Emmanuel Bernard
* @author Steve Ebersole
*/
public interface HibernateQuery extends Query {
/**
* Gives access to the underlying Hibernate query object..
*
* @return THe Hibernate query object.
*/
public org.hibernate.Query getHibernateQuery();
}

View File

@ -27,6 +27,7 @@ import javax.persistence.LockModeType;
import org.hibernate.AssertionFailure;
import org.hibernate.LockMode;
import org.hibernate.internal.util.LockModeConverter;
/**
* Helper to deal with {@link LockModeType} <-> {@link LockMode} conversions.
@ -35,57 +36,11 @@ import org.hibernate.LockMode;
*/
public class LockModeTypeHelper {
public static LockModeType getLockModeType(LockMode lockMode) {
if ( lockMode == LockMode.NONE ) {
return LockModeType.NONE;
}
else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ ) {
return LockModeType.OPTIMISTIC;
}
else if ( lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT || lockMode == LockMode.WRITE ) {
return LockModeType.OPTIMISTIC_FORCE_INCREMENT;
}
else if ( lockMode == LockMode.PESSIMISTIC_READ ) {
return LockModeType.PESSIMISTIC_READ;
}
else if ( lockMode == LockMode.PESSIMISTIC_WRITE
|| lockMode == LockMode.UPGRADE
|| lockMode == LockMode.UPGRADE_NOWAIT ) {
return LockModeType.PESSIMISTIC_WRITE;
}
else if ( lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT
|| lockMode == LockMode.FORCE ) {
return LockModeType.PESSIMISTIC_FORCE_INCREMENT;
}
throw new AssertionFailure( "unhandled lock mode " + lockMode );
return LockModeConverter.convertToLockModeType( lockMode );
}
public static LockMode getLockMode(LockModeType lockMode) {
switch ( lockMode ) {
case READ:
case OPTIMISTIC: {
return LockMode.OPTIMISTIC;
}
case OPTIMISTIC_FORCE_INCREMENT:
case WRITE: {
return LockMode.OPTIMISTIC_FORCE_INCREMENT;
}
case PESSIMISTIC_READ: {
return LockMode.PESSIMISTIC_READ;
}
case PESSIMISTIC_WRITE: {
return LockMode.PESSIMISTIC_WRITE;
}
case PESSIMISTIC_FORCE_INCREMENT: {
return LockMode.PESSIMISTIC_FORCE_INCREMENT;
}
case NONE: {
return LockMode.NONE;
}
default: {
throw new AssertionFailure( "Unknown LockModeType: " + lockMode );
}
}
public static LockMode getLockMode(LockModeType lockModeType) {
return LockModeConverter.convertToLockMode( lockModeType );
}
public static LockMode interpretLockMode(Object value) {

View File

@ -8,12 +8,17 @@ import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.Id;
import javax.persistence.LockModeType;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.QueryHint;
import javax.persistence.SqlResultSetMapping;
import org.hibernate.annotations.QueryHints;
/**
* @author Gavin King
*/
@ -36,8 +41,23 @@ import javax.persistence.SqlResultSetMapping;
resultClass = Item.class
)
})
@NamedQueries({
@NamedQuery(
name = "itemJpaQueryWithLockModeAndHints",
query = "select i from Item i",
lockMode = LockModeType.PESSIMISTIC_WRITE,
hints = {
@QueryHint( name = QueryHints.TIMEOUT_JPA, value = "3000" ),
@QueryHint( name = QueryHints.CACHE_MODE, value = "ignore" ),
@QueryHint( name = QueryHints.CACHEABLE, value = "true" ),
@QueryHint( name = QueryHints.READ_ONLY, value = "true" ),
@QueryHint( name = QueryHints.COMMENT, value = "custom static comment" ),
@QueryHint( name = QueryHints.FETCH_SIZE, value = "512" ),
@QueryHint( name = QueryHints.FLUSH_MODE, value = "manual" )
}
),
@NamedQuery(name = "query-construct", query = "select new Item(i.name,i.descr) from Item i")
//@Cache(region="Item", usage=NONSTRICT_READ_WRITE)
})
public class Item implements Serializable {
private String name;

View File

@ -0,0 +1,127 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.ejb.test.query;
import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.Query;
import javax.persistence.QueryHint;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockMode;
import org.hibernate.ejb.HibernateQuery;
import org.hibernate.ejb.QueryHints;
import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.ejb.test.Distributor;
import org.hibernate.ejb.test.Item;
import org.hibernate.ejb.test.Wallet;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Tests for {@link javax.persistence.EntityManagerFactory#addNamedQuery} handling.
*
* @author Steve Ebersole
*/
public class AddNamedQueryTest extends BaseEntityManagerFunctionalTestCase {
@Override
public Class[] getAnnotatedClasses() {
return new Class[]{
Item.class,
Distributor.class,
Wallet.class
};
}
@Test
public void basicTest() {
// just making sure we can add one and that it is usable when we get it back
EntityManager em = getOrCreateEntityManager();
Query query = em.createQuery( "from Item" );
final String name = "myBasicItemQuery";
em.getEntityManagerFactory().addNamedQuery( name, query );
Query query2 = em.createNamedQuery( name );
query2.getResultList();
em.close();
}
@Test
public void testConfigValueHandling() {
final String name = "itemJpaQueryWithLockModeAndHints";
EntityManager em = getOrCreateEntityManager();
Query query = em.createNamedQuery( name );
org.hibernate.Query hibernateQuery = ( (HibernateQuery) query ).getHibernateQuery();
// assert the state of the query config settings based on the initial named query
assertNull( hibernateQuery.getFirstResult() );
assertNull( hibernateQuery.getMaxResults() );
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() ); // todo : we need to fix this to stick to AUTO/COMMIT when used from JPA
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
assertEquals( (Integer) 3, hibernateQuery.getTimeout() ); // jpa timeout is in milliseconds, whereas Hibernate's is in seconds
query.setHint( QueryHints.HINT_TIMEOUT, 10 );
em.getEntityManagerFactory().addNamedQuery( name, query );
query = em.createNamedQuery( name );
hibernateQuery = ( (HibernateQuery) query ).getHibernateQuery();
// assert the state of the query config settings based on the initial named query
assertNull( hibernateQuery.getFirstResult() );
assertNull( hibernateQuery.getMaxResults() );
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() );
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
query.setHint( QueryHints.SPEC_HINT_TIMEOUT, 10000 );
em.getEntityManagerFactory().addNamedQuery( name, query );
query = em.createNamedQuery( name );
hibernateQuery = ( (HibernateQuery) query ).getHibernateQuery();
// assert the state of the query config settings based on the initial named query
assertNull( hibernateQuery.getFirstResult() );
assertNull( hibernateQuery.getMaxResults() );
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() );
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
query.setFirstResult( 51 );
em.getEntityManagerFactory().addNamedQuery( name, query );
query = em.createNamedQuery( name );
hibernateQuery = ( (HibernateQuery) query ).getHibernateQuery();
// assert the state of the query config settings based on the initial named query
assertEquals( (Integer) 51, hibernateQuery.getFirstResult() );
assertNull( hibernateQuery.getMaxResults() );
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() );
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
}
}