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',
|
||||
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',
|
||||
db2: 'com.ibm.db2:jcc:11.5.4.0',
|
||||
hana: 'com.sap.cloud.db.jdbc:ngdbc:2.4.59',
|
||||
|
|
|
@ -684,7 +684,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
try {
|
||||
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 );
|
||||
return query;
|
||||
}
|
||||
|
@ -796,7 +798,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
if ( namedHqlDescriptor != null ) {
|
||||
HqlQueryImplementor<T> query = namedHqlDescriptor.toQuery( this, resultType );
|
||||
query.setComment( "dynamic HQL query" );
|
||||
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||
query.setComment( "dynamic HQL query" );
|
||||
}
|
||||
applyQuerySettingsAndHints( query );
|
||||
if ( namedHqlDescriptor.getLockOptions() != null ) {
|
||||
query.setLockOptions( namedHqlDescriptor.getLockOptions() );
|
||||
|
@ -817,7 +821,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
else {
|
||||
query = namedNativeDescriptor.toQuery( this, resultType );
|
||||
}
|
||||
query.setComment( "dynamic native SQL query" );
|
||||
if ( StringHelper.isEmpty( query.getComment() ) ) {
|
||||
query.setComment( "dynamic native SQL query" );
|
||||
}
|
||||
applyQuerySettingsAndHints( query );
|
||||
return query;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
|
|||
import org.hibernate.proxy.HibernateProxyHelper;
|
||||
import org.hibernate.query.QueryLogging;
|
||||
import org.hibernate.query.hql.spi.HqlQueryImplementor;
|
||||
import org.hibernate.query.named.NamedObjectRepository;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
||||
|
@ -899,10 +900,11 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
// query implementations
|
||||
|
||||
// first, handle StoredProcedureQuery
|
||||
final NamedObjectRepository namedObjectRepository = getQueryEngine().getNamedObjectRepository();
|
||||
try {
|
||||
final ProcedureCallImplementor unwrapped = query.unwrap( ProcedureCallImplementor.class );
|
||||
if ( unwrapped != null ) {
|
||||
getQueryEngine().getNamedObjectRepository().registerCallableQueryMemento(
|
||||
namedObjectRepository.registerCallableQueryMemento(
|
||||
name,
|
||||
unwrapped.toMemento( name )
|
||||
);
|
||||
|
@ -919,13 +921,14 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
if ( hibernateQuery != null ) {
|
||||
// create and register the proper NamedQueryDefinition...
|
||||
if ( hibernateQuery instanceof NativeQueryImplementor ) {
|
||||
getQueryEngine().getNamedObjectRepository().registerNativeQueryMemento(
|
||||
namedObjectRepository.registerNativeQueryMemento(
|
||||
name,
|
||||
( (NativeQueryImplementor) hibernateQuery ).toMemento( name )
|
||||
);
|
||||
|
||||
}
|
||||
else {
|
||||
getQueryEngine().getNamedObjectRepository().registerHqlQueryMemento(
|
||||
namedObjectRepository.registerHqlQueryMemento(
|
||||
name,
|
||||
( ( HqlQueryImplementor ) hibernateQuery ).toMemento( name )
|
||||
);
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.FetchMode;
|
|||
import org.hibernate.Filter;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -1609,8 +1610,9 @@ public abstract class AbstractEntityPersister
|
|||
// for the collection to the just loaded collection
|
||||
final EntityEntry ownerEntry = persistenceContext.getEntry( entity );
|
||||
if ( ownerEntry == null ) {
|
||||
// not good
|
||||
throw new AssertionFailure(
|
||||
// the entity is not in the session; it was probably deleted,
|
||||
// so we cannot load the collection anymore.
|
||||
throw new LazyInitializationException(
|
||||
"Could not locate EntityEntry for the collection owner in the PersistenceContext"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
|
|||
@Override
|
||||
public synchronized void registerHqlQueryMemento(String name, NamedHqlQueryMemento descriptor) {
|
||||
hqlMementoMap.put( name, descriptor );
|
||||
sqlMementoMap.remove( name );
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,6 +88,7 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
|
|||
@Override
|
||||
public synchronized void registerNativeQueryMemento(String name, NamedNativeQueryMemento descriptor) {
|
||||
sqlMementoMap.put( name, descriptor );
|
||||
hqlMementoMap.remove( name );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -123,6 +123,10 @@ public class ResultSetMappingImpl implements ResultSetMapping {
|
|||
}
|
||||
}
|
||||
|
||||
public String getMappingIdentifier(){
|
||||
return mappingIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAffectedTableNames(Set<String> affectedTableNames, SessionFactoryImplementor sessionFactory) {
|
||||
if ( StringHelper.isEmpty( mappingIdentifier ) ) {
|
||||
|
|
|
@ -37,7 +37,6 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
||||
|
@ -145,8 +144,10 @@ public class NativeQueryImpl<R>
|
|||
.getQueryEngine()
|
||||
.getNamedObjectRepository()
|
||||
.getResultSetMappingMemento( memento.getResultMappingName() );
|
||||
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
|
||||
return true;
|
||||
if ( resultSetMappingMemento != null ) {
|
||||
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( memento.getResultMappingClass() != null ) {
|
||||
|
@ -376,7 +377,23 @@ public class NativeQueryImpl<R>
|
|||
|
||||
@Override
|
||||
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
|
||||
|
|
|
@ -454,7 +454,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
return getAssociatedEntityPersister( factory ).getIdentifierType();
|
||||
}
|
||||
|
||||
protected EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) {
|
||||
public EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) {
|
||||
final EntityPersister persister = associatedEntityPersister;
|
||||
//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
|
||||
|
@ -469,7 +469,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
}
|
||||
|
||||
protected final Object getIdentifier(Object value, SharedSessionContractImplementor session) throws HibernateException {
|
||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
||||
if ( isReferenceToIdentifierProperty() ) {
|
||||
return ForeignKeys.getEntityIdentifierIfNotUnsaved(
|
||||
getAssociatedEntityName(),
|
||||
value,
|
||||
|
@ -605,7 +605,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
* or unique key property name.
|
||||
*/
|
||||
public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
|
||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
||||
if ( isReferenceToIdentifierProperty() ) {
|
||||
return getIdentifierType( factory );
|
||||
}
|
||||
else {
|
||||
|
@ -629,12 +629,14 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
*/
|
||||
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
|
||||
throws MappingException {
|
||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
||||
return factory.getIdentifierPropertyName( getAssociatedEntityName() );
|
||||
}
|
||||
else {
|
||||
return uniqueKeyPropertyName;
|
||||
}
|
||||
return isReferenceToIdentifierProperty()
|
||||
? factory.getIdentifierPropertyName( getAssociatedEntityName() )
|
||||
: 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