HHH-8518 - Validate EMF#addNamedQuery transfers all query settings
This commit is contained in:
parent
feaac3b917
commit
346d958c20
|
@ -378,6 +378,16 @@ public class SessionDelegatorBaseImpl implements SessionImplementor, Session {
|
||||||
return sessionImplementor.getLoadQueryInfluencers();
|
return sessionImplementor.getLoadQueryInfluencers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Query createQuery(NamedQueryDefinition namedQueryDefinition) {
|
||||||
|
return sessionImplementor.createQuery( namedQueryDefinition );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SQLQuery createSQLQuery(NamedSQLQueryDefinition namedQueryDefinition) {
|
||||||
|
return sessionImplementor.createSQLQuery( namedQueryDefinition );
|
||||||
|
}
|
||||||
|
|
||||||
// Delegates to Session
|
// Delegates to Session
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.FlushMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
import org.hibernate.Query;
|
import org.hibernate.Query;
|
||||||
|
import org.hibernate.SQLQuery;
|
||||||
import org.hibernate.ScrollMode;
|
import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.cache.spi.CacheKey;
|
import org.hibernate.cache.spi.CacheKey;
|
||||||
|
@ -389,4 +390,22 @@ public interface SessionImplementor extends Serializable, LobCreationContext {
|
||||||
* should never be null.
|
* should never be null.
|
||||||
*/
|
*/
|
||||||
public LoadQueryInfluencers getLoadQueryInfluencers();
|
public LoadQueryInfluencers getLoadQueryInfluencers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used from EntityManager
|
||||||
|
*
|
||||||
|
* @param namedQueryDefinition The named query definition
|
||||||
|
*
|
||||||
|
* @return The basic HQL/JPQL query (without saved settings applied)
|
||||||
|
*/
|
||||||
|
Query createQuery(NamedQueryDefinition namedQueryDefinition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used from EntityManager
|
||||||
|
*
|
||||||
|
* @param namedQueryDefinition The named query definition
|
||||||
|
*
|
||||||
|
* @return The basic SQL query (without saved settings applied)
|
||||||
|
*/
|
||||||
|
SQLQuery createSQLQuery(NamedSQLQueryDefinition namedQueryDefinition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,36 +133,50 @@ public abstract class AbstractSessionImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Query createQuery(NamedQueryDefinition namedQueryDefinition) {
|
||||||
|
String queryString = namedQueryDefinition.getQueryString();
|
||||||
|
final Query query = new QueryImpl(
|
||||||
|
queryString,
|
||||||
|
namedQueryDefinition.getFlushMode(),
|
||||||
|
this,
|
||||||
|
getHQLQueryPlan( queryString, false ).getParameterMetadata()
|
||||||
|
);
|
||||||
|
query.setComment( "named HQL query " + namedQueryDefinition.getName() );
|
||||||
|
if ( namedQueryDefinition.getLockOptions() != null ) {
|
||||||
|
query.setLockOptions( namedQueryDefinition.getLockOptions() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SQLQuery createSQLQuery(NamedSQLQueryDefinition namedQueryDefinition) {
|
||||||
|
final ParameterMetadata parameterMetadata = factory.getQueryPlanCache().getSQLParameterMetadata( namedQueryDefinition.getQueryString() );
|
||||||
|
final SQLQuery query = new SQLQueryImpl(
|
||||||
|
namedQueryDefinition,
|
||||||
|
this,
|
||||||
|
parameterMetadata
|
||||||
|
);
|
||||||
|
query.setComment( "named native SQL query " + namedQueryDefinition.getName() );
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query getNamedQuery(String queryName) throws MappingException {
|
public Query getNamedQuery(String queryName) throws MappingException {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
NamedQueryDefinition nqd = factory.getNamedQuery( queryName );
|
NamedQueryDefinition nqd = factory.getNamedQuery( queryName );
|
||||||
final Query query;
|
final Query query;
|
||||||
if ( nqd != null ) {
|
if ( nqd != null ) {
|
||||||
String queryString = nqd.getQueryString();
|
query = createQuery( nqd );
|
||||||
query = new QueryImpl(
|
|
||||||
queryString,
|
|
||||||
nqd.getFlushMode(),
|
|
||||||
this,
|
|
||||||
getHQLQueryPlan( queryString, false ).getParameterMetadata()
|
|
||||||
);
|
|
||||||
query.setComment( "named HQL query " + queryName );
|
|
||||||
if ( nqd.getLockOptions() != null ) {
|
|
||||||
query.setLockOptions( nqd.getLockOptions() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NamedSQLQueryDefinition nsqlqd = factory.getNamedSQLQuery( queryName );
|
NamedSQLQueryDefinition nsqlqd = factory.getNamedSQLQuery( queryName );
|
||||||
if ( nsqlqd==null ) {
|
if ( nsqlqd==null ) {
|
||||||
throw new MappingException( "Named query not known: " + queryName );
|
throw new MappingException( "Named query not known: " + queryName );
|
||||||
}
|
}
|
||||||
ParameterMetadata parameterMetadata = factory.getQueryPlanCache().getSQLParameterMetadata( nsqlqd.getQueryString() );
|
|
||||||
query = new SQLQueryImpl(
|
query = createSQLQuery( nsqlqd );
|
||||||
nsqlqd,
|
|
||||||
this,
|
|
||||||
parameterMetadata
|
|
||||||
);
|
|
||||||
query.setComment( "named native SQL query " + queryName );
|
|
||||||
nqd = nsqlqd;
|
nqd = nsqlqd;
|
||||||
}
|
}
|
||||||
initQuery( query, nqd );
|
initQuery( query, nqd );
|
||||||
|
|
|
@ -86,14 +86,18 @@ import org.hibernate.StaleStateException;
|
||||||
import org.hibernate.TransientObjectException;
|
import org.hibernate.TransientObjectException;
|
||||||
import org.hibernate.TypeMismatchException;
|
import org.hibernate.TypeMismatchException;
|
||||||
import org.hibernate.UnresolvableObjectException;
|
import org.hibernate.UnresolvableObjectException;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.lock.LockingStrategyException;
|
import org.hibernate.dialect.lock.LockingStrategyException;
|
||||||
import org.hibernate.dialect.lock.OptimisticEntityLockException;
|
import org.hibernate.dialect.lock.OptimisticEntityLockException;
|
||||||
import org.hibernate.dialect.lock.PessimisticEntityLockException;
|
import org.hibernate.dialect.lock.PessimisticEntityLockException;
|
||||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||||
import org.hibernate.engine.query.spi.HQLQueryPlan;
|
import org.hibernate.engine.query.spi.HQLQueryPlan;
|
||||||
|
import org.hibernate.engine.query.spi.sql.NativeSQLQueryConstructorReturn;
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
||||||
|
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||||
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
|
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
@ -763,93 +767,178 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query createNamedQuery(String name) {
|
public Query createNamedQuery(String name) {
|
||||||
|
return buildQueryFromName( name, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private QueryImpl buildQueryFromName(String name, Class resultType) {
|
||||||
checkOpen();
|
checkOpen();
|
||||||
try {
|
|
||||||
org.hibernate.Query namedQuery = internalGetSession().getNamedQuery( name );
|
// we can't just call Session#getNamedQuery because we need to apply stored setting at the JPA Query
|
||||||
try {
|
// level too
|
||||||
return new QueryImpl( namedQuery, this );
|
|
||||||
}
|
final SessionFactoryImplementor sfi = entityManagerFactory.getSessionFactory();
|
||||||
catch ( RuntimeException e ) {
|
|
||||||
throw convert( e );
|
// first try as hql/jpql query
|
||||||
|
{
|
||||||
|
final NamedQueryDefinition namedQueryDefinition = sfi.getNamedQueryRepository().getNamedQueryDefinition( name );
|
||||||
|
if ( namedQueryDefinition != null ) {
|
||||||
|
return createNamedJpqlQuery( namedQueryDefinition, resultType );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( MappingException e ) {
|
|
||||||
throw convert(new IllegalArgumentException( "Named query not found: " + name ));
|
// then as a native (SQL) query
|
||||||
|
{
|
||||||
|
final NamedSQLQueryDefinition namedQueryDefinition = sfi.getNamedQueryRepository().getNamedSQLQueryDefinition( name );
|
||||||
|
if ( namedQueryDefinition != null ) {
|
||||||
|
return createNamedSqlQuery( namedQueryDefinition, resultType );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw convert( new IllegalArgumentException( "No query defined for that name [" + name + "]" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected QueryImpl createNamedJpqlQuery(NamedQueryDefinition namedQueryDefinition, Class resultType) {
|
||||||
|
final org.hibernate.Query hibQuery = ( (SessionImplementor) internalGetSession() ).createQuery( namedQueryDefinition );
|
||||||
|
if ( resultType != null ) {
|
||||||
|
resultClassChecking( resultType, hibQuery );
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapAsJpaQuery( namedQueryDefinition, hibQuery );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected QueryImpl wrapAsJpaQuery(NamedQueryDefinition namedQueryDefinition, org.hibernate.Query hibQuery) {
|
||||||
|
try {
|
||||||
|
final QueryImpl jpaQuery = new QueryImpl( hibQuery, this );
|
||||||
|
applySavedSettings( namedQueryDefinition, jpaQuery );
|
||||||
|
return jpaQuery;
|
||||||
|
}
|
||||||
|
catch ( RuntimeException e ) {
|
||||||
|
throw convert( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void applySavedSettings(NamedQueryDefinition namedQueryDefinition, QueryImpl jpaQuery) {
|
||||||
|
if ( namedQueryDefinition.isCacheable() ) {
|
||||||
|
jpaQuery.setHint( QueryHints.HINT_CACHEABLE, true );
|
||||||
|
if ( namedQueryDefinition.getCacheRegion() != null ) {
|
||||||
|
jpaQuery.setHint( QueryHints.HINT_CACHE_REGION, namedQueryDefinition.getCacheRegion() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getCacheMode() != null ) {
|
||||||
|
jpaQuery.setHint( QueryHints.HINT_CACHE_MODE, namedQueryDefinition.getCacheMode() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.isReadOnly() ) {
|
||||||
|
jpaQuery.setHint( QueryHints.HINT_READONLY, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getTimeout() != null ) {
|
||||||
|
jpaQuery.setHint( QueryHints.SPEC_HINT_TIMEOUT, namedQueryDefinition.getTimeout() * 1000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getFetchSize() != null ) {
|
||||||
|
jpaQuery.setHint( QueryHints.HINT_FETCH_SIZE, namedQueryDefinition.getFetchSize() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getComment() != null ) {
|
||||||
|
jpaQuery.setHint( QueryHints.HINT_COMMENT, namedQueryDefinition.getComment() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getFirstResult() != null ) {
|
||||||
|
jpaQuery.setFirstResult( namedQueryDefinition.getFirstResult() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getMaxResults() != null ) {
|
||||||
|
jpaQuery.setMaxResults( namedQueryDefinition.getMaxResults() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getLockOptions() != null ) {
|
||||||
|
if ( namedQueryDefinition.getLockOptions().getLockMode() != null ) {
|
||||||
|
jpaQuery.setLockMode(
|
||||||
|
LockModeTypeHelper.getLockModeType( namedQueryDefinition.getLockOptions().getLockMode() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedQueryDefinition.getFlushMode() != null ) {
|
||||||
|
if ( namedQueryDefinition.getFlushMode() == FlushMode.COMMIT ) {
|
||||||
|
jpaQuery.setFlushMode( FlushModeType.COMMIT );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jpaQuery.setFlushMode( FlushModeType.AUTO );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected QueryImpl createNamedSqlQuery(NamedSQLQueryDefinition namedQueryDefinition, Class resultType) {
|
||||||
|
if ( resultType != null ) {
|
||||||
|
resultClassChecking( resultType, namedQueryDefinition );
|
||||||
|
}
|
||||||
|
return wrapAsJpaQuery(
|
||||||
|
namedQueryDefinition,
|
||||||
|
( (SessionImplementor) internalGetSession() ).createSQLQuery( namedQueryDefinition )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void resultClassChecking(Class resultType, NamedSQLQueryDefinition namedQueryDefinition) {
|
||||||
|
final SessionFactoryImplementor sfi = entityManagerFactory.getSessionFactory();
|
||||||
|
|
||||||
|
final NativeSQLQueryReturn[] queryReturns;
|
||||||
|
if ( namedQueryDefinition.getQueryReturns() != null ) {
|
||||||
|
queryReturns = namedQueryDefinition.getQueryReturns();
|
||||||
|
}
|
||||||
|
else if ( namedQueryDefinition.getResultSetRef() != null ) {
|
||||||
|
final ResultSetMappingDefinition rsMapping = sfi.getResultSetMapping( namedQueryDefinition.getResultSetRef() );
|
||||||
|
queryReturns = rsMapping.getQueryReturns();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new AssertionFailure( "Unsupported named query model. Please report the bug in Hibernate EntityManager");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( queryReturns.length > 1 ) {
|
||||||
|
throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
|
||||||
|
}
|
||||||
|
|
||||||
|
final NativeSQLQueryReturn nativeSQLQueryReturn = queryReturns[0];
|
||||||
|
|
||||||
|
if ( nativeSQLQueryReturn instanceof NativeSQLQueryRootReturn ) {
|
||||||
|
final Class<?> actualReturnedClass;
|
||||||
|
final String entityClassName = ( (NativeSQLQueryRootReturn) nativeSQLQueryReturn ).getReturnEntityName();
|
||||||
|
try {
|
||||||
|
actualReturnedClass = sfi.getServiceRegistry().getService( ClassLoaderService.class ).classForName( entityClassName );
|
||||||
|
}
|
||||||
|
catch ( ClassLoadingException e ) {
|
||||||
|
throw new AssertionFailure(
|
||||||
|
"Unable to load class [" + entityClassName + "] declared on named native query [" +
|
||||||
|
namedQueryDefinition.getName() + "]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ( !resultType.isAssignableFrom( actualReturnedClass ) ) {
|
||||||
|
throw buildIncompatibleException( resultType, actualReturnedClass );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( nativeSQLQueryReturn instanceof NativeSQLQueryConstructorReturn ) {
|
||||||
|
final NativeSQLQueryConstructorReturn ctorRtn = (NativeSQLQueryConstructorReturn) nativeSQLQueryReturn;
|
||||||
|
if ( !resultType.isAssignableFrom( ctorRtn.getTargetClass() ) ) {
|
||||||
|
throw buildIncompatibleException( resultType, ctorRtn.getTargetClass() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//TODO support other NativeSQLQueryReturn type. For now let it go.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
|
public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
|
||||||
checkOpen();
|
return buildQueryFromName( name, resultClass );
|
||||||
try {
|
|
||||||
/*
|
|
||||||
* Get the named query.
|
|
||||||
* If the named query is a SQL query, get the expected returned type from the query definition
|
|
||||||
* or its associated result set mapping
|
|
||||||
* If the named query is a HQL query, use getReturnType()
|
|
||||||
*/
|
|
||||||
org.hibernate.Query namedQuery = internalGetSession().getNamedQuery( name );
|
|
||||||
//TODO clean this up to avoid downcasting
|
|
||||||
final SessionFactoryImplementor factoryImplementor = entityManagerFactory.getSessionFactory();
|
|
||||||
final NamedSQLQueryDefinition queryDefinition = factoryImplementor.getNamedSQLQuery( name );
|
|
||||||
try {
|
|
||||||
if ( queryDefinition != null ) {
|
|
||||||
Class<?> actualReturnedClass;
|
|
||||||
|
|
||||||
final NativeSQLQueryReturn[] queryReturns;
|
|
||||||
if ( queryDefinition.getQueryReturns() != null ) {
|
|
||||||
queryReturns = queryDefinition.getQueryReturns();
|
|
||||||
}
|
|
||||||
else if ( queryDefinition.getResultSetRef() != null ) {
|
|
||||||
final ResultSetMappingDefinition rsMapping = factoryImplementor.getResultSetMapping(
|
|
||||||
queryDefinition.getResultSetRef()
|
|
||||||
);
|
|
||||||
queryReturns = rsMapping.getQueryReturns();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new AssertionFailure( "Unsupported named query model. Please report the bug in Hibernate EntityManager");
|
|
||||||
}
|
|
||||||
if ( queryReturns.length > 1 ) {
|
|
||||||
throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
|
|
||||||
}
|
|
||||||
final NativeSQLQueryReturn nativeSQLQueryReturn = queryReturns[0];
|
|
||||||
if ( nativeSQLQueryReturn instanceof NativeSQLQueryRootReturn ) {
|
|
||||||
final String entityClassName = ( ( NativeSQLQueryRootReturn ) nativeSQLQueryReturn ).getReturnEntityName();
|
|
||||||
try {
|
|
||||||
actualReturnedClass = ReflectHelper.classForName( entityClassName, AbstractEntityManagerImpl.class );
|
|
||||||
}
|
|
||||||
catch ( ClassNotFoundException e ) {
|
|
||||||
throw new AssertionFailure( "Unable to instantiate class declared on named native query: " + name + " " + entityClassName );
|
|
||||||
}
|
|
||||||
if ( !resultClass.isAssignableFrom( actualReturnedClass ) ) {
|
|
||||||
throw buildIncompatibleException( resultClass, actualReturnedClass );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//TODO support other NativeSQLQueryReturn type. For now let it go.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resultClassChecking( resultClass, namedQuery );
|
|
||||||
}
|
|
||||||
return new QueryImpl<T>( namedQuery, this );
|
|
||||||
}
|
|
||||||
catch ( RuntimeException e ) {
|
|
||||||
throw convert( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( MappingException e ) {
|
|
||||||
throw convert(new IllegalArgumentException( "Named query not found: " + name ));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IllegalArgumentException buildIncompatibleException(Class<?> resultClass, Class<?> actualResultClass) {
|
private IllegalArgumentException buildIncompatibleException(Class<?> resultClass, Class<?> actualResultClass) {
|
||||||
return new IllegalArgumentException(
|
return new IllegalArgumentException(
|
||||||
"Type specified for TypedQuery [" +
|
"Type specified for TypedQuery [" + resultClass.getName() +
|
||||||
resultClass.getName() +
|
"] is incompatible with query return type [" + actualResultClass + "]"
|
||||||
"] is incompatible with query return type [" +
|
);
|
||||||
actualResultClass + "]"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
package org.hibernate.jpa.spi;
|
package org.hibernate.jpa.spi;
|
||||||
|
|
||||||
import javax.persistence.FlushModeType;
|
import javax.persistence.FlushModeType;
|
||||||
|
import javax.persistence.LockModeType;
|
||||||
import javax.persistence.Parameter;
|
import javax.persistence.Parameter;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
import javax.persistence.TransactionRequiredException;
|
import javax.persistence.TransactionRequiredException;
|
||||||
|
@ -118,12 +119,18 @@ public abstract class AbstractQueryImpl<X> extends BaseQueryImpl implements Type
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
|
public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
|
||||||
checkOpen( true );
|
checkOpen( true );
|
||||||
if (! getEntityManager().isTransactionInProgress()) {
|
|
||||||
throw new TransactionRequiredException( "no transaction is in progress" );
|
// todo : technically this check should be on execution of the query, not here : HHH-8521
|
||||||
|
if ( lockModeType != LockModeType.NONE ) {
|
||||||
|
if (! getEntityManager().isTransactionInProgress()) {
|
||||||
|
throw new TransactionRequiredException( "no transaction is in progress" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! canApplyAliasSpecificLockModeHints() ) {
|
if ( ! canApplyAliasSpecificLockModeHints() ) {
|
||||||
throw new IllegalStateException( "Not a JPAQL/Criteria query" );
|
throw new IllegalStateException( "Not a JPAQL/Criteria query" );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.jpaLockMode = lockModeType;
|
this.jpaLockMode = lockModeType;
|
||||||
internalApplyLockMode( lockModeType );
|
internalApplyLockMode( lockModeType );
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
package org.hibernate.jpa.test.query;
|
package org.hibernate.jpa.test.query;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.FlushModeType;
|
||||||
|
import javax.persistence.LockModeType;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
|
@ -31,6 +33,8 @@ import org.hibernate.FlushMode;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.ejb.HibernateQuery;
|
import org.hibernate.ejb.HibernateQuery;
|
||||||
import org.hibernate.ejb.QueryHints;
|
import org.hibernate.ejb.QueryHints;
|
||||||
|
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
import org.hibernate.jpa.test.Distributor;
|
import org.hibernate.jpa.test.Distributor;
|
||||||
import org.hibernate.jpa.test.Item;
|
import org.hibernate.jpa.test.Item;
|
||||||
|
@ -69,6 +73,60 @@ public class AddNamedQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
em.close();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLockModeHandling() {
|
||||||
|
final String name = "lock-mode-handling";
|
||||||
|
|
||||||
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
Query q = em.createQuery( "from Item" );
|
||||||
|
assertEquals( LockModeType.NONE, q.getLockMode() );
|
||||||
|
q.setLockMode( LockModeType.OPTIMISTIC );
|
||||||
|
assertEquals( LockModeType.OPTIMISTIC, q.getLockMode() );
|
||||||
|
em.getEntityManagerFactory().addNamedQuery( name, q );
|
||||||
|
|
||||||
|
// first, lets check the underlying stored query def
|
||||||
|
SessionFactoryImplementor sfi = entityManagerFactory().unwrap( SessionFactoryImplementor.class );
|
||||||
|
NamedQueryDefinition def = sfi.getNamedQueryRepository().getNamedQueryDefinition( name );
|
||||||
|
assertEquals( LockMode.OPTIMISTIC, def.getLockOptions().getLockMode() );
|
||||||
|
|
||||||
|
// then lets create a query by name and check its setting
|
||||||
|
q = em.createNamedQuery( name );
|
||||||
|
assertEquals( LockMode.OPTIMISTIC, q.unwrap( org.hibernate.Query.class ).getLockOptions().getLockMode() );
|
||||||
|
assertEquals( LockModeType.OPTIMISTIC, q.getLockMode() );
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlushModeHandling() {
|
||||||
|
final String name = "flush-mode-handling";
|
||||||
|
|
||||||
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
Query q = em.createQuery( "from Item" );
|
||||||
|
assertEquals( FlushModeType.AUTO, q.getFlushMode() );
|
||||||
|
q.setFlushMode( FlushModeType.COMMIT );
|
||||||
|
assertEquals( FlushModeType.COMMIT, q.getFlushMode() );
|
||||||
|
em.getEntityManagerFactory().addNamedQuery( name, q );
|
||||||
|
|
||||||
|
// first, lets check the underlying stored query def
|
||||||
|
SessionFactoryImplementor sfi = entityManagerFactory().unwrap( SessionFactoryImplementor.class );
|
||||||
|
NamedQueryDefinition def = sfi.getNamedQueryRepository().getNamedQueryDefinition( name );
|
||||||
|
assertEquals( FlushMode.COMMIT, def.getFlushMode() );
|
||||||
|
|
||||||
|
// then lets create a query by name and check its setting
|
||||||
|
q = em.createNamedQuery( name );
|
||||||
|
assertEquals( FlushMode.COMMIT, q.unwrap( org.hibernate.Query.class ).getFlushMode() );
|
||||||
|
assertEquals( FlushModeType.COMMIT, q.getFlushMode() );
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConfigValueHandling() {
|
public void testConfigValueHandling() {
|
||||||
final String name = "itemJpaQueryWithLockModeAndHints";
|
final String name = "itemJpaQueryWithLockModeAndHints";
|
||||||
|
@ -78,7 +136,7 @@ public class AddNamedQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
// assert the state of the query config settings based on the initial named query
|
// assert the state of the query config settings based on the initial named query
|
||||||
assertNull( hibernateQuery.getFirstResult() );
|
assertNull( hibernateQuery.getFirstResult() );
|
||||||
assertNull( hibernateQuery.getMaxResults() );
|
assertNull( hibernateQuery.getMaxResults() );
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() ); // todo : we need to fix this to stick to AUTO/COMMIT when used from JPA
|
assertEquals( FlushMode.AUTO, hibernateQuery.getFlushMode() );
|
||||||
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
||||||
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
||||||
assertEquals( (Integer) 3, hibernateQuery.getTimeout() ); // jpa timeout is in milliseconds, whereas Hibernate's is in seconds
|
assertEquals( (Integer) 3, hibernateQuery.getTimeout() ); // jpa timeout is in milliseconds, whereas Hibernate's is in seconds
|
||||||
|
@ -91,7 +149,7 @@ public class AddNamedQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
// assert the state of the query config settings based on the initial named query
|
// assert the state of the query config settings based on the initial named query
|
||||||
assertNull( hibernateQuery.getFirstResult() );
|
assertNull( hibernateQuery.getFirstResult() );
|
||||||
assertNull( hibernateQuery.getMaxResults() );
|
assertNull( hibernateQuery.getMaxResults() );
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() );
|
assertEquals( FlushMode.AUTO, hibernateQuery.getFlushMode() );
|
||||||
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
||||||
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
||||||
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
||||||
|
@ -104,7 +162,7 @@ public class AddNamedQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
// assert the state of the query config settings based on the initial named query
|
// assert the state of the query config settings based on the initial named query
|
||||||
assertNull( hibernateQuery.getFirstResult() );
|
assertNull( hibernateQuery.getFirstResult() );
|
||||||
assertNull( hibernateQuery.getMaxResults() );
|
assertNull( hibernateQuery.getMaxResults() );
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() );
|
assertEquals( FlushMode.AUTO, hibernateQuery.getFlushMode() );
|
||||||
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
||||||
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
||||||
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
||||||
|
@ -117,7 +175,7 @@ public class AddNamedQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
// assert the state of the query config settings based on the initial named query
|
// assert the state of the query config settings based on the initial named query
|
||||||
assertEquals( (Integer) 51, hibernateQuery.getFirstResult() );
|
assertEquals( (Integer) 51, hibernateQuery.getFirstResult() );
|
||||||
assertNull( hibernateQuery.getMaxResults() );
|
assertNull( hibernateQuery.getMaxResults() );
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getFlushMode() );
|
assertEquals( FlushMode.AUTO, hibernateQuery.getFlushMode() );
|
||||||
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
||||||
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
||||||
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
||||||
|
|
Loading…
Reference in New Issue