Merge remote-tracking branch 'upstream/main' into wip/6.0
This commit is contained in:
commit
236e901cd1
|
@ -142,7 +142,7 @@ ext {
|
||||||
mariadb: 'org.mariadb.jdbc:mariadb-java-client:2.2.3',
|
mariadb: 'org.mariadb.jdbc:mariadb-java-client:2.2.3',
|
||||||
cockroachdb: 'org.postgresql:postgresql:42.2.8',
|
cockroachdb: 'org.postgresql:postgresql:42.2.8',
|
||||||
|
|
||||||
oracle: 'com.oracle.database.jdbc:ojdbc8:21.1.0.0',
|
oracle: 'com.oracle.database.jdbc:ojdbc8:21.3.0.0',
|
||||||
mssql: 'com.microsoft.sqlserver:mssql-jdbc:7.2.1.jre8',
|
mssql: 'com.microsoft.sqlserver:mssql-jdbc:7.2.1.jre8',
|
||||||
db2: 'com.ibm.db2:jcc:11.5.4.0',
|
db2: 'com.ibm.db2:jcc:11.5.4.0',
|
||||||
hana: 'com.sap.cloud.db.jdbc:ngdbc:2.4.59',
|
hana: 'com.sap.cloud.db.jdbc:ngdbc:2.4.59',
|
||||||
|
|
|
@ -684,7 +684,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
|
|
||||||
try {
|
try {
|
||||||
NativeQueryImpl query = new NativeQueryImpl( queryString, this );
|
NativeQueryImpl query = new NativeQueryImpl( queryString, this );
|
||||||
query.setComment( "dynamic native SQL query" );
|
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||||
|
query.setComment( "dynamic native SQL query" );
|
||||||
|
}
|
||||||
applyQuerySettingsAndHints( query );
|
applyQuerySettingsAndHints( query );
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
@ -796,7 +798,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
|
|
||||||
if ( namedHqlDescriptor != null ) {
|
if ( namedHqlDescriptor != null ) {
|
||||||
HqlQueryImplementor<T> query = namedHqlDescriptor.toQuery( this, resultType );
|
HqlQueryImplementor<T> query = namedHqlDescriptor.toQuery( this, resultType );
|
||||||
query.setComment( "dynamic HQL query" );
|
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||||
|
query.setComment( "dynamic HQL query" );
|
||||||
|
}
|
||||||
applyQuerySettingsAndHints( query );
|
applyQuerySettingsAndHints( query );
|
||||||
if ( namedHqlDescriptor.getLockOptions() != null ) {
|
if ( namedHqlDescriptor.getLockOptions() != null ) {
|
||||||
query.setLockOptions( namedHqlDescriptor.getLockOptions() );
|
query.setLockOptions( namedHqlDescriptor.getLockOptions() );
|
||||||
|
@ -817,7 +821,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
else {
|
else {
|
||||||
query = namedNativeDescriptor.toQuery( this, resultType );
|
query = namedNativeDescriptor.toQuery( this, resultType );
|
||||||
}
|
}
|
||||||
query.setComment( "dynamic native SQL query" );
|
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||||
|
query.setComment( "dynamic native SQL query" );
|
||||||
|
}
|
||||||
applyQuerySettingsAndHints( query );
|
applyQuerySettingsAndHints( query );
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,7 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||||
import org.hibernate.proxy.HibernateProxyHelper;
|
import org.hibernate.proxy.HibernateProxyHelper;
|
||||||
import org.hibernate.query.QueryLogging;
|
import org.hibernate.query.QueryLogging;
|
||||||
import org.hibernate.query.hql.spi.HqlQueryImplementor;
|
import org.hibernate.query.hql.spi.HqlQueryImplementor;
|
||||||
|
import org.hibernate.query.named.NamedObjectRepository;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.spi.QueryImplementor;
|
import org.hibernate.query.spi.QueryImplementor;
|
||||||
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
||||||
|
@ -899,10 +900,11 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
// query implementations
|
// query implementations
|
||||||
|
|
||||||
// first, handle StoredProcedureQuery
|
// first, handle StoredProcedureQuery
|
||||||
|
final NamedObjectRepository namedObjectRepository = getQueryEngine().getNamedObjectRepository();
|
||||||
try {
|
try {
|
||||||
final ProcedureCallImplementor unwrapped = query.unwrap( ProcedureCallImplementor.class );
|
final ProcedureCallImplementor unwrapped = query.unwrap( ProcedureCallImplementor.class );
|
||||||
if ( unwrapped != null ) {
|
if ( unwrapped != null ) {
|
||||||
getQueryEngine().getNamedObjectRepository().registerCallableQueryMemento(
|
namedObjectRepository.registerCallableQueryMemento(
|
||||||
name,
|
name,
|
||||||
unwrapped.toMemento( name )
|
unwrapped.toMemento( name )
|
||||||
);
|
);
|
||||||
|
@ -919,13 +921,14 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
if ( hibernateQuery != null ) {
|
if ( hibernateQuery != null ) {
|
||||||
// create and register the proper NamedQueryDefinition...
|
// create and register the proper NamedQueryDefinition...
|
||||||
if ( hibernateQuery instanceof NativeQueryImplementor ) {
|
if ( hibernateQuery instanceof NativeQueryImplementor ) {
|
||||||
getQueryEngine().getNamedObjectRepository().registerNativeQueryMemento(
|
namedObjectRepository.registerNativeQueryMemento(
|
||||||
name,
|
name,
|
||||||
( (NativeQueryImplementor) hibernateQuery ).toMemento( name )
|
( (NativeQueryImplementor) hibernateQuery ).toMemento( name )
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
getQueryEngine().getNamedObjectRepository().registerHqlQueryMemento(
|
namedObjectRepository.registerHqlQueryMemento(
|
||||||
name,
|
name,
|
||||||
( ( HqlQueryImplementor ) hibernateQuery ).toMemento( name )
|
( ( HqlQueryImplementor ) hibernateQuery ).toMemento( name )
|
||||||
);
|
);
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.FetchMode;
|
||||||
import org.hibernate.Filter;
|
import org.hibernate.Filter;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.JDBCException;
|
import org.hibernate.JDBCException;
|
||||||
|
import org.hibernate.LazyInitializationException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -1609,8 +1610,9 @@ public abstract class AbstractEntityPersister
|
||||||
// for the collection to the just loaded collection
|
// for the collection to the just loaded collection
|
||||||
final EntityEntry ownerEntry = persistenceContext.getEntry( entity );
|
final EntityEntry ownerEntry = persistenceContext.getEntry( entity );
|
||||||
if ( ownerEntry == null ) {
|
if ( ownerEntry == null ) {
|
||||||
// not good
|
// the entity is not in the session; it was probably deleted,
|
||||||
throw new AssertionFailure(
|
// so we cannot load the collection anymore.
|
||||||
|
throw new LazyInitializationException(
|
||||||
"Could not locate EntityEntry for the collection owner in the PersistenceContext"
|
"Could not locate EntityEntry for the collection owner in the PersistenceContext"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void registerHqlQueryMemento(String name, NamedHqlQueryMemento descriptor) {
|
public synchronized void registerHqlQueryMemento(String name, NamedHqlQueryMemento descriptor) {
|
||||||
hqlMementoMap.put( name, descriptor );
|
hqlMementoMap.put( name, descriptor );
|
||||||
|
sqlMementoMap.remove( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void registerNativeQueryMemento(String name, NamedNativeQueryMemento descriptor) {
|
public synchronized void registerNativeQueryMemento(String name, NamedNativeQueryMemento descriptor) {
|
||||||
sqlMementoMap.put( name, descriptor );
|
sqlMementoMap.put( name, descriptor );
|
||||||
|
hqlMementoMap.remove( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,10 @@ public class ResultSetMappingImpl implements ResultSetMapping {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMappingIdentifier(){
|
||||||
|
return mappingIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAffectedTableNames(Set<String> affectedTableNames, SessionFactoryImplementor sessionFactory) {
|
public void addAffectedTableNames(Set<String> affectedTableNames, SessionFactoryImplementor sessionFactory) {
|
||||||
if ( StringHelper.isEmpty( mappingIdentifier ) ) {
|
if ( StringHelper.isEmpty( mappingIdentifier ) ) {
|
||||||
|
|
|
@ -37,7 +37,6 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.ScrollMode;
|
import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
||||||
|
@ -145,8 +144,10 @@ public class NativeQueryImpl<R>
|
||||||
.getQueryEngine()
|
.getQueryEngine()
|
||||||
.getNamedObjectRepository()
|
.getNamedObjectRepository()
|
||||||
.getResultSetMappingMemento( memento.getResultMappingName() );
|
.getResultSetMappingMemento( memento.getResultMappingName() );
|
||||||
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
|
if ( resultSetMappingMemento != null ) {
|
||||||
return true;
|
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( memento.getResultMappingClass() != null ) {
|
if ( memento.getResultMappingClass() != null ) {
|
||||||
|
@ -376,7 +377,23 @@ public class NativeQueryImpl<R>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamedNativeQueryMemento toMemento(String name) {
|
public NamedNativeQueryMemento toMemento(String name) {
|
||||||
throw new NotYetImplementedFor6Exception( );
|
return new NamedNativeQueryMementoImpl(
|
||||||
|
name,
|
||||||
|
sqlString,
|
||||||
|
resultSetMapping.getMappingIdentifier(),
|
||||||
|
null,
|
||||||
|
querySpaces,
|
||||||
|
isCacheable(),
|
||||||
|
getCacheRegion(),
|
||||||
|
getCacheMode(),
|
||||||
|
getHibernateFlushMode(),
|
||||||
|
isReadOnly(),
|
||||||
|
getTimeout(),
|
||||||
|
getFetchSize(),
|
||||||
|
getComment(),
|
||||||
|
getHints()
|
||||||
|
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -454,7 +454,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
return getAssociatedEntityPersister( factory ).getIdentifierType();
|
return getAssociatedEntityPersister( factory ).getIdentifierType();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) {
|
public EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) {
|
||||||
final EntityPersister persister = associatedEntityPersister;
|
final EntityPersister persister = associatedEntityPersister;
|
||||||
//The following branch implements a simple lazy-initialization, but rather than the canonical
|
//The following branch implements a simple lazy-initialization, but rather than the canonical
|
||||||
//form it returns the local variable to avoid a second volatile read: associatedEntityPersister
|
//form it returns the local variable to avoid a second volatile read: associatedEntityPersister
|
||||||
|
@ -469,7 +469,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final Object getIdentifier(Object value, SharedSessionContractImplementor session) throws HibernateException {
|
protected final Object getIdentifier(Object value, SharedSessionContractImplementor session) throws HibernateException {
|
||||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
if ( isReferenceToIdentifierProperty() ) {
|
||||||
return ForeignKeys.getEntityIdentifierIfNotUnsaved(
|
return ForeignKeys.getEntityIdentifierIfNotUnsaved(
|
||||||
getAssociatedEntityName(),
|
getAssociatedEntityName(),
|
||||||
value,
|
value,
|
||||||
|
@ -605,7 +605,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
* or unique key property name.
|
* or unique key property name.
|
||||||
*/
|
*/
|
||||||
public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
|
public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
|
||||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
if ( isReferenceToIdentifierProperty() ) {
|
||||||
return getIdentifierType( factory );
|
return getIdentifierType( factory );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -629,12 +629,14 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
*/
|
*/
|
||||||
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
|
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
|
||||||
throws MappingException {
|
throws MappingException {
|
||||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
return isReferenceToIdentifierProperty()
|
||||||
return factory.getIdentifierPropertyName( getAssociatedEntityName() );
|
? factory.getIdentifierPropertyName( getAssociatedEntityName() )
|
||||||
}
|
: uniqueKeyPropertyName;
|
||||||
else {
|
}
|
||||||
return uniqueKeyPropertyName;
|
|
||||||
}
|
public boolean isReferenceToIdentifierProperty() {
|
||||||
|
return isReferenceToPrimaryKey()
|
||||||
|
|| uniqueKeyPropertyName == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.query;
|
||||||
|
|
||||||
|
import javax.persistence.FlushModeType;
|
||||||
|
import javax.persistence.LockModeType;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
|
||||||
|
import org.hibernate.CacheMode;
|
||||||
|
import org.hibernate.FlushMode;
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.jpa.QueryHints;
|
||||||
|
import org.hibernate.jpa.test.Distributor;
|
||||||
|
import org.hibernate.jpa.test.Item;
|
||||||
|
import org.hibernate.jpa.test.Wallet;
|
||||||
|
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Jpa;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link javax.persistence.EntityManagerFactory#addNamedQuery} handling.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Jpa(
|
||||||
|
annotatedClasses = {
|
||||||
|
Item.class,
|
||||||
|
Distributor.class,
|
||||||
|
Wallet.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class AddNamedQueryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void basicTest(EntityManagerFactoryScope scope) {
|
||||||
|
// just making sure we can add one and that it is usable when we get it back
|
||||||
|
scope.inEntityManager(
|
||||||
|
entityManager -> {
|
||||||
|
Query query = entityManager.createQuery( "from Item" );
|
||||||
|
final String name = "myBasicItemQuery";
|
||||||
|
entityManager.getEntityManagerFactory().addNamedQuery( name, query );
|
||||||
|
Query query2 = entityManager.createNamedQuery( name );
|
||||||
|
query2.getResultList();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void replaceTest(EntityManagerFactoryScope scope) {
|
||||||
|
|
||||||
|
scope.inEntityManager(
|
||||||
|
em -> {
|
||||||
|
final String name = "myReplaceItemQuery";
|
||||||
|
|
||||||
|
// create a jpql query
|
||||||
|
String sql = "from Item";
|
||||||
|
Query query = em.createQuery( sql );
|
||||||
|
query.setHint( "org.hibernate.comment", sql );
|
||||||
|
em.getEntityManagerFactory().addNamedQuery( name, query );
|
||||||
|
query = em.createNamedQuery( name );
|
||||||
|
assertEquals( sql, query.getHints().get( "org.hibernate.comment" ) );
|
||||||
|
assertEquals( 0, query.getResultList().size() );
|
||||||
|
|
||||||
|
// create a native query and replace the previous jpql
|
||||||
|
sql = "select * from Item";
|
||||||
|
query = em.createNativeQuery( sql, Item.class );
|
||||||
|
query.setHint( "org.hibernate.comment", sql );
|
||||||
|
em.getEntityManagerFactory().addNamedQuery( name, query );
|
||||||
|
query = em.createNamedQuery( name );
|
||||||
|
assertEquals( sql, query.getHints().get( "org.hibernate.comment" ) );
|
||||||
|
assertEquals( 0, query.getResultList().size() );
|
||||||
|
|
||||||
|
// define back a named query
|
||||||
|
sql = "from Item";
|
||||||
|
query = em.createQuery( sql );
|
||||||
|
query.setHint( "org.hibernate.comment", sql );
|
||||||
|
em.getEntityManagerFactory().addNamedQuery( name, query );
|
||||||
|
query = em.createNamedQuery( name );
|
||||||
|
assertEquals( sql, query.getHints().get( "org.hibernate.comment" ) );
|
||||||
|
assertEquals( 0, query.getResultList().size() );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLockModeHandling(EntityManagerFactoryScope scope) {
|
||||||
|
final String name = "lock-mode-handling";
|
||||||
|
scope.inTransaction(
|
||||||
|
em -> {
|
||||||
|
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 = scope.getEntityManagerFactory()
|
||||||
|
.unwrap( SessionFactoryImplementor.class );
|
||||||
|
NamedHqlQueryMemento def = sfi.getQueryEngine()
|
||||||
|
.getNamedObjectRepository()
|
||||||
|
.getHqlQueryMemento( 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.Query.class ).getLockOptions().getLockMode()
|
||||||
|
);
|
||||||
|
assertEquals( LockModeType.OPTIMISTIC, q.getLockMode() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlushModeHandling(EntityManagerFactoryScope scope) {
|
||||||
|
final String name = "flush-mode-handling";
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
em -> {
|
||||||
|
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 = scope.getEntityManagerFactory()
|
||||||
|
.unwrap( SessionFactoryImplementor.class );
|
||||||
|
NamedHqlQueryMemento def = sfi.getQueryEngine()
|
||||||
|
.getNamedObjectRepository()
|
||||||
|
.getHqlQueryMemento( 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.Query.class ).getHibernateFlushMode()
|
||||||
|
);
|
||||||
|
assertEquals( FlushModeType.COMMIT, q.getFlushMode() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfigValueHandling(EntityManagerFactoryScope scope) {
|
||||||
|
final String name = "itemJpaQueryWithLockModeAndHints";
|
||||||
|
scope.inTransaction(
|
||||||
|
em -> {
|
||||||
|
Query query = em.createNamedQuery( name );
|
||||||
|
org.hibernate.query.Query hibernateQuery = (org.hibernate.query.Query) query;
|
||||||
|
// assert the state of the query config settings based on the initial named query
|
||||||
|
//
|
||||||
|
// NOTE: here we check "query options" via the Hibernate contract (allowing nullness checking); see below for access via the JPA contract
|
||||||
|
assertNull( hibernateQuery.getQueryOptions().getFirstRow() );
|
||||||
|
assertNull( hibernateQuery.getQueryOptions().getMaxRows() );
|
||||||
|
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
||||||
|
assertEquals( FlushModeType.COMMIT, hibernateQuery.getFlushMode() );
|
||||||
|
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
||||||
|
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
||||||
|
// jpa timeout is in milliseconds, whereas Hibernate's is in seconds
|
||||||
|
assertEquals( (Integer) 3, hibernateQuery.getTimeout() );
|
||||||
|
|
||||||
|
query.setHint( QueryHints.HINT_TIMEOUT, 10 );
|
||||||
|
em.getEntityManagerFactory().addNamedQuery( name, query );
|
||||||
|
|
||||||
|
query = em.createNamedQuery( name );
|
||||||
|
hibernateQuery = (org.hibernate.query.Query) query;
|
||||||
|
// assert the state of the query config settings based on the initial named query
|
||||||
|
//
|
||||||
|
// NOTE: here we check "query options" via the JPA contract
|
||||||
|
assertEquals( 0, hibernateQuery.getFirstResult() );
|
||||||
|
assertEquals( Integer.MAX_VALUE, hibernateQuery.getMaxResults() );
|
||||||
|
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
||||||
|
assertEquals( FlushModeType.COMMIT, 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 = (org.hibernate.query.Query) query;
|
||||||
|
// assert the state of the query config settings based on the initial named query
|
||||||
|
assertEquals( 0, hibernateQuery.getFirstResult() );
|
||||||
|
assertEquals( Integer.MAX_VALUE, hibernateQuery.getMaxResults() );
|
||||||
|
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
||||||
|
assertEquals( FlushModeType.COMMIT, 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 = (org.hibernate.query.Query) query;
|
||||||
|
// assert the state of the query config settings based on the initial named query
|
||||||
|
assertEquals( 51, hibernateQuery.getFirstResult() );
|
||||||
|
assertEquals( Integer.MAX_VALUE, hibernateQuery.getMaxResults() );
|
||||||
|
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
||||||
|
assertEquals( FlushModeType.COMMIT, hibernateQuery.getFlushMode() );
|
||||||
|
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
||||||
|
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
||||||
|
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.bytecode.enhancement.lazy.proxy;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.LazyInitializationException;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@TestForIssue(jiraKey = "HHH-14811")
|
||||||
|
@RunWith(BytecodeEnhancerRunner.class)
|
||||||
|
@EnhancementOptions(lazyLoading = true)
|
||||||
|
public class BytecodeEnhancedLazyLoadingOnDeletedEntityTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] { AssociationOwner.class, AssociationNonOwner.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
s.createQuery( "delete from AOwner" ).executeUpdate();
|
||||||
|
s.createQuery( "delete from ANonOwner" ).executeUpdate();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void accessUnloadedLazyAssociationOnDeletedOwner() {
|
||||||
|
inTransaction( s -> {
|
||||||
|
AssociationOwner owner = new AssociationOwner();
|
||||||
|
owner.setId( 1 );
|
||||||
|
for ( int i = 0; i < 2; i++ ) {
|
||||||
|
AssociationNonOwner nonOwner = new AssociationNonOwner();
|
||||||
|
nonOwner.setId( i );
|
||||||
|
s.persist( nonOwner );
|
||||||
|
nonOwner.getOwners().add( owner );
|
||||||
|
owner.getNonOwners().add( nonOwner );
|
||||||
|
}
|
||||||
|
s.persist( owner );
|
||||||
|
} );
|
||||||
|
assertThatThrownBy( () -> inTransaction( session -> {
|
||||||
|
AssociationOwner owner = session.load( AssociationOwner.class, 1 );
|
||||||
|
session.delete( owner );
|
||||||
|
session.flush();
|
||||||
|
owner.getNonOwners().size();
|
||||||
|
} ) )
|
||||||
|
.isInstanceOf( LazyInitializationException.class )
|
||||||
|
.hasMessageContaining(
|
||||||
|
"Could not locate EntityEntry for the collection owner in the PersistenceContext" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void accessUnloadedLazyAssociationOnDeletedNonOwner() {
|
||||||
|
inTransaction( s -> {
|
||||||
|
AssociationNonOwner nonOwner = new AssociationNonOwner();
|
||||||
|
nonOwner.setId( 1 );
|
||||||
|
s.persist( nonOwner );
|
||||||
|
} );
|
||||||
|
assertThatThrownBy( () -> inTransaction( session -> {
|
||||||
|
AssociationNonOwner nonOwner = session.load( AssociationNonOwner.class, 1 );
|
||||||
|
session.delete( nonOwner );
|
||||||
|
session.flush();
|
||||||
|
nonOwner.getOwners().size();
|
||||||
|
} ) )
|
||||||
|
.isInstanceOf( LazyInitializationException.class )
|
||||||
|
.hasMessageContaining(
|
||||||
|
"Could not locate EntityEntry for the collection owner in the PersistenceContext" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "AOwner")
|
||||||
|
@Table
|
||||||
|
private static class AssociationOwner {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
Integer id;
|
||||||
|
|
||||||
|
@ManyToMany(fetch = FetchType.LAZY)
|
||||||
|
List<AssociationNonOwner> nonOwners = new ArrayList<>();
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AssociationNonOwner> getNonOwners() {
|
||||||
|
return nonOwners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonOwners(
|
||||||
|
List<AssociationNonOwner> nonOwners) {
|
||||||
|
this.nonOwners = nonOwners;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "ANonOwner")
|
||||||
|
@Table
|
||||||
|
private static class AssociationNonOwner {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
Integer id;
|
||||||
|
|
||||||
|
@ManyToMany(mappedBy = "nonOwners", fetch = FetchType.LAZY)
|
||||||
|
List<AssociationOwner> owners = new ArrayList<>();
|
||||||
|
|
||||||
|
AssociationNonOwner() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AssociationOwner> getOwners() {
|
||||||
|
return owners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwners(List<AssociationOwner> owners) {
|
||||||
|
this.owners = owners;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,178 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.jpa.test.query;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
import javax.persistence.FlushModeType;
|
|
||||||
import javax.persistence.LockModeType;
|
|
||||||
import javax.persistence.Query;
|
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
|
||||||
import org.hibernate.FlushMode;
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.jpa.QueryHints;
|
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
|
||||||
import org.hibernate.jpa.test.Distributor;
|
|
||||||
import org.hibernate.jpa.test.Item;
|
|
||||||
import org.hibernate.jpa.test.Wallet;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 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 );
|
|
||||||
NamedHqlQueryMementoImpl 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.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 );
|
|
||||||
NamedHqlQueryMementoImpl 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.Query.class ).getHibernateFlushMode() );
|
|
||||||
assertEquals( FlushModeType.COMMIT, q.getFlushMode() );
|
|
||||||
|
|
||||||
em.getTransaction().commit();
|
|
||||||
em.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConfigValueHandling() {
|
|
||||||
final String name = "itemJpaQueryWithLockModeAndHints";
|
|
||||||
EntityManager em = getOrCreateEntityManager();
|
|
||||||
em.getTransaction().begin();
|
|
||||||
|
|
||||||
Query query = em.createNamedQuery( name );
|
|
||||||
org.hibernate.query.Query hibernateQuery = (org.hibernate.query.Query) query;
|
|
||||||
// assert the state of the query config settings based on the initial named query
|
|
||||||
//
|
|
||||||
// NOTE: here we check "query options" via the Hibernate contract (allowing nullness checking); see below for access via the JPA contract
|
|
||||||
assertNull( hibernateQuery.getQueryOptions().getFirstRow() );
|
|
||||||
assertNull( hibernateQuery.getQueryOptions().getMaxRows() );
|
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
|
||||||
assertEquals( FlushModeType.COMMIT, hibernateQuery.getFlushMode() );
|
|
||||||
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
|
||||||
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
|
||||||
// jpa timeout is in milliseconds, whereas Hibernate's is in seconds
|
|
||||||
assertEquals( (Integer) 3, hibernateQuery.getTimeout() );
|
|
||||||
|
|
||||||
query.setHint( QueryHints.HINT_TIMEOUT, 10 );
|
|
||||||
em.getEntityManagerFactory().addNamedQuery( name, query );
|
|
||||||
|
|
||||||
query = em.createNamedQuery( name );
|
|
||||||
hibernateQuery = (org.hibernate.query.Query) query;
|
|
||||||
// assert the state of the query config settings based on the initial named query
|
|
||||||
//
|
|
||||||
// NOTE: here we check "query options" via the JPA contract
|
|
||||||
assertEquals( 0, hibernateQuery.getFirstResult() );
|
|
||||||
assertEquals( Integer.MAX_VALUE, hibernateQuery.getMaxResults() );
|
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
|
||||||
assertEquals( FlushModeType.COMMIT, 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 = (org.hibernate.query.Query) query;
|
|
||||||
// assert the state of the query config settings based on the initial named query
|
|
||||||
assertEquals( 0, hibernateQuery.getFirstResult() );
|
|
||||||
assertEquals( Integer.MAX_VALUE, hibernateQuery.getMaxResults() );
|
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
|
||||||
assertEquals( FlushModeType.COMMIT, 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 = (org.hibernate.query.Query) query;
|
|
||||||
// assert the state of the query config settings based on the initial named query
|
|
||||||
assertEquals( 51, hibernateQuery.getFirstResult() );
|
|
||||||
assertEquals( Integer.MAX_VALUE, hibernateQuery.getMaxResults() );
|
|
||||||
assertEquals( FlushMode.MANUAL, hibernateQuery.getHibernateFlushMode() );
|
|
||||||
assertEquals( FlushModeType.COMMIT, hibernateQuery.getFlushMode() );
|
|
||||||
assertEquals( CacheMode.IGNORE, hibernateQuery.getCacheMode() );
|
|
||||||
assertEquals( LockMode.PESSIMISTIC_WRITE, hibernateQuery.getLockOptions().getLockMode() );
|
|
||||||
assertEquals( (Integer) 10, hibernateQuery.getTimeout() );
|
|
||||||
|
|
||||||
em.getTransaction().commit();
|
|
||||||
em.close();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue