Merge remote-tracking branch 'upstream5/master' into wip/6.0_merged_8
This commit is contained in:
commit
39afae5462
|
@ -62,10 +62,10 @@ public class MetadataSources implements Serializable {
|
|||
|
||||
private XmlMappingBinderAccess xmlMappingBinderAccess;
|
||||
|
||||
private List<Binding> xmlBindings = new ArrayList<>();
|
||||
private LinkedHashSet<Class<?>> annotatedClasses = new LinkedHashSet<>();
|
||||
private LinkedHashSet<String> annotatedClassNames = new LinkedHashSet<>();
|
||||
private LinkedHashSet<String> annotatedPackages = new LinkedHashSet<>();
|
||||
private List<Binding> xmlBindings;
|
||||
private LinkedHashSet<Class<?>> annotatedClasses;
|
||||
private LinkedHashSet<String> annotatedClassNames;
|
||||
private LinkedHashSet<String> annotatedPackages;
|
||||
|
||||
private Map<String,Class<?>> extraQueryImports;
|
||||
|
||||
|
@ -81,14 +81,15 @@ public class MetadataSources implements Serializable {
|
|||
public MetadataSources(ServiceRegistry serviceRegistry) {
|
||||
// service registry really should be either BootstrapServiceRegistry or StandardServiceRegistry type...
|
||||
if ( ! isExpectedServiceRegistryType( serviceRegistry ) ) {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf(
|
||||
"Unexpected ServiceRegistry type [%s] encountered during building of MetadataSources; may cause " +
|
||||
"problems later attempting to construct MetadataBuilder",
|
||||
serviceRegistry.getClass().getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
this.xmlMappingBinderAccess = new XmlMappingBinderAccess( serviceRegistry );
|
||||
}
|
||||
|
||||
protected static boolean isExpectedServiceRegistryType(ServiceRegistry serviceRegistry) {
|
||||
|
@ -97,23 +98,26 @@ public class MetadataSources implements Serializable {
|
|||
}
|
||||
|
||||
public XmlMappingBinderAccess getXmlMappingBinderAccess() {
|
||||
if ( xmlMappingBinderAccess == null ) {
|
||||
xmlMappingBinderAccess = new XmlMappingBinderAccess( serviceRegistry );
|
||||
}
|
||||
return xmlMappingBinderAccess;
|
||||
}
|
||||
|
||||
public List<Binding> getXmlBindings() {
|
||||
return xmlBindings;
|
||||
return xmlBindings == null ? Collections.emptyList() : xmlBindings;
|
||||
}
|
||||
|
||||
public Collection<String> getAnnotatedPackages() {
|
||||
return annotatedPackages;
|
||||
return annotatedPackages == null ? Collections.emptySet() : annotatedPackages;
|
||||
}
|
||||
|
||||
public Collection<Class<?>> getAnnotatedClasses() {
|
||||
return annotatedClasses;
|
||||
return annotatedClasses == null ? Collections.emptySet() : annotatedClasses;
|
||||
}
|
||||
|
||||
public Collection<String> getAnnotatedClassNames() {
|
||||
return annotatedClassNames;
|
||||
return annotatedClassNames == null ? Collections.emptySet() : annotatedClassNames;
|
||||
}
|
||||
|
||||
public Map<String,Class<?>> getExtraQueryImports() {
|
||||
|
@ -201,6 +205,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining)
|
||||
*/
|
||||
public MetadataSources addAnnotatedClass(Class annotatedClass) {
|
||||
if ( annotatedClasses == null ) {
|
||||
annotatedClasses = new LinkedHashSet<>();
|
||||
}
|
||||
annotatedClasses.add( annotatedClass );
|
||||
return this;
|
||||
}
|
||||
|
@ -225,6 +232,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining)
|
||||
*/
|
||||
public MetadataSources addAnnotatedClassName(String annotatedClassName) {
|
||||
if ( annotatedClassNames == null ) {
|
||||
annotatedClassNames = new LinkedHashSet<>();
|
||||
}
|
||||
annotatedClassNames.add( annotatedClassName );
|
||||
return this;
|
||||
}
|
||||
|
@ -265,11 +275,17 @@ public class MetadataSources implements Serializable {
|
|||
packageName = packageName.substring( 0, packageName.length() - 1 );
|
||||
}
|
||||
|
||||
annotatedPackages.add( packageName );
|
||||
|
||||
addPackageInternal( packageName );
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addPackageInternal(String packageName) {
|
||||
if ( annotatedPackages == null ) {
|
||||
annotatedPackages = new LinkedHashSet<>();
|
||||
}
|
||||
annotatedPackages.add( packageName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read package-level metadata.
|
||||
*
|
||||
|
@ -278,7 +294,7 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining)
|
||||
*/
|
||||
public MetadataSources addPackage(Package packageRef) {
|
||||
annotatedPackages.add( packageRef.getName() );
|
||||
addPackageInternal( packageRef.getName() );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -297,7 +313,9 @@ public class MetadataSources implements Serializable {
|
|||
if ( entityClass == null ) {
|
||||
throw new IllegalArgumentException( "The specified class cannot be null" );
|
||||
}
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "adding resource mappings from class convention : %s", entityClass.getName() );
|
||||
}
|
||||
final String mappingResourceName = entityClass.getName().replace( '.', '/' ) + ".hbm.xml";
|
||||
addResource( mappingResourceName );
|
||||
return this;
|
||||
|
@ -311,7 +329,7 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addResource(String name) {
|
||||
xmlBindings.add( getXmlMappingBinderAccess().bind( name ) );
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( name ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -337,7 +355,7 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addFile(File file) {
|
||||
xmlBindings.add( getXmlMappingBinderAccess().bind( file ) );
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( file ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -357,7 +375,7 @@ public class MetadataSources implements Serializable {
|
|||
}
|
||||
|
||||
private void addCacheableFile(Origin origin, File file) {
|
||||
xmlBindings.add( new CacheableFileXmlSource( origin, file, false ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
getXmlBindingsForWrite().add( new CacheableFileXmlSource( origin, file, false ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -394,7 +412,7 @@ public class MetadataSources implements Serializable {
|
|||
*/
|
||||
public MetadataSources addCacheableFileStrictly(File file) throws SerializationException, FileNotFoundException {
|
||||
final Origin origin = new Origin( SourceType.FILE, file.getAbsolutePath() );
|
||||
xmlBindings.add( new CacheableFileXmlSource( origin, file, true ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
getXmlBindingsForWrite().add( new CacheableFileXmlSource( origin, file, true ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -406,7 +424,7 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addInputStream(InputStreamAccess xmlInputStreamAccess) {
|
||||
xmlBindings.add( getXmlMappingBinderAccess().bind( xmlInputStreamAccess ) );
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( xmlInputStreamAccess ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -418,7 +436,7 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addInputStream(InputStream xmlInputStream) {
|
||||
xmlBindings.add( getXmlMappingBinderAccess().bind( xmlInputStream ) );
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( xmlInputStream ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -430,7 +448,7 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addURL(URL url) {
|
||||
xmlBindings.add( getXmlMappingBinderAccess().bind( url ) );
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( url ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -446,7 +464,7 @@ public class MetadataSources implements Serializable {
|
|||
@Deprecated
|
||||
public MetadataSources addDocument(Document document) {
|
||||
final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH );
|
||||
xmlBindings.add( new JaxpSourceXmlSource( origin, new DOMSource( document ) ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
getXmlBindingsForWrite().add( new JaxpSourceXmlSource( origin, new DOMSource( document ) ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -460,17 +478,22 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addJar(File jar) {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Seeking mapping documents in jar file : %s", jar.getName() );
|
||||
}
|
||||
final Origin origin = new Origin( SourceType.JAR, jar.getAbsolutePath() );
|
||||
try {
|
||||
JarFile jarFile = new JarFile( jar );
|
||||
final boolean TRACE = LOG.isTraceEnabled();
|
||||
try {
|
||||
Enumeration jarEntries = jarFile.entries();
|
||||
while ( jarEntries.hasMoreElements() ) {
|
||||
final ZipEntry zipEntry = (ZipEntry) jarEntries.nextElement();
|
||||
if ( zipEntry.getName().endsWith( ".hbm.xml" ) ) {
|
||||
if ( TRACE ) {
|
||||
LOG.tracef( "found mapping document : %s", zipEntry.getName() );
|
||||
xmlBindings.add(
|
||||
}
|
||||
getXmlBindingsForWrite().add(
|
||||
new JarFileEntryXmlSource( origin, jarFile, zipEntry ).doBind( getXmlMappingBinderAccess().getMappingBinder() )
|
||||
);
|
||||
}
|
||||
|
@ -490,6 +513,13 @@ public class MetadataSources implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
private <Binding> List getXmlBindingsForWrite() {
|
||||
if ( xmlBindings == null ) {
|
||||
xmlBindings = new ArrayList<>();
|
||||
}
|
||||
return xmlBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all mapping documents from a directory tree.
|
||||
* <p/>
|
||||
|
|
|
@ -437,7 +437,7 @@ public class MapBinder extends CollectionBinder {
|
|||
referencedEntityColumns = referencedProperty.getColumnIterator();
|
||||
}
|
||||
fromAndWhere = getFromAndWhereFormula(
|
||||
associatedClass.getTable().getName(),
|
||||
associatedClass.getTable().getQualifiedTableName().toString(),
|
||||
element.getColumnIterator(),
|
||||
referencedEntityColumns
|
||||
);
|
||||
|
|
|
@ -332,6 +332,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
|| "getTransaction".equals( methodName )
|
||||
|| "isTransactionInProgress".equals( methodName )
|
||||
|| "setFlushMode".equals( methodName )
|
||||
|| "setHibernateFlushMode".equals( methodName )
|
||||
|| "getFactory".equals( methodName )
|
||||
|| "getSessionFactory".equals( methodName )
|
||||
|| "getTenantIdentifier".equals( methodName ) ) {
|
||||
|
|
|
@ -260,15 +260,6 @@ public interface SharedSessionContractImplementor
|
|||
Object internalLoad(String entityName, Serializable id, boolean eager, boolean nullable)
|
||||
throws HibernateException;
|
||||
|
||||
default Object internalLoad(
|
||||
String entityName,
|
||||
Serializable id,
|
||||
boolean eager,
|
||||
boolean nullable,
|
||||
Boolean unwrapProxy) throws HibernateException {
|
||||
return internalLoad( entityName, id, eager, nullable );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an instance immediately. This method is only called when lazily initializing a proxy.
|
||||
* Do not return the proxy.
|
||||
|
|
|
@ -299,7 +299,7 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
|||
return createProxy( event, persister, keyToLoad, persistenceContext );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !entityMetamodel.hasSubclasses() ) {
|
||||
if ( keyToLoad.isBatchLoadable() ) {
|
||||
// Add a batch-fetch entry into the queue for this entity
|
||||
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( keyToLoad );
|
||||
|
@ -309,6 +309,9 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
|||
// create the (uninitialized) entity instance - has only id set
|
||||
return persister.getBytecodeEnhancementMetadata().createEnhancedProxy( keyToLoad, true, session );
|
||||
}
|
||||
// If we get here, then the entity class has subclasses and there is no HibernateProxy factory.
|
||||
// The entity will get loaded below.
|
||||
}
|
||||
else {
|
||||
if ( persister.hasProxy() ) {
|
||||
// look for a proxy
|
||||
|
|
|
@ -975,18 +975,7 @@ public final class SessionImpl
|
|||
String entityName,
|
||||
Serializable id,
|
||||
boolean eager,
|
||||
boolean nullable) throws HibernateException {
|
||||
return internalLoad( entityName, id, eager, nullable, null );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object internalLoad(
|
||||
String entityName,
|
||||
Serializable id,
|
||||
boolean eager,
|
||||
boolean nullable,
|
||||
Boolean unwrapProxy) {
|
||||
boolean nullable) {
|
||||
final EffectiveEntityGraph effectiveEntityGraph = getLoadQueryInfluencers().getEffectiveEntityGraph();
|
||||
final GraphSemantic semantic = effectiveEntityGraph.getSemantic();
|
||||
final RootGraphImplementor<?> graph = effectiveEntityGraph.getGraph();
|
||||
|
|
|
@ -298,13 +298,39 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
|||
final BytecodeEnhancementMetadata bytecodeEnhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata();
|
||||
if ( allowBytecodeProxy && bytecodeEnhancementMetadata.isEnhancedForLazyLoading() ) {
|
||||
|
||||
// we cannot use bytecode proxy for entities with subclasses
|
||||
if ( !entityMetamodel.hasSubclasses() ) {
|
||||
return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this );
|
||||
// if the entity defines a HibernateProxy factory, see if there is an
|
||||
// existing proxy associated with the PC - and if so, use it
|
||||
if ( persister.getEntityMetamodel().getTuplizer().getProxyFactory() != null ) {
|
||||
final PersistenceContext persistenceContext = getPersistenceContext();
|
||||
final Object proxy = persistenceContext.getProxy( entityKey );
|
||||
|
||||
if ( proxy != null ) {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.trace( "Entity proxy found in session cache" );
|
||||
}
|
||||
if ( LOG.isDebugEnabled() && ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isUnwrap() ) {
|
||||
LOG.debug( "Ignoring NO_PROXY to honor laziness" );
|
||||
}
|
||||
|
||||
// we could not use bytecode proxy, check to see if we can use HibernateProxy
|
||||
return persistenceContext.narrowProxy( proxy, persister, entityKey, null );
|
||||
}
|
||||
|
||||
// specialized handling for entities with subclasses with a HibernateProxy factory
|
||||
if ( entityMetamodel.hasSubclasses() ) {
|
||||
// entities with subclasses that define a ProxyFactory can create
|
||||
// a HibernateProxy.
|
||||
LOG.debugf( "Creating a HibernateProxy for to-one association with subclasses to honor laziness" );
|
||||
return createProxy( entityKey );
|
||||
}
|
||||
return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this );
|
||||
}
|
||||
else if ( !entityMetamodel.hasSubclasses() ) {
|
||||
return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this );
|
||||
}
|
||||
// If we get here, then the entity class has subclasses and there is no HibernateProxy factory.
|
||||
// The entity will get loaded below.
|
||||
}
|
||||
else {
|
||||
if ( persister.hasProxy() ) {
|
||||
final PersistenceContext persistenceContext = getPersistenceContext();
|
||||
final Object existingProxy = persistenceContext.getProxy( entityKey );
|
||||
|
@ -312,9 +338,8 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
|||
return persistenceContext.narrowProxy( existingProxy, persister, entityKey, null );
|
||||
}
|
||||
else {
|
||||
final Object proxy = persister.createProxy( id, this );
|
||||
persistenceContext.addProxy( entityKey, proxy );
|
||||
return proxy;
|
||||
return createProxy( entityKey );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -323,6 +348,12 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
|||
return get( entityName, id );
|
||||
}
|
||||
|
||||
private Object createProxy(EntityKey entityKey) {
|
||||
final Object proxy = entityKey.getPersister().createProxy( entityKey.getIdentifier(), this );
|
||||
getPersistenceContext().addProxy( entityKey, proxy );
|
||||
return proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoCloseSessionEnabled() {
|
||||
return getFactory().getSessionFactoryOptions().isAutoCloseSessionEnabled();
|
||||
|
|
|
@ -1733,6 +1733,7 @@ public abstract class Loader {
|
|||
// see if the entity defines reference caching, and if so use the cached reference (if one).
|
||||
if ( session.getCacheMode().isGetEnabled() && persister.canUseReferenceCacheEntries() ) {
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
if ( cache != null ) {
|
||||
final Object ck = cache.generateCacheKey(
|
||||
key.getIdentifier(),
|
||||
persister,
|
||||
|
@ -1741,10 +1742,14 @@ public abstract class Loader {
|
|||
);
|
||||
final Object cachedEntry = CacheHelper.fromSharedCache( session, ck, cache );
|
||||
if ( cachedEntry != null ) {
|
||||
CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( cachedEntry, factory );
|
||||
CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure(
|
||||
cachedEntry,
|
||||
factory
|
||||
);
|
||||
return ( (ReferenceCacheEntryImpl) entry ).getReference();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Object object;
|
||||
if ( optionalObjectKey != null && key.equals( optionalObjectKey ) ) {
|
||||
|
|
|
@ -655,8 +655,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
getAssociatedEntityName(),
|
||||
id,
|
||||
eager,
|
||||
isNullable(),
|
||||
unwrapProxy
|
||||
isNullable()
|
||||
);
|
||||
|
||||
if ( proxyOrEntity instanceof HibernateProxy ) {
|
||||
|
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.annotations.LazyToOne;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
public class QueryScrollingWithInheritanceTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( EmployeeParent.class );
|
||||
sources.addAnnotatedClass( Employee.class );
|
||||
sources.addAnnotatedClass( OtherEntity.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrollableWithStatelessSession() {
|
||||
final StatisticsImplementor stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
ScrollableResults scrollableResults = null;
|
||||
final StatelessSession statelessSession = sessionFactory().openStatelessSession();
|
||||
|
||||
try {
|
||||
statelessSession.beginTransaction();
|
||||
Query<Employee> query = statelessSession.createQuery(
|
||||
"select distinct e from Employee e left join fetch e.otherEntities order by e.dept",
|
||||
Employee.class
|
||||
);
|
||||
if ( getDialect() instanceof DB2Dialect ) {
|
||||
/*
|
||||
FetchingScrollableResultsImp#next() in order to check if the ResultSet is empty calls ResultSet#isBeforeFirst()
|
||||
but the support for ResultSet#isBeforeFirst() is optional for ResultSets with a result
|
||||
set type of TYPE_FORWARD_ONLY and db2 does not support it.
|
||||
*/
|
||||
scrollableResults = query.scroll( ScrollMode.SCROLL_INSENSITIVE );
|
||||
}
|
||||
else {
|
||||
scrollableResults = query.scroll( ScrollMode.FORWARD_ONLY );
|
||||
}
|
||||
|
||||
while ( scrollableResults.next() ) {
|
||||
final Employee employee = (Employee) scrollableResults.get( 0 );
|
||||
assertThat( Hibernate.isPropertyInitialized( employee, "otherEntities" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( employee.getOtherEntities() ), is( true ) );
|
||||
if ( "ENG1".equals( employee.getDept() ) ) {
|
||||
assertThat( employee.getOtherEntities().size(), is( 2 ) );
|
||||
for ( OtherEntity otherEntity : employee.getOtherEntities() ) {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( false ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( false ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertThat( employee.getOtherEntities().size(), is( 0 ) );
|
||||
}
|
||||
}
|
||||
statelessSession.getTransaction().commit();
|
||||
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||
}
|
||||
finally {
|
||||
if ( scrollableResults != null ) {
|
||||
scrollableResults.close();
|
||||
}
|
||||
if ( statelessSession.getTransaction().isActive() ) {
|
||||
statelessSession.getTransaction().rollback();
|
||||
}
|
||||
statelessSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrollableWithSession() {
|
||||
final StatisticsImplementor stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
ScrollableResults scrollableResults = null;
|
||||
final Session session = sessionFactory().openSession();
|
||||
|
||||
try {
|
||||
session.beginTransaction();
|
||||
Query<Employee> query = session.createQuery(
|
||||
"select distinct e from Employee e left join fetch e.otherEntities order by e.dept",
|
||||
Employee.class
|
||||
);
|
||||
if ( getDialect() instanceof DB2Dialect ) {
|
||||
/*
|
||||
FetchingScrollableResultsImp#next() in order to check if the ResultSet is empty calls ResultSet#isBeforeFirst()
|
||||
but the support for ResultSet#isBeforeFirst() is optional for ResultSets with a result
|
||||
set type of TYPE_FORWARD_ONLY and db2 does not support it.
|
||||
*/
|
||||
scrollableResults = query.scroll( ScrollMode.SCROLL_INSENSITIVE );
|
||||
}
|
||||
else {
|
||||
scrollableResults = query.scroll( ScrollMode.FORWARD_ONLY );
|
||||
}
|
||||
|
||||
while ( scrollableResults.next() ) {
|
||||
final Employee employee = (Employee) scrollableResults.get( 0 );
|
||||
assertThat( Hibernate.isPropertyInitialized( employee, "otherEntities" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( employee.getOtherEntities() ), is( true ) );
|
||||
if ( "ENG1".equals( employee.getDept() ) ) {
|
||||
assertThat( employee.getOtherEntities().size(), is( 2 ) );
|
||||
for ( OtherEntity otherEntity : employee.getOtherEntities() ) {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( false ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( false ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertThat( employee.getOtherEntities().size(), is( 0 ) );
|
||||
}
|
||||
}
|
||||
session.getTransaction().commit();
|
||||
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||
}
|
||||
finally {
|
||||
if ( scrollableResults != null ) {
|
||||
scrollableResults.close();
|
||||
}
|
||||
if ( session.getTransaction().isActive() ) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void prepareTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Employee e1 = new Employee( "ENG1" );
|
||||
Employee e2 = new Employee( "ENG2" );
|
||||
OtherEntity other1 = new OtherEntity( "test1" );
|
||||
OtherEntity other2 = new OtherEntity( "test2" );
|
||||
e1.getOtherEntities().add( other1 );
|
||||
e1.getOtherEntities().add( other2 );
|
||||
e1.getParentOtherEntities().add( other1 );
|
||||
e1.getParentOtherEntities().add( other2 );
|
||||
other1.employee = e1;
|
||||
other2.employee = e1;
|
||||
other1.employeeParent = e1;
|
||||
other2.employeeParent = e2;
|
||||
session.persist( other1 );
|
||||
session.persist( other2 );
|
||||
session.persist( e1 );
|
||||
session.persist( e2 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from OtherEntity" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
session.createQuery( "delete from EmployeeParent" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "EmployeeParent")
|
||||
@Table(name = "EmployeeParent")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
public static abstract class EmployeeParent {
|
||||
|
||||
@Id
|
||||
private String dept;
|
||||
|
||||
@OneToMany(targetEntity = OtherEntity.class, mappedBy = "employeeParent", fetch = FetchType.LAZY)
|
||||
protected Set<OtherEntity> parentOtherEntities = new HashSet<>();
|
||||
|
||||
public Set<OtherEntity> getParentOtherEntities() {
|
||||
if ( parentOtherEntities == null ) {
|
||||
parentOtherEntities = new LinkedHashSet();
|
||||
}
|
||||
return parentOtherEntities;
|
||||
}
|
||||
|
||||
public void setOtherEntities(Set<OtherEntity> pParentOtherEntites) {
|
||||
parentOtherEntities = pParentOtherEntites;
|
||||
}
|
||||
|
||||
public String getDept() {
|
||||
return dept;
|
||||
}
|
||||
|
||||
protected void setDept(String dept) {
|
||||
this.dept = dept;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Employee")
|
||||
@Table(name = "Employee")
|
||||
public static class Employee extends EmployeeParent {
|
||||
|
||||
@OneToMany(targetEntity = OtherEntity.class, mappedBy = "employee", fetch = FetchType.LAZY)
|
||||
protected Set<OtherEntity> otherEntities = new HashSet<>();
|
||||
|
||||
public Employee(String dept) {
|
||||
this();
|
||||
setDept( dept );
|
||||
}
|
||||
|
||||
protected Employee() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public Set<OtherEntity> getOtherEntities() {
|
||||
if ( otherEntities == null ) {
|
||||
otherEntities = new LinkedHashSet();
|
||||
}
|
||||
return otherEntities;
|
||||
}
|
||||
|
||||
public void setOtherEntities(Set<OtherEntity> pOtherEntites) {
|
||||
otherEntities = pOtherEntites;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
@Table(name = "OtherEntity")
|
||||
public static class OtherEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
@JoinColumn(name = "Employee_Id")
|
||||
protected Employee employee = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
@JoinColumn(name = "EmployeeParent_Id")
|
||||
protected EmployeeParent employeeParent = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public OtherEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* 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 java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.annotations.LazyToOne;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.annotations.Tuplizer;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.ProxyFactory;
|
||||
import org.hibernate.stat.Statistics;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
import org.hibernate.tuple.entity.PojoEntityTuplizer;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
public class LazyToOnesNoProxyFactoryWithSubclassesStatefulTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( Animal.class );
|
||||
sources.addAnnotatedClass( Primate.class );
|
||||
sources.addAnnotatedClass( Human.class );
|
||||
sources.addAnnotatedClass( OtherEntity.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewEnhancedProxyAssociation() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.human = human;
|
||||
|
||||
session.persist( human );
|
||||
session.persist( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingInitializedAssociationLeafSubclass() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.animal = human;
|
||||
otherEntity.primate = human;
|
||||
otherEntity.human = human;
|
||||
session.persist( human );
|
||||
session.persist( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "primate" ) );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.primate ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.primate ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertSame( otherEntity.human, otherEntity.animal );
|
||||
assertSame( otherEntity.human, otherEntity.primate );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingEnhancedProxyAssociationLeafSubclassOnly() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.human = human;
|
||||
otherEntity.otherHuman = human;
|
||||
session.persist( human );
|
||||
session.persist( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertNull( otherEntity.animal );
|
||||
assertNull( otherEntity.primate );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "otherHuman" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.otherHuman ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.otherHuman ) );
|
||||
assertSame( otherEntity.human, otherEntity.otherHuman );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from OtherEntity" ).executeUpdate();
|
||||
session.createQuery( "delete from Human" ).executeUpdate();
|
||||
session.createQuery( "delete from Primate" ).executeUpdate();
|
||||
session.createQuery( "delete from Animal" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
@Tuplizer(impl=NoProxyFactoryPojoEntityTuplizer.class)
|
||||
public static abstract class Animal {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Primate")
|
||||
@Table(name = "Primate")
|
||||
public static class Primate extends Animal {
|
||||
|
||||
public Primate(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Primate() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Human")
|
||||
@Table(name = "Human")
|
||||
public static class Human extends Primate {
|
||||
|
||||
private String sex;
|
||||
|
||||
public Human(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Human() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
@Table(name = "OtherEntity")
|
||||
public static class OtherEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Animal animal = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Primate primate = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Human human = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Human otherHuman = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public OtherEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Human getHuman() {
|
||||
return human;
|
||||
}
|
||||
|
||||
public void setHuman(Human human) {
|
||||
this.human = human;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NoProxyFactoryPojoEntityTuplizer implements EntityTuplizer {
|
||||
|
||||
private final PojoEntityTuplizer pojoEntityTuplizer;
|
||||
|
||||
public NoProxyFactoryPojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
|
||||
pojoEntityTuplizer = new PojoEntityTuplizer( entityMetamodel, mappedEntity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMode getEntityMode() {
|
||||
return pojoEntityTuplizer.getEntityMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate(Serializable id) throws HibernateException {
|
||||
return pojoEntityTuplizer.instantiate( id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate(Serializable id, SharedSessionContractImplementor session) {
|
||||
return pojoEntityTuplizer.instantiate( id, session );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdentifier(Object entity) throws HibernateException {
|
||||
return pojoEntityTuplizer.getIdentifier( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
return pojoEntityTuplizer.getIdentifier( entity, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Serializable id) throws HibernateException {
|
||||
pojoEntityTuplizer.setIdentifier( entity, id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Serializable id, SharedSessionContractImplementor session) {
|
||||
pojoEntityTuplizer.setIdentifier( entity, id, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetIdentifier(Object entity, Serializable currentId, Object currentVersion) {
|
||||
pojoEntityTuplizer.resetIdentifier( entity, currentId, currentVersion );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetIdentifier(
|
||||
Object entity,
|
||||
Serializable currentId,
|
||||
Object currentVersion,
|
||||
SharedSessionContractImplementor session) {
|
||||
pojoEntityTuplizer.resetIdentifier( entity, currentId, currentVersion, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getVersion(Object entity) throws HibernateException {
|
||||
return pojoEntityTuplizer.getVersion( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValue(Object entity, int i, Object value) throws HibernateException {
|
||||
pojoEntityTuplizer. setPropertyValue( entity, i, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException {
|
||||
pojoEntityTuplizer.setPropertyValue( entity, propertyName, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getPropertyValuesToInsert(
|
||||
Object entity,
|
||||
Map mergeMap,
|
||||
SharedSessionContractImplementor session) throws HibernateException {
|
||||
return pojoEntityTuplizer.getPropertyValuesToInsert( entity, mergeMap, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(Object entity, String propertyName) throws HibernateException {
|
||||
return pojoEntityTuplizer.getPropertyValue( entity, propertyName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterInitialize(Object entity, SharedSessionContractImplementor session) {
|
||||
pojoEntityTuplizer.afterInitialize( entity, session );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProxy() {
|
||||
return pojoEntityTuplizer.hasProxy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createProxy(Serializable id, SharedSessionContractImplementor session) throws HibernateException {
|
||||
return pojoEntityTuplizer.createProxy( id, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLifecycleImplementor() {
|
||||
return pojoEntityTuplizer.isLifecycleImplementor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getConcreteProxyClass() {
|
||||
return pojoEntityTuplizer.getConcreteProxyClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityNameResolver[] getEntityNameResolvers() {
|
||||
return pojoEntityTuplizer.getEntityNameResolvers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String determineConcreteSubclassEntityName(
|
||||
Object entityInstance, SessionFactoryImplementor factory) {
|
||||
return pojoEntityTuplizer.determineConcreteSubclassEntityName( entityInstance, factory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Getter getIdentifierGetter() {
|
||||
return pojoEntityTuplizer.getIdentifierGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Getter getVersionGetter() {
|
||||
return pojoEntityTuplizer.getVersionGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProxyFactory getProxyFactory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getPropertyValues(Object entity) {
|
||||
return pojoEntityTuplizer.getPropertyValues( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValues(Object entity, Object[] values) {
|
||||
pojoEntityTuplizer.setPropertyValues( entity, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(Object entity, int i) {
|
||||
return pojoEntityTuplizer.getPropertyValue( entity, i );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate() {
|
||||
return pojoEntityTuplizer.instantiate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstance(Object object) {
|
||||
return pojoEntityTuplizer.isInstance( object );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getMappedClass() {
|
||||
return pojoEntityTuplizer.getMappedClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Getter getGetter(int i) {
|
||||
return pojoEntityTuplizer.getGetter( i );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* 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 java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.annotations.LazyToOne;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.annotations.Tuplizer;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.ProxyFactory;
|
||||
import org.hibernate.stat.Statistics;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
import org.hibernate.tuple.entity.PojoEntityTuplizer;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
public class LazyToOnesNoProxyFactoryWithSubclassesStatelessTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( Animal.class );
|
||||
sources.addAnnotatedClass( Primate.class );
|
||||
sources.addAnnotatedClass( Human.class );
|
||||
sources.addAnnotatedClass( OtherEntity.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewEnhancedProxyAssociation() {
|
||||
inStatelessTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.human = human;
|
||||
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingInitializedAssociationLeafSubclass() {
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.animal = human;
|
||||
otherEntity.primate = human;
|
||||
otherEntity.human = human;
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "primate" ) );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.primate ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.primate ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertSame( otherEntity.human, otherEntity.animal );
|
||||
assertSame( otherEntity.human, otherEntity.primate );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingEnhancedProxyAssociationLeafSubclassOnly() {
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.human = human;
|
||||
otherEntity.otherHuman = human;
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertNull( otherEntity.animal );
|
||||
assertNull( otherEntity.primate );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "otherHuman" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.otherHuman ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.otherHuman ) );
|
||||
assertSame( otherEntity.human, otherEntity.otherHuman );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from OtherEntity" ).executeUpdate();
|
||||
session.createQuery( "delete from Human" ).executeUpdate();
|
||||
session.createQuery( "delete from Primate" ).executeUpdate();
|
||||
session.createQuery( "delete from Animal" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
@Tuplizer(impl=NoProxyFactoryPojoEntityTuplizer.class)
|
||||
public static abstract class Animal {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Primate")
|
||||
@Table(name = "Primate")
|
||||
public static class Primate extends Animal {
|
||||
|
||||
public Primate(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Primate() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Human")
|
||||
@Table(name = "Human")
|
||||
public static class Human extends Primate {
|
||||
|
||||
private String sex;
|
||||
|
||||
public Human(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Human() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
@Table(name = "OtherEntity")
|
||||
public static class OtherEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Animal animal = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Primate primate = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Human human = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Human otherHuman = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public OtherEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Human getHuman() {
|
||||
return human;
|
||||
}
|
||||
|
||||
public void setHuman(Human human) {
|
||||
this.human = human;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NoProxyFactoryPojoEntityTuplizer implements EntityTuplizer {
|
||||
|
||||
private final PojoEntityTuplizer pojoEntityTuplizer;
|
||||
|
||||
public NoProxyFactoryPojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
|
||||
pojoEntityTuplizer = new PojoEntityTuplizer( entityMetamodel, mappedEntity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMode getEntityMode() {
|
||||
return pojoEntityTuplizer.getEntityMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate(Serializable id) throws HibernateException {
|
||||
return pojoEntityTuplizer.instantiate( id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate(Serializable id, SharedSessionContractImplementor session) {
|
||||
return pojoEntityTuplizer.instantiate( id, session );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdentifier(Object entity) throws HibernateException {
|
||||
return pojoEntityTuplizer.getIdentifier( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
return pojoEntityTuplizer.getIdentifier( entity, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Serializable id) throws HibernateException {
|
||||
pojoEntityTuplizer.setIdentifier( entity, id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Serializable id, SharedSessionContractImplementor session) {
|
||||
pojoEntityTuplizer.setIdentifier( entity, id, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetIdentifier(Object entity, Serializable currentId, Object currentVersion) {
|
||||
pojoEntityTuplizer.resetIdentifier( entity, currentId, currentVersion );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetIdentifier(
|
||||
Object entity,
|
||||
Serializable currentId,
|
||||
Object currentVersion,
|
||||
SharedSessionContractImplementor session) {
|
||||
pojoEntityTuplizer.resetIdentifier( entity, currentId, currentVersion, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getVersion(Object entity) throws HibernateException {
|
||||
return pojoEntityTuplizer.getVersion( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValue(Object entity, int i, Object value) throws HibernateException {
|
||||
pojoEntityTuplizer. setPropertyValue( entity, i, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException {
|
||||
pojoEntityTuplizer.setPropertyValue( entity, propertyName, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getPropertyValuesToInsert(
|
||||
Object entity,
|
||||
Map mergeMap,
|
||||
SharedSessionContractImplementor session) throws HibernateException {
|
||||
return pojoEntityTuplizer.getPropertyValuesToInsert( entity, mergeMap, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(Object entity, String propertyName) throws HibernateException {
|
||||
return pojoEntityTuplizer.getPropertyValue( entity, propertyName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterInitialize(Object entity, SharedSessionContractImplementor session) {
|
||||
pojoEntityTuplizer.afterInitialize( entity, session );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProxy() {
|
||||
return pojoEntityTuplizer.hasProxy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createProxy(Serializable id, SharedSessionContractImplementor session) throws HibernateException {
|
||||
return pojoEntityTuplizer.createProxy( id, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLifecycleImplementor() {
|
||||
return pojoEntityTuplizer.isLifecycleImplementor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getConcreteProxyClass() {
|
||||
return pojoEntityTuplizer.getConcreteProxyClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityNameResolver[] getEntityNameResolvers() {
|
||||
return pojoEntityTuplizer.getEntityNameResolvers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String determineConcreteSubclassEntityName(
|
||||
Object entityInstance, SessionFactoryImplementor factory) {
|
||||
return pojoEntityTuplizer.determineConcreteSubclassEntityName( entityInstance, factory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Getter getIdentifierGetter() {
|
||||
return pojoEntityTuplizer.getIdentifierGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Getter getVersionGetter() {
|
||||
return pojoEntityTuplizer.getVersionGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProxyFactory getProxyFactory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getPropertyValues(Object entity) {
|
||||
return pojoEntityTuplizer.getPropertyValues( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValues(Object entity, Object[] values) {
|
||||
pojoEntityTuplizer.setPropertyValues( entity, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(Object entity, int i) {
|
||||
return pojoEntityTuplizer.getPropertyValue( entity, i );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate() {
|
||||
return pojoEntityTuplizer.instantiate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstance(Object object) {
|
||||
return pojoEntityTuplizer.isInstance( object );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getMappedClass() {
|
||||
return pojoEntityTuplizer.getMappedClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Getter getGetter(int i) {
|
||||
return pojoEntityTuplizer.getGetter( i );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,865 @@
|
|||
/*
|
||||
* 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 javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.annotations.LazyToOne;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
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.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
@RunWith(BytecodeEnhancerRunner.class )
|
||||
@EnhancementOptions(lazyLoading = true)
|
||||
public class LazyToOnesProxyMergeWithSubclassesTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( Animal.class );
|
||||
sources.addAnnotatedClass( Primate.class );
|
||||
sources.addAnnotatedClass( Human.class );
|
||||
sources.addAnnotatedClass( OtherEntity.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeUpdatedHibernateProxy() {
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity withInitializedHibernateProxy = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
otherEntity.getHuman().getSex();
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
return otherEntity;
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated HibernateProxy to updated HibernateProxy
|
||||
|
||||
withInitializedHibernateProxy.getHuman().setAge( 2 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
otherEntity.getHuman().setAge( 3 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
final Human humanImpl = (Human) ( (HibernateProxy) otherEntity.getHuman() )
|
||||
.getHibernateLazyInitializer()
|
||||
.getImplementation();
|
||||
|
||||
session.merge( withInitializedHibernateProxy );
|
||||
// TODO: Reference to associated HibernateProxy is changed
|
||||
// to the HibernateProxy's implementation.
|
||||
assertSame( humanImpl, otherEntity.getHuman() );
|
||||
assertEquals( 2, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 2 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated HibernateProxy to updated enhanced entity
|
||||
|
||||
withInitializedHibernateProxy.getHuman().setAge( 4 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
human.setAge( 5 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
session.merge( withInitializedHibernateProxy );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertEquals( 4, human.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 4 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated HibernateProxy to uninitialized HibernateProxy
|
||||
|
||||
withInitializedHibernateProxy.getHuman().setAge( 6 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
final Human humanHibernateProxy = otherEntity.getHuman();
|
||||
|
||||
session.merge( withInitializedHibernateProxy );
|
||||
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
// TODO: Reference to associated HibernateProxy is changed
|
||||
// reference to the HibernateProxy's implementation.
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
assertSame(
|
||||
otherEntity.getHuman(),
|
||||
( (HibernateProxy) humanHibernateProxy ).getHibernateLazyInitializer().getImplementation()
|
||||
);
|
||||
|
||||
assertEquals( 6, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 6 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated HibernateProxy To uninitialized enhanced proxy
|
||||
|
||||
withInitializedHibernateProxy.getHuman().setAge( 7 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
|
||||
session.merge( withInitializedHibernateProxy );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertTrue( Hibernate.isInitialized( human ) );
|
||||
|
||||
assertEquals( 7, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 7 );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeUpdatedEnhancedProxy() {
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity withInitializedEnhancedProxy = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
otherEntity.getHuman().getSex();
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
return otherEntity;
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated enhanced proxy to updated HibernateProxy
|
||||
|
||||
withInitializedEnhancedProxy.getHuman().setAge( 2 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
otherEntity.getHuman().setAge( 3 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
final Human humanImpl = (Human) ( (HibernateProxy) otherEntity.getHuman() )
|
||||
.getHibernateLazyInitializer()
|
||||
.getImplementation();
|
||||
|
||||
session.merge( withInitializedEnhancedProxy );
|
||||
// TODO: Reference to HibernateProxy is changed
|
||||
// to the HibernateProxy's implementation.
|
||||
assertSame( humanImpl, otherEntity.getHuman() );
|
||||
|
||||
assertEquals( 2, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 2 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated enhanced proxy to updated enhanced proxy
|
||||
|
||||
withInitializedEnhancedProxy.getHuman().setAge( 4 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
human.setAge( 5 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
session.merge( withInitializedEnhancedProxy );
|
||||
assertEquals( 4, human.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 4 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated enhanced proxy to uninitialized HibernateProxy
|
||||
|
||||
withInitializedEnhancedProxy.getHuman().setAge( 6 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
session.merge( withInitializedEnhancedProxy );
|
||||
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
// TODO: Reference in managed entity gets changed from a HibernateProxy
|
||||
// to an initialized entity. This happens without enhancement as well.
|
||||
//assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
assertEquals( 6, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 6 );
|
||||
stats.clear();
|
||||
|
||||
// merge updated enhanced proxy to uninitialized enhanced proxy
|
||||
|
||||
withInitializedEnhancedProxy.getHuman().setAge( 7 );
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
|
||||
session.merge( withInitializedEnhancedProxy );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertTrue( Hibernate.isInitialized( human ) );
|
||||
|
||||
assertEquals( 7, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 7 );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeUninitializedHibernateProxy() {
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity withUninitializedHibernateProxy = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
return otherEntity;
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized HibernateProxy to updated HibernateProxy
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
otherEntity.getHuman().setAge( 3 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
final Human humanImpl = (Human) ( (HibernateProxy) otherEntity.getHuman() )
|
||||
.getHibernateLazyInitializer()
|
||||
.getImplementation();
|
||||
|
||||
session.merge( withUninitializedHibernateProxy );
|
||||
//assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
// TODO: Reference to HibernateProxy is changed
|
||||
// to the HibernateProxy's implementation.
|
||||
assertSame( humanImpl, otherEntity.getHuman() );
|
||||
|
||||
assertEquals( 3, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 3 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized HibernateProxy to updated enhanced proxy
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
human.setAge( 5 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
session.merge( withUninitializedHibernateProxy );
|
||||
assertEquals( 5, human.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 5 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized HibernateProxy to uninitialized HibernateProxy
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
session.merge( withUninitializedHibernateProxy );
|
||||
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 5 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized HibernateProxy to uninitialized enhanced proxy
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
|
||||
session.merge( withUninitializedHibernateProxy );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 5 );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testmergeUninitializedEnhancedProxy() {
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity withUninitializedEnhancedProxy = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
return otherEntity;
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 1 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized enhanced proxy to updated HibernateProxy
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
otherEntity.getHuman().setAge( 3 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
final Human humanImpl = (Human) ( (HibernateProxy) otherEntity.getHuman() )
|
||||
.getHibernateLazyInitializer()
|
||||
.getImplementation();
|
||||
|
||||
session.merge( withUninitializedEnhancedProxy );
|
||||
// TODO: Reference to HibernateProxy is changed
|
||||
// to the HibernateProxy's implementation.
|
||||
assertSame( humanImpl, otherEntity.getHuman() );
|
||||
|
||||
assertEquals( 3, otherEntity.getHuman().getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 3 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized enhanced proxy to updated enhanced entity
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
human.setAge( 5 );
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
session.merge( withUninitializedEnhancedProxy );
|
||||
assertEquals( 5, human.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 3, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 5 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized enhanced proxy to uninitialized HibernateProxy
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
session.merge( withUninitializedEnhancedProxy );
|
||||
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.getHuman() ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 5 );
|
||||
stats.clear();
|
||||
|
||||
// merge uninitialized enhanced proxy to uninitialized enhanced proxy
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( human ) );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
|
||||
session.merge( withUninitializedEnhancedProxy );
|
||||
assertSame( human, otherEntity.getHuman() );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
checkAgeInNewSession( 5 );
|
||||
}
|
||||
|
||||
private void checkAgeInNewSession(int expectedAge) {
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Human human = session.get( Human.class, "A Human" );
|
||||
assertEquals( expectedAge, human.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.animal = human;
|
||||
otherEntity.primate = human;
|
||||
otherEntity.human = human;
|
||||
otherEntity.human.setAge( 1 );
|
||||
|
||||
session.persist( human );
|
||||
session.persist( otherEntity );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from OtherEntity" ).executeUpdate();
|
||||
session.createQuery( "delete from Human" ).executeUpdate();
|
||||
session.createQuery( "delete from Primate" ).executeUpdate();
|
||||
session.createQuery( "delete from Animal" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
public static abstract class Animal {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Primate")
|
||||
@Table(name = "Primate")
|
||||
public static class Primate extends Animal {
|
||||
|
||||
public Primate(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Primate() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Human")
|
||||
@Table(name = "Human")
|
||||
public static class Human extends Primate {
|
||||
|
||||
private String sex;
|
||||
|
||||
public Human(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Human() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
@Table(name = "OtherEntity")
|
||||
public static class OtherEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Animal animal = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Primate primate = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Human human = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public OtherEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Human getHuman() {
|
||||
return human;
|
||||
}
|
||||
|
||||
public void setHuman(Human human) {
|
||||
this.human = human;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* 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 javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.annotations.LazyToOne;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
public class LazyToOnesProxyWithSubclassesStatelessTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( Animal.class );
|
||||
sources.addAnnotatedClass( Primate.class );
|
||||
sources.addAnnotatedClass( Human.class );
|
||||
sources.addAnnotatedClass( OtherEntity.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewHibernateProxyAssociation() {
|
||||
inStatelessTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.animal = human;
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewEnhancedProxyAssociation() {
|
||||
inStatelessTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.human = human;
|
||||
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingProxyAssociation() {
|
||||
inStatelessTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.animal = human;
|
||||
otherEntity.primate = human;
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "primate" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.primate ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.primate ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingHibernateProxyAssociationLeafSubclass() {
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.animal = human;
|
||||
otherEntity.primate = human;
|
||||
otherEntity.human = human;
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "primate" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.primate ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.primate ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingEnhancedProxyAssociationLeafSubclassOnly() {
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.human = human;
|
||||
session.insert( human );
|
||||
session.insert( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inStatelessSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity otherEntity = (OtherEntity) session.get( OtherEntity.class, "test1" );
|
||||
assertNull( otherEntity.animal );
|
||||
assertNull( otherEntity.primate );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from OtherEntity" ).executeUpdate();
|
||||
session.createQuery( "delete from Human" ).executeUpdate();
|
||||
session.createQuery( "delete from Primate" ).executeUpdate();
|
||||
session.createQuery( "delete from Animal" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
public static abstract class Animal {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Primate")
|
||||
@Table(name = "Primate")
|
||||
public static class Primate extends Animal {
|
||||
|
||||
public Primate(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Primate() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Human")
|
||||
@Table(name = "Human")
|
||||
public static class Human extends Primate {
|
||||
|
||||
private String sex;
|
||||
|
||||
public Human(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
}
|
||||
|
||||
protected Human() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
@Table(name = "OtherEntity")
|
||||
public static class OtherEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Animal animal = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Primate primate = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
private Human human = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public OtherEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Human getHuman() {
|
||||
return human;
|
||||
}
|
||||
|
||||
public void setHuman(Human human) {
|
||||
this.human = human;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,8 +31,10 @@ import org.junit.After;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
|
@ -154,7 +156,7 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExistingProxyAssociationLeafSubclass() {
|
||||
public void testExistingHibernateProxyAssociationLeafSubclass() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
|
@ -167,11 +169,12 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
|
@ -181,18 +184,101 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
assertTrue( HibernateProxy.class.isInstance( otherEntity.primate ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
// TODO: Should otherEntity.human be a narrowed HibernateProxy or
|
||||
// an uninitialized non-HibernateProxy proxy?
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
Human human = otherEntity.getHuman();
|
||||
// Make sure human can still get loaded and not initialized.
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
|
||||
human.getName();
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
|
||||
human.getSex();
|
||||
|
||||
assertTrue( Hibernate.isInitialized( human ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
stats.clear();
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "primate" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.primate ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.primate ) );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
// Make sure human can still get loaded
|
||||
final Human human = session.get( Human.class, "A Human" );
|
||||
assertTrue( !HibernateProxy.class.isInstance( human ) );
|
||||
assertTrue( Hibernate.isInitialized( human ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.getHuman() ) );
|
||||
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingEnhancedProxyAssociationLeafSubclassOnly() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.human = human;
|
||||
session.persist( human );
|
||||
session.persist( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertNull( otherEntity.animal );
|
||||
assertNull( otherEntity.primate );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "human" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
// Make sure human can still get loaded and not initialized.
|
||||
final Human human = session.getReference( Human.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
|
||||
human.getName();
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
|
||||
human.getSex();
|
||||
assertTrue( Hibernate.isInitialized( otherEntity.human ) );
|
||||
assertFalse( HibernateProxy.class.isInstance( otherEntity.human ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
return otherEntity;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -215,6 +301,8 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -223,6 +311,13 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Primate")
|
||||
|
@ -272,15 +367,15 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
protected Animal animal = null;
|
||||
private Animal animal = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
protected Primate primate = null;
|
||||
private Primate primate = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
protected Human human = null;
|
||||
private Human human = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.junit.runner.RunWith;
|
|||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
|
@ -155,7 +156,8 @@ public class ProxyInitializeAndUpdateTest extends BaseNonConfigCoreFunctionalTes
|
|||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalInitialized );
|
||||
final Animal animalMerged = (Animal) session.merge( animalInitialized );
|
||||
assertSame( animal, animalMerged );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
|
@ -204,7 +206,8 @@ public class ProxyInitializeAndUpdateTest extends BaseNonConfigCoreFunctionalTes
|
|||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setAge( 5 );
|
||||
animal.setSex( "male" );
|
||||
session.merge( animalInitialized );
|
||||
final Animal animalMerged = (Animal) session.merge( animalInitialized );
|
||||
assertSame( animal, animalMerged );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
}
|
||||
|
@ -245,7 +248,8 @@ public class ProxyInitializeAndUpdateTest extends BaseNonConfigCoreFunctionalTes
|
|||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalUninitialized );
|
||||
final Animal animalMerged = (Animal) session.merge( animalUninitialized );
|
||||
assertSame( animal, animalMerged );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
}
|
||||
);
|
||||
|
@ -283,11 +287,13 @@ public class ProxyInitializeAndUpdateTest extends BaseNonConfigCoreFunctionalTes
|
|||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
animal.setSex( "other" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setAge( 4 );
|
||||
session.merge( animalUninitialized );
|
||||
final Animal animalMerged = (Animal) session.merge( animalUninitialized );
|
||||
assertSame( animal, animalMerged );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* 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 java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.annotations.LazyToOne;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
public class QueryScrollingWithInheritanceProxyTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( EmployeeParent.class );
|
||||
sources.addAnnotatedClass( Employee.class );
|
||||
sources.addAnnotatedClass( OtherEntity.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrollableWithStatelessSession() {
|
||||
final StatisticsImplementor stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
ScrollableResults scrollableResults = null;
|
||||
final StatelessSession statelessSession = sessionFactory().openStatelessSession();
|
||||
|
||||
try {
|
||||
statelessSession.beginTransaction();
|
||||
Query<Employee> query = statelessSession.createQuery(
|
||||
"select distinct e from Employee e left join fetch e.otherEntities order by e.dept",
|
||||
Employee.class
|
||||
);
|
||||
if ( getDialect() instanceof DB2Dialect ) {
|
||||
/*
|
||||
FetchingScrollableResultsImp#next() in order to check if the ResultSet is empty calls ResultSet#isBeforeFirst()
|
||||
but the support for ResultSet#isBeforeFirst() is optional for ResultSets with a result
|
||||
set type of TYPE_FORWARD_ONLY and db2 does not support it.
|
||||
*/
|
||||
scrollableResults = query.scroll( ScrollMode.SCROLL_INSENSITIVE );
|
||||
}
|
||||
else {
|
||||
scrollableResults = query.scroll( ScrollMode.FORWARD_ONLY );
|
||||
}
|
||||
|
||||
while ( scrollableResults.next() ) {
|
||||
final Employee employee = (Employee) scrollableResults.get( 0 );
|
||||
assertThat( Hibernate.isPropertyInitialized( employee, "otherEntities" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( employee.getOtherEntities() ), is( true ) );
|
||||
if ( "ENG1".equals( employee.getDept() ) ) {
|
||||
assertThat( employee.getOtherEntities().size(), is( 2 ) );
|
||||
for ( OtherEntity otherEntity : employee.getOtherEntities() ) {
|
||||
if ( "test1".equals( otherEntity.id ) ) {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( otherEntity.employeeParent, is( employee ) );
|
||||
}
|
||||
else {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( otherEntity.employeeParent ), is( false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertThat( employee.getOtherEntities().size(), is( 0 ) );
|
||||
}
|
||||
}
|
||||
statelessSession.getTransaction().commit();
|
||||
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||
}
|
||||
finally {
|
||||
if ( scrollableResults != null ) {
|
||||
scrollableResults.close();
|
||||
}
|
||||
if ( statelessSession.getTransaction().isActive() ) {
|
||||
statelessSession.getTransaction().rollback();
|
||||
}
|
||||
statelessSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrollableWithSession() {
|
||||
final StatisticsImplementor stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
ScrollableResults scrollableResults = null;
|
||||
final Session session = sessionFactory().openSession();
|
||||
|
||||
try {
|
||||
session.beginTransaction();
|
||||
Query<Employee> query = session.createQuery(
|
||||
"select distinct e from Employee e left join fetch e.otherEntities order by e.dept",
|
||||
Employee.class
|
||||
);
|
||||
if ( getDialect() instanceof DB2Dialect ) {
|
||||
/*
|
||||
FetchingScrollableResultsImp#next() in order to check if the ResultSet is empty calls ResultSet#isBeforeFirst()
|
||||
but the support for ResultSet#isBeforeFirst() is optional for ResultSets with a result
|
||||
set type of TYPE_FORWARD_ONLY and db2 does not support it.
|
||||
*/
|
||||
scrollableResults = query.scroll( ScrollMode.SCROLL_INSENSITIVE );
|
||||
}
|
||||
else {
|
||||
scrollableResults = query.scroll( ScrollMode.FORWARD_ONLY );
|
||||
}
|
||||
|
||||
while ( scrollableResults.next() ) {
|
||||
final Employee employee = (Employee) scrollableResults.get( 0 );
|
||||
assertThat( Hibernate.isPropertyInitialized( employee, "otherEntities" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( employee.getOtherEntities() ), is( true ) );
|
||||
if ( "ENG1".equals( employee.getDept() ) ) {
|
||||
assertThat( employee.getOtherEntities().size(), is( 2 ) );
|
||||
for ( OtherEntity otherEntity : employee.getOtherEntities() ) {
|
||||
if ( "test1".equals( otherEntity.id ) ) {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( otherEntity.employeeParent, is( employee ) );
|
||||
}
|
||||
else {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( otherEntity.employeeParent ), is( false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertThat( employee.getOtherEntities().size(), is( 0 ) );
|
||||
}
|
||||
}
|
||||
session.getTransaction().commit();
|
||||
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||
}
|
||||
finally {
|
||||
if ( scrollableResults != null ) {
|
||||
scrollableResults.close();
|
||||
}
|
||||
if ( session.getTransaction().isActive() ) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void prepareTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Employee e1 = new Employee( "ENG1" );
|
||||
Employee e2 = new Employee( "ENG2" );
|
||||
OtherEntity other1 = new OtherEntity( "test1" );
|
||||
OtherEntity other2 = new OtherEntity( "test2" );
|
||||
e1.getOtherEntities().add( other1 );
|
||||
e1.getOtherEntities().add( other2 );
|
||||
e1.getParentOtherEntities().add( other1 );
|
||||
e1.getParentOtherEntities().add( other2 );
|
||||
other1.employee = e1;
|
||||
other2.employee = e1;
|
||||
other1.employeeParent = e1;
|
||||
other2.employeeParent = e2;
|
||||
session.persist( other1 );
|
||||
session.persist( other2 );
|
||||
session.persist( e1 );
|
||||
session.persist( e2 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from OtherEntity" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
session.createQuery( "delete from EmployeeParent" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "EmployeeParent")
|
||||
@Table(name = "EmployeeParent")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
public static abstract class EmployeeParent {
|
||||
|
||||
@Id
|
||||
private String dept;
|
||||
|
||||
@OneToMany(targetEntity = OtherEntity.class, mappedBy = "employeeParent", fetch = FetchType.LAZY)
|
||||
protected Set<OtherEntity> parentOtherEntities = new HashSet<>();
|
||||
|
||||
public Set<OtherEntity> getParentOtherEntities() {
|
||||
if ( parentOtherEntities == null ) {
|
||||
parentOtherEntities = new LinkedHashSet();
|
||||
}
|
||||
return parentOtherEntities;
|
||||
}
|
||||
|
||||
public void setOtherEntities(Set<OtherEntity> pParentOtherEntites) {
|
||||
parentOtherEntities = pParentOtherEntites;
|
||||
}
|
||||
|
||||
public String getDept() {
|
||||
return dept;
|
||||
}
|
||||
|
||||
protected void setDept(String dept) {
|
||||
this.dept = dept;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Employee")
|
||||
@Table(name = "Employee")
|
||||
public static class Employee extends EmployeeParent {
|
||||
|
||||
@OneToMany(targetEntity = OtherEntity.class, mappedBy = "employee", fetch = FetchType.LAZY)
|
||||
protected Set<OtherEntity> otherEntities = new HashSet<>();
|
||||
|
||||
public Employee(String dept) {
|
||||
this();
|
||||
setDept( dept );
|
||||
}
|
||||
|
||||
protected Employee() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public Set<OtherEntity> getOtherEntities() {
|
||||
if ( otherEntities == null ) {
|
||||
otherEntities = new LinkedHashSet();
|
||||
}
|
||||
return otherEntities;
|
||||
}
|
||||
|
||||
public void setOtherEntities(Set<OtherEntity> pOtherEntites) {
|
||||
otherEntities = pOtherEntites;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
@Table(name = "OtherEntity")
|
||||
public static class OtherEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
@JoinColumn(name = "Employee_Id")
|
||||
protected Employee employee = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@LazyToOne(LazyToOneOption.NO_PROXY)
|
||||
@JoinColumn(name = "EmployeeParent_Id")
|
||||
protected EmployeeParent employeeParent = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public OtherEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
72
hibernate-core/src/test/java/org/hibernate/test/cfg/cache/DirectReferenceCacheEntriesTest.java
vendored
Normal file
72
hibernate-core/src/test/java/org/hibernate/test/cfg/cache/DirectReferenceCacheEntriesTest.java
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.cfg.cache;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.Immutable;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-13665")
|
||||
public class DirectReferenceCacheEntriesTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { TheEntity.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
configuration.setProperty( AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES, "true" );
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
TheEntity theEntity = new TheEntity();
|
||||
theEntity.setId( 1L );
|
||||
session.persist( theEntity );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectANonCachablenEntity() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.createQuery( "select t from TheEntity t", TheEntity.class ).getResultList();
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "TheEntity")
|
||||
@Table(name = "THE_ENTITY")
|
||||
@Immutable
|
||||
public static class TheEntity {
|
||||
@Id
|
||||
public Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.flush;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test for issue https://hibernate.atlassian.net/browse/HHH-13663
|
||||
*
|
||||
* @author Luca Domenichini
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-13663")
|
||||
public class TestHibernateFlushModeOnThreadLocalInactiveTransaction extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
configuration.setProperty( AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS, "thread" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHibernateFlushModeOnInactiveTransaction() {
|
||||
try ( Session s = sessionFactory().getCurrentSession() ) {
|
||||
//s.setFlushMode( FlushMode.AUTO ); // this does not throw (API is deprecated)
|
||||
s.setHibernateFlushMode( FlushMode.AUTO ); // this should not throw even within an inactive transaction
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* 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.hqlfetchscroll;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
public class QueryScrollingWithInheritanceTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( EmployeeParent.class );
|
||||
sources.addAnnotatedClass( Employee.class );
|
||||
sources.addAnnotatedClass( OtherEntity.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrollableWithStatelessSession() {
|
||||
final StatisticsImplementor stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
ScrollableResults scrollableResults = null;
|
||||
final StatelessSession statelessSession = sessionFactory().openStatelessSession();
|
||||
|
||||
try {
|
||||
statelessSession.beginTransaction();
|
||||
Query<Employee> query = statelessSession.createQuery(
|
||||
"select distinct e from Employee e left join fetch e.otherEntities order by e.dept",
|
||||
Employee.class
|
||||
);
|
||||
if ( getDialect() instanceof DB2Dialect ) {
|
||||
/*
|
||||
FetchingScrollableResultsImp#next() in order to check if the ResultSet is empty calls ResultSet#isBeforeFirst()
|
||||
but the support for ResultSet#isBeforeFirst() is optional for ResultSets with a result
|
||||
set type of TYPE_FORWARD_ONLY and db2 does not support it.
|
||||
*/
|
||||
scrollableResults = query.scroll( ScrollMode.SCROLL_INSENSITIVE );
|
||||
}
|
||||
else {
|
||||
scrollableResults = query.scroll( ScrollMode.FORWARD_ONLY );
|
||||
}
|
||||
|
||||
while ( scrollableResults.next() ) {
|
||||
final Employee employee = (Employee) scrollableResults.get( 0 );
|
||||
assertThat( Hibernate.isPropertyInitialized( employee, "otherEntities" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( employee.getOtherEntities() ), is( true ) );
|
||||
if ( "ENG1".equals( employee.getDept() ) ) {
|
||||
assertThat( employee.getOtherEntities().size(), is( 2 ) );
|
||||
for ( OtherEntity otherEntity : employee.getOtherEntities() ) {
|
||||
if ( "test1".equals( otherEntity.id ) ) {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( otherEntity.employeeParent, is( employee ) );
|
||||
}
|
||||
else {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( otherEntity.employeeParent ), is( false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertThat( employee.getOtherEntities().size(), is( 0 ) );
|
||||
}
|
||||
}
|
||||
statelessSession.getTransaction().commit();
|
||||
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||
}
|
||||
finally {
|
||||
if ( scrollableResults != null ) {
|
||||
scrollableResults.close();
|
||||
}
|
||||
if ( statelessSession.getTransaction().isActive() ) {
|
||||
statelessSession.getTransaction().rollback();
|
||||
}
|
||||
statelessSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrollableWithSession() {
|
||||
final StatisticsImplementor stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
ScrollableResults scrollableResults = null;
|
||||
final Session session = sessionFactory().openSession();
|
||||
|
||||
try {
|
||||
session.beginTransaction();
|
||||
Query<Employee> query = session.createQuery(
|
||||
"select distinct e from Employee e left join fetch e.otherEntities order by e.dept",
|
||||
Employee.class
|
||||
);
|
||||
if ( getDialect() instanceof DB2Dialect ) {
|
||||
/*
|
||||
FetchingScrollableResultsImp#next() in order to check if the ResultSet is empty calls ResultSet#isBeforeFirst()
|
||||
but the support for ResultSet#isBeforeFirst() is optional for ResultSets with a result
|
||||
set type of TYPE_FORWARD_ONLY and db2 does not support it.
|
||||
*/
|
||||
scrollableResults = query.scroll( ScrollMode.SCROLL_INSENSITIVE );
|
||||
}
|
||||
else {
|
||||
scrollableResults = query.scroll( ScrollMode.FORWARD_ONLY );
|
||||
}
|
||||
|
||||
while ( scrollableResults.next() ) {
|
||||
final Employee employee = (Employee) scrollableResults.get( 0 );
|
||||
assertThat( Hibernate.isPropertyInitialized( employee, "otherEntities" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( employee.getOtherEntities() ), is( true ) );
|
||||
if ( "ENG1".equals( employee.getDept() ) ) {
|
||||
assertThat( employee.getOtherEntities().size(), is( 2 ) );
|
||||
for ( OtherEntity otherEntity : employee.getOtherEntities() ) {
|
||||
if ( "test1".equals( otherEntity.id ) ) {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( otherEntity.employeeParent, is( employee ) );
|
||||
}
|
||||
else {
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employee" ), is( true ) );
|
||||
assertThat( otherEntity.employee, is( employee ) );
|
||||
assertThat( Hibernate.isPropertyInitialized( otherEntity, "employeeParent" ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( otherEntity.employeeParent ), is( false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertThat( employee.getOtherEntities().size(), is( 0 ) );
|
||||
}
|
||||
}
|
||||
session.getTransaction().commit();
|
||||
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||
}
|
||||
finally {
|
||||
if ( scrollableResults != null ) {
|
||||
scrollableResults.close();
|
||||
}
|
||||
if ( session.getTransaction().isActive() ) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void prepareTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Employee e1 = new Employee( "ENG1" );
|
||||
Employee e2 = new Employee( "ENG2" );
|
||||
OtherEntity other1 = new OtherEntity( "test1" );
|
||||
OtherEntity other2 = new OtherEntity( "test2" );
|
||||
e1.getOtherEntities().add( other1 );
|
||||
e1.getOtherEntities().add( other2 );
|
||||
e1.getParentOtherEntities().add( other1 );
|
||||
e1.getParentOtherEntities().add( other2 );
|
||||
other1.employee = e1;
|
||||
other2.employee = e1;
|
||||
other1.employeeParent = e1;
|
||||
other2.employeeParent = e2;
|
||||
session.persist( other1 );
|
||||
session.persist( other2 );
|
||||
session.persist( e1 );
|
||||
session.persist( e2 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from OtherEntity" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
session.createQuery( "delete from EmployeeParent" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "EmployeeParent")
|
||||
@Table(name = "EmployeeParent")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
public static abstract class EmployeeParent {
|
||||
|
||||
@Id
|
||||
private String dept;
|
||||
|
||||
@OneToMany(targetEntity = OtherEntity.class, mappedBy = "employeeParent", fetch = FetchType.LAZY)
|
||||
protected Set<OtherEntity> parentOtherEntities = new HashSet<>();
|
||||
|
||||
public Set<OtherEntity> getParentOtherEntities() {
|
||||
if ( parentOtherEntities == null ) {
|
||||
parentOtherEntities = new LinkedHashSet();
|
||||
}
|
||||
return parentOtherEntities;
|
||||
}
|
||||
|
||||
public void setOtherEntities(Set<OtherEntity> pParentOtherEntites) {
|
||||
parentOtherEntities = pParentOtherEntites;
|
||||
}
|
||||
|
||||
public String getDept() {
|
||||
return dept;
|
||||
}
|
||||
|
||||
protected void setDept(String dept) {
|
||||
this.dept = dept;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Employee")
|
||||
@Table(name = "Employee")
|
||||
public static class Employee extends EmployeeParent {
|
||||
|
||||
@OneToMany(targetEntity = OtherEntity.class, mappedBy = "employee", fetch = FetchType.LAZY)
|
||||
protected Set<OtherEntity> otherEntities = new HashSet<>();
|
||||
|
||||
public Employee(String dept) {
|
||||
this();
|
||||
setDept( dept );
|
||||
}
|
||||
|
||||
protected Employee() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public Set<OtherEntity> getOtherEntities() {
|
||||
if ( otherEntities == null ) {
|
||||
otherEntities = new LinkedHashSet();
|
||||
}
|
||||
return otherEntities;
|
||||
}
|
||||
|
||||
public void setOtherEntities(Set<OtherEntity> pOtherEntites) {
|
||||
otherEntities = pOtherEntites;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
@Table(name = "OtherEntity")
|
||||
public static class OtherEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "Employee_Id")
|
||||
protected Employee employee = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "EmployeeParent_Id")
|
||||
protected EmployeeParent employeeParent = null;
|
||||
|
||||
protected OtherEntity() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public OtherEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.manytomany.mapkey;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.MapKey;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.RequiresDialectFeature;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-4235")
|
||||
@RequiresDialectFeature(DialectChecks.SupportSchemaCreation.class)
|
||||
public class ManyToManyWithMaykeyAndSchemaDefinitionTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
configuration.setProperty( AvailableSettings.HBM2DDL_CREATE_SCHEMAS, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { EntityA.class, EntityB.class };
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
EntityA entityA = new EntityA();
|
||||
entityA.setId( 1L );
|
||||
|
||||
EntityB entityB = new EntityB();
|
||||
entityB.setId( 1L );
|
||||
entityA.setEntityBs( "B", entityB );
|
||||
session.persist( entityB );
|
||||
session.persist( entityA );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrievingTheMapGeneratesACorrectlyQuery() {
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
EntityA entityA = session.get( EntityA.class, 1L );
|
||||
Collection<EntityB> values = entityA.getEntityBMap().values();
|
||||
assertThat( values.size(), is( 1 ) );
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Entity(name = "EntityA")
|
||||
@Table(name = "entitya", schema = "myschema")
|
||||
public static class EntityA {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@ManyToMany
|
||||
@MapKey(name = "id")
|
||||
@JoinTable(name = "entitya_entityb", schema = "myschema", joinColumns = @JoinColumn(name = "entitya_pk"), inverseJoinColumns = @JoinColumn(name = "entityb_pk"))
|
||||
private Map<String, EntityB> entityBMap = new HashMap<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setEntityBs(String key, EntityB entityB) {
|
||||
this.entityBMap.put( key, entityB );
|
||||
}
|
||||
|
||||
public Map<String, EntityB> getEntityBMap() {
|
||||
return entityBMap;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "EntityB")
|
||||
@Table(name = "entityb", schema = "myschema")
|
||||
public static class EntityB {
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue