HHH-10267 - Support defining lazy attribute fetch groups

This commit is contained in:
Steve Ebersole 2015-11-16 15:25:19 -06:00
parent 6afc759bf3
commit 1e44e7420b
69 changed files with 1310 additions and 581 deletions

View File

@ -132,8 +132,7 @@ public abstract class AbstractEntityInsertAction extends EntityAction {
LockMode.WRITE,
isExecuted,
getPersister(),
isVersionIncrementDisabled,
false
isVersionIncrementDisabled
);
}

View File

@ -0,0 +1,27 @@
/*
* 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.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* For use with bytecode-enhanced lazy-loading support.
* <p/>
* Identifies grouping for performing lazy attribute loading. By default all
* non-collection attributes are loaded in one group named {@code "DEFAULT"}.
* This annotation allows defining different groups of attributes to be
* initialized together when access one attribute in the group.
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LazyGroup {
String value();
}

View File

@ -7,6 +7,7 @@
package org.hibernate.bytecode.enhance.spi;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.engine.spi.SessionImplementor;
@ -20,7 +21,7 @@ public interface LazyPropertyInitializer {
/**
* Marker value for uninitialized properties.
*/
public static final Serializable UNFETCHED_PROPERTY = new Serializable() {
Serializable UNFETCHED_PROPERTY = new Serializable() {
@Override
public String toString() {
return "<lazy>";
@ -31,6 +32,11 @@ public interface LazyPropertyInitializer {
}
};
interface InterceptorImplementor {
Set<String> getInitializedLazyAttributeNames();
void attributeInitialized(String name);
}
/**
* Initialize the property, and return its new value.
*
@ -40,6 +46,6 @@ public interface LazyPropertyInitializer {
*
* @return ?
*/
public Object initializeLazyProperty(String fieldName, Object entity, SessionImplementor session);
Object initializeLazyProperty(String fieldName, Object entity, SessionImplementor session);
}

View File

@ -0,0 +1,102 @@
/*
* 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.bytecode.enhance.spi.interceptor;
import org.hibernate.mapping.Property;
import org.hibernate.type.Type;
/**
* Descriptor for an attribute which is enabled for bytecode lazy fetching
*
* @author Steve Ebersole
*/
public class LazyAttributeDescriptor {
public static LazyAttributeDescriptor from(
Property property,
int attributeIndex,
int lazyIndex) {
String fetchGroupName = property.getLazyGroup();
if ( fetchGroupName == null ) {
fetchGroupName = property.getType().isCollectionType()
? property.getName()
: "DEFAULT";
}
return new LazyAttributeDescriptor(
attributeIndex,
lazyIndex,
property.getName(),
property.getType(),
fetchGroupName
);
}
private final int attributeIndex;
private final int lazyIndex;
private final String name;
private final Type type;
private final String fetchGroupName;
private LazyAttributeDescriptor(
int attributeIndex,
int lazyIndex,
String name,
Type type,
String fetchGroupName) {
assert attributeIndex >= lazyIndex;
this.attributeIndex = attributeIndex;
this.lazyIndex = lazyIndex;
this.name = name;
this.type = type;
this.fetchGroupName = fetchGroupName;
}
/**
* Access to the index of the attribute in terms of its position in the entity persister
*
* @return The persister attribute index
*/
public int getAttributeIndex() {
return attributeIndex;
}
/**
* Access to the index of the attribute in terms of its position withing the lazy attributes of the persister
*
* @return The persister lazy attribute index
*/
public int getLazyIndex() {
return lazyIndex;
}
/**
* Access to the name of the attribute
*
* @return The attribute name
*/
public String getName() {
return name;
}
/**
* Access to the attribute's type
*
* @return The attribute type
*/
public Type getType() {
return type;
}
/**
* Access to the name of the fetch group to which the attribute belongs
*
* @return The name of the fetch group the attribute belongs to
*/
public String getFetchGroupName() {
return fetchGroupName;
}
}

View File

@ -9,14 +9,16 @@ package org.hibernate.bytecode.enhance.spi.interceptor;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer.InterceptorImplementor;
import org.hibernate.bytecode.enhance.spi.interceptor.Helper.Consumer;
import org.hibernate.bytecode.enhance.spi.interceptor.Helper.LazyInitializationWork;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionImplementor;
@ -29,29 +31,30 @@ import org.jboss.logging.Logger;
* Interceptor that loads attributes lazily
*
* @author Luis Barreiro
* @author Steve Ebersole
*/
public class LazyAttributeLoadingInterceptor implements PersistentAttributeInterceptor, Consumer {
public class LazyAttributeLoadingInterceptor
implements PersistentAttributeInterceptor, Consumer, InterceptorImplementor {
private static final Logger log = Logger.getLogger( LazyAttributeLoadingInterceptor.class );
private transient SessionImplementor session;
private final Set<String> lazyFields;
private final String entityName;
private final Set<String> lazyFields;
private String sessionFactoryUuid;
private Set<String> initializedLazyFields;
private transient SessionImplementor session;
private boolean allowLoadOutsideTransaction;
private String sessionFactoryUuid;
private final SimpleFieldTracker initializedFields = new SimpleFieldTracker();
public LazyAttributeLoadingInterceptor(SessionImplementor session, Set<String> lazyFields, String entityName) {
this.session = session;
this.lazyFields = lazyFields;
public LazyAttributeLoadingInterceptor(
String entityName,
Set<String> lazyFields,
SessionImplementor session) {
this.entityName = entityName;
this.lazyFields = lazyFields;
this.allowLoadOutsideTransaction = session.getFactory().getSessionFactoryOptions().isInitializeLazyStateOutsideTransactionsEnabled();
if ( this.allowLoadOutsideTransaction ) {
this.sessionFactoryUuid = session.getFactory().getUuid();
}
setSession( session );
}
protected final Object intercept(Object target, String attributeName, Object value) {
@ -77,8 +80,6 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
final Object[] loadedState = null;
// 2) does a row exist in the db for this entity?
final boolean existsInDb = true;
// NOTE2: the final boolean is 'lazyPropertiesAreUnfetched' which is another
// place where a "single lazy fetch group" shows up
session.getPersistenceContext().addEntity(
target,
Status.READ_ONLY,
@ -88,7 +89,6 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
LockMode.NONE,
existsInDb,
persister,
true,
true
);
}
@ -100,7 +100,6 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
session
);
initializedFields.add( attributeName );
takeCollectionSizeSnapshot( target, attributeName, loadedValue );
return loadedValue;
}
@ -120,6 +119,12 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
public final void setSession(SessionImplementor session) {
this.session = session;
if ( session != null && !allowLoadOutsideTransaction ) {
this.allowLoadOutsideTransaction = session.getFactory().getSessionFactoryOptions().isInitializeLazyStateOutsideTransactionsEnabled();
if ( this.allowLoadOutsideTransaction ) {
this.sessionFactoryUuid = session.getFactory().getUuid();
}
}
}
public final void unsetSession() {
@ -127,28 +132,35 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
}
public boolean isAttributeLoaded(String fieldName) {
return lazyFields == null || !lazyFields.contains( fieldName ) || initializedFields.contains( fieldName );
return !isLazyAttribute( fieldName ) || isInitializedLazyField( fieldName );
}
private boolean isLazyAttribute(String fieldName) {
return lazyFields == null || lazyFields.contains( fieldName );
}
private boolean isInitializedLazyField(String fieldName) {
return initializedLazyFields != null && initializedLazyFields.contains( fieldName );
}
public boolean hasAnyUninitializedAttributes() {
if ( lazyFields != null ) {
for ( String fieldName : lazyFields ) {
if ( !initializedFields.contains( fieldName ) ) {
return true;
}
if ( lazyFields == null ) {
return false;
}
if ( initializedLazyFields == null ) {
return true;
}
for ( String fieldName : lazyFields ) {
if ( !initializedLazyFields.contains( fieldName ) ) {
return true;
}
}
return false;
}
public void setLoaded(String attributeName) {
initializedFields.add( attributeName );
}
public String[] getiInitializedFields() {
return initializedFields.get();
}
@Override
public String toString() {
return "LazyAttributeLoader(entityName=" + entityName + " ,lazyFields=" + lazyFields + ')';
@ -174,7 +186,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -187,7 +199,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public byte writeByte(Object obj, String name, byte oldValue, byte newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -200,7 +212,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public char writeChar(Object obj, String name, char oldValue, char newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -213,7 +225,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public short writeShort(Object obj, String name, short oldValue, short newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -226,7 +238,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public int writeInt(Object obj, String name, int oldValue, int newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -239,7 +251,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public float writeFloat(Object obj, String name, float oldValue, float newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -252,7 +264,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public double writeDouble(Object obj, String name, double oldValue, double newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -265,7 +277,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public long writeLong(Object obj, String name, long oldValue, long newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -278,7 +290,7 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
@Override
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
if ( lazyFields != null && lazyFields.contains( name ) ) {
initializedFields.add( name );
attributeInitialized( name );
}
return newValue;
}
@ -297,4 +309,21 @@ public class LazyAttributeLoadingInterceptor implements PersistentAttributeInter
public String getSessionFactoryUuid() {
return sessionFactoryUuid;
}
@Override
public void attributeInitialized(String name) {
if ( !isLazyAttribute( name ) ) {
return;
}
if ( initializedLazyFields == null ) {
initializedLazyFields = new HashSet<String>();
}
initializedLazyFields.add( name );
}
@Override
public Set<String> getInitializedLazyAttributeNames() {
return initializedLazyFields == null ? Collections.<String>emptySet() : initializedLazyFields;
}
}

View File

@ -0,0 +1,141 @@
/*
* 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.bytecode.enhance.spi.interceptor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
/**
* Information about all of the bytecode lazy attributes for an entity
*
* @author Steve Ebersole
*/
public class LazyAttributesMetadata implements Serializable {
/**
* Build a LazyFetchGroupMetadata based on the attributes defined for the
* PersistentClass
*
* @param mappedEntity The entity definition
*
* @return The built LazyFetchGroupMetadata
*/
public static LazyAttributesMetadata from(PersistentClass mappedEntity) {
final Map<String, LazyAttributeDescriptor> lazyAttributeDescriptorMap = new LinkedHashMap<String, LazyAttributeDescriptor>();
final Map<String, Set<String>> fetchGroupToAttributesMap = new HashMap<String, Set<String>>();
int i = -1;
int x = 0;
final Iterator itr = mappedEntity.getPropertyClosureIterator();
while ( itr.hasNext() ) {
i++;
final Property property = (Property) itr.next();
if ( property.isLazy() ) {
final LazyAttributeDescriptor lazyAttributeDescriptor = LazyAttributeDescriptor.from( property, i, x++ );
lazyAttributeDescriptorMap.put( lazyAttributeDescriptor.getName(), lazyAttributeDescriptor );
Set<String> attributeSet = fetchGroupToAttributesMap.get( lazyAttributeDescriptor.getFetchGroupName() );
if ( attributeSet == null ) {
attributeSet = new LinkedHashSet<String>();
fetchGroupToAttributesMap.put( lazyAttributeDescriptor.getFetchGroupName(), attributeSet );
}
attributeSet.add( lazyAttributeDescriptor.getName() );
}
}
if ( lazyAttributeDescriptorMap.isEmpty() ) {
return new LazyAttributesMetadata( mappedEntity.getEntityName() );
}
for ( Map.Entry<String, Set<String>> entry : fetchGroupToAttributesMap.entrySet() ) {
entry.setValue( Collections.unmodifiableSet( entry.getValue() ) );
}
return new LazyAttributesMetadata(
mappedEntity.getEntityName(),
Collections.unmodifiableMap( lazyAttributeDescriptorMap ),
Collections.unmodifiableMap( fetchGroupToAttributesMap )
);
}
public static LazyAttributesMetadata nonEnhanced(String entityName) {
return new LazyAttributesMetadata( entityName );
}
private final String entityName;
private final Map<String, LazyAttributeDescriptor> lazyAttributeDescriptorMap;
private final Map<String,Set<String>> fetchGroupToAttributeMap;
public LazyAttributesMetadata(String entityName) {
this( entityName, Collections.<String, LazyAttributeDescriptor>emptyMap(), Collections.<String, Set<String>>emptyMap() );
}
public LazyAttributesMetadata(
String entityName,
Map<String, LazyAttributeDescriptor> lazyAttributeDescriptorMap,
Map<String, Set<String>> fetchGroupToAttributeMap) {
this.entityName = entityName;
this.lazyAttributeDescriptorMap = lazyAttributeDescriptorMap;
this.fetchGroupToAttributeMap = fetchGroupToAttributeMap;
}
public String getEntityName() {
return entityName;
}
public boolean hasLazyAttributes() {
return !lazyAttributeDescriptorMap.isEmpty();
}
public int lazyAttributeCount() {
return lazyAttributeDescriptorMap.size();
}
public Set<String> getLazyAttributeNames() {
return lazyAttributeDescriptorMap.keySet();
}
public Set<String> getFetchGroupNames() {
return fetchGroupToAttributeMap.keySet();
}
public boolean isLazyAttribute(String attributeName) {
return lazyAttributeDescriptorMap.containsKey( attributeName );
}
public String getFetchGroupName(String attributeName) {
return lazyAttributeDescriptorMap.get( attributeName ).getFetchGroupName();
}
public Set<String> getAttributesInFetchGroup(String fetchGroupName) {
return fetchGroupToAttributeMap.get( fetchGroupName );
}
public List<LazyAttributeDescriptor> getFetchGroupAttributeDescriptors(String groupName) {
final List<LazyAttributeDescriptor> list = new ArrayList<LazyAttributeDescriptor>();
for ( String attributeName : fetchGroupToAttributeMap.get( groupName ) ) {
list.add( lazyAttributeDescriptorMap.get( attributeName ) );
}
return list;
}
public Set<String> getAttributesInSameFetchGroup(String attributeName) {
final String fetchGroupName = getFetchGroupName( attributeName );
return getAttributesInFetchGroup( fetchGroupName );
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.bytecode.enhance.spi.interceptor;
/**
* Information about a particular bytecode lazy attribute grouping.
*
* @author Steve Ebersole
*/
public interface LazyFetchGroupMetadata {
/**
* Access to the name of the fetch group.
*
* @return The fetch group name
*/
String getName();
}

View File

@ -9,6 +9,7 @@ package org.hibernate.bytecode.spi;
import java.util.Set;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata;
import org.hibernate.engine.spi.SessionImplementor;
/**
@ -32,11 +33,12 @@ public interface BytecodeEnhancementMetadata {
*/
boolean isEnhancedForLazyLoading();
LazyAttributesMetadata getLazyAttributesMetadata();
/**
* Build and inject an interceptor instance into the enhanced entity.
*
* @param entity The entity into which built interceptor should be injected
* @param uninitializedFieldNames The name of fields marked as lazy
* @param session The session to which the entity instance belongs.
*
* @return The built and injected interceptor
@ -45,7 +47,6 @@ public interface BytecodeEnhancementMetadata {
*/
LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException;
/**
@ -58,4 +59,6 @@ public interface BytecodeEnhancementMetadata {
* @throws NotInstrumentedException Thrown if {@link #isEnhancedForLazyLoading()} returns {@code false}
*/
LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException;
boolean hasUnFetchedAttributes(Object entity);
}

View File

@ -20,7 +20,7 @@ public interface CacheEntry extends Serializable {
*
* @return true/false
*/
public boolean isReferenceEntry();
boolean isReferenceEntry();
/**
* Hibernate stores all entries pertaining to a given entity hierarchy in a single region. This attribute
@ -28,21 +28,14 @@ public interface CacheEntry extends Serializable {
*
* @return The entry's exact entity type.
*/
public String getSubclass();
String getSubclass();
/**
* Retrieves the version (optimistic locking) associated with this cache entry.
*
* @return The version of the entity represented by this entry
*/
public Object getVersion();
/**
* Does the represented data contain any un-fetched attribute values?
*
* @return true/false
*/
public boolean areLazyPropertiesUnfetched();
Object getVersion();
/**
* Get the underlying disassembled state
@ -53,6 +46,5 @@ public interface CacheEntry extends Serializable {
*
* @return The disassembled state
*/
public Serializable[] getDisassembledState();
Serializable[] getDisassembledState();
}

View File

@ -60,12 +60,6 @@ public class ReferenceCacheEntryImpl implements CacheEntry {
return null;
}
@Override
public boolean areLazyPropertiesUnfetched() {
// reference data cannot define lazy attributes
return false;
}
@Override
public Serializable[] getDisassembledState() {
// reference data is not disassembled into the cache

View File

@ -7,6 +7,7 @@
package org.hibernate.cache.spi.entry;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
@ -19,6 +20,7 @@ import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.TypeHelper;
@ -30,7 +32,6 @@ import org.hibernate.type.TypeHelper;
public class StandardCacheEntryImpl implements CacheEntry {
private final Serializable[] disassembledState;
private final String subclass;
private final boolean lazyPropertiesAreUnfetched;
private final Object version;
/**
@ -38,7 +39,6 @@ public class StandardCacheEntryImpl implements CacheEntry {
*
* @param state The extracted state
* @param persister The entity persister
* @param unfetched Are any values present in state unfetched?
* @param version The current version (if versioned)
* @param session The originating session
* @param owner The owner
@ -48,11 +48,9 @@ public class StandardCacheEntryImpl implements CacheEntry {
public StandardCacheEntryImpl(
final Object[] state,
final EntityPersister persister,
final boolean unfetched,
final Object version,
final SessionImplementor session,
final Object owner)
throws HibernateException {
final Object owner) throws HibernateException {
// disassembled state gets put in a new array (we write to cache by value!)
this.disassembledState = TypeHelper.disassemble(
state,
@ -62,14 +60,12 @@ public class StandardCacheEntryImpl implements CacheEntry {
owner
);
subclass = persister.getEntityName();
lazyPropertiesAreUnfetched = unfetched || !persister.isLazyPropertiesCacheable();
this.version = version;
}
StandardCacheEntryImpl(Serializable[] state, String subclass, boolean unfetched, Object version) {
StandardCacheEntryImpl(Serializable[] state, String subclass, Object version) {
this.disassembledState = state;
this.subclass = subclass;
this.lazyPropertiesAreUnfetched = unfetched;
this.version = version;
}
@ -93,11 +89,6 @@ public class StandardCacheEntryImpl implements CacheEntry {
return subclass;
}
@Override
public boolean areLazyPropertiesUnfetched() {
return lazyPropertiesAreUnfetched;
}
@Override
public Object getVersion() {
return version;

View File

@ -9,6 +9,7 @@ package org.hibernate.cache.spi.entry;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
@ -21,6 +22,9 @@ import org.hibernate.persister.entity.EntityPersister;
* @author Steve Ebersole
*/
public class StructuredCacheEntry implements CacheEntryStructure {
public static final String SUBCLASS_KEY = "_subclass";
public static final String VERSION_KEY = "_version";
private EntityPersister persister;
/**
@ -33,18 +37,18 @@ public class StructuredCacheEntry implements CacheEntryStructure {
}
@Override
@SuppressWarnings("unchecked")
public Object destructure(Object structured, SessionFactoryImplementor factory) {
final Map map = (Map) structured;
final boolean lazyPropertiesUnfetched = (Boolean) map.get( "_lazyPropertiesUnfetched" );
final String subclass = (String) map.get( "_subclass" );
final Object version = map.get( "_version" );
final String subclass = (String) map.get( SUBCLASS_KEY );
final Object version = map.get( VERSION_KEY );
final EntityPersister subclassPersister = factory.getEntityPersister( subclass );
final String[] names = subclassPersister.getPropertyNames();
final Serializable[] state = new Serializable[names.length];
for ( int i = 0; i < names.length; i++ ) {
state[i] = (Serializable) map.get( names[i] );
}
return new StandardCacheEntryImpl( state, subclass, lazyPropertiesUnfetched, version );
return new StandardCacheEntryImpl( state, subclass, version );
}
@Override
@ -53,9 +57,8 @@ public class StructuredCacheEntry implements CacheEntryStructure {
final CacheEntry entry = (CacheEntry) item;
final String[] names = persister.getPropertyNames();
final Map map = new HashMap( names.length + 3, 1f );
map.put( "_subclass", entry.getSubclass() );
map.put( "_version", entry.getVersion() );
map.put( "_lazyPropertiesUnfetched", entry.areLazyPropertiesUnfetched() );
map.put( SUBCLASS_KEY, entry.getSubclass() );
map.put( VERSION_KEY, entry.getVersion() );
for ( int i=0; i<names.length; i++ ) {
map.put( names[i], entry.getDisassembledState()[i] );
}

View File

@ -97,6 +97,7 @@ import org.hibernate.annotations.Formula;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.GenericGenerators;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.LazyGroup;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.annotations.ListIndexBase;
@ -1666,6 +1667,11 @@ public final class AnnotationBinder {
|| property.isAnnotationPresent( EmbeddedId.class ) );
propertyBinder.setId( isId );
final LazyGroup lazyGroupAnnotation = property.getAnnotation( LazyGroup.class );
if ( lazyGroupAnnotation != null ) {
propertyBinder.setLazyGroup( lazyGroupAnnotation.value() );
}
if ( property.isAnnotationPresent( Version.class ) ) {
if ( isIdentifierMapper ) {
throw new AnnotationException(

View File

@ -44,6 +44,7 @@ import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.LazyGroup;
import org.hibernate.annotations.Loader;
import org.hibernate.annotations.ManyToAny;
import org.hibernate.annotations.OptimisticLock;
@ -525,6 +526,10 @@ public abstract class CollectionBinder {
collection.setOrphanDelete( true );
}
binder.setLazy( collection.isLazy() );
final LazyGroup lazyGroupAnnotation = property.getAnnotation( LazyGroup.class );
if ( lazyGroupAnnotation != null ) {
binder.setLazyGroup( lazyGroupAnnotation.value() );
}
binder.setAccessType( accessType );
binder.setProperty( property );
binder.setInsertable( insertable );

View File

@ -58,6 +58,7 @@ public class PropertyBinder {
private String name;
private String returnedClassName;
private boolean lazy;
private String lazyGroup;
private AccessType accessType;
private Ejb3Column[] columns;
private PropertyHolder holder;
@ -115,6 +116,10 @@ public class PropertyBinder {
this.lazy = lazy;
}
public void setLazyGroup(String lazyGroup) {
this.lazyGroup = lazyGroup;
}
public void setAccessType(AccessType accessType) {
this.accessType = accessType;
}
@ -262,6 +267,7 @@ public class PropertyBinder {
prop.setName( name );
prop.setValue( value );
prop.setLazy( lazy );
prop.setLazyGroup( lazyGroup );
prop.setCascade( cascade );
prop.setPropertyAccessorName( accessType.getType() );

View File

@ -90,10 +90,10 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
final EntityMode entityMode,
final String tenantId,
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched,
final PersistenceContext persistenceContext) {
this( status, loadedState, rowId, id, version, lockMode, existsInDatabase,
persister,disableVersionIncrement, lazyPropertiesAreUnfetched, persistenceContext );
persister,disableVersionIncrement, persistenceContext
);
}
public AbstractEntityEntry(
@ -106,7 +106,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched,
final PersistenceContext persistenceContext) {
setCompressedValue( EnumState.STATUS, status );
// not useful strictly speaking but more explicit
@ -121,7 +120,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
this.version=version;
setCompressedValue( EnumState.LOCK_MODE, lockMode );
setCompressedValue( BooleanState.IS_BEING_REPLICATED, disableVersionIncrement );
setCompressedValue( BooleanState.LOADED_WITH_LAZY_PROPERTIES_UNFETCHED, lazyPropertiesAreUnfetched );
this.persister=persister;
this.persistenceContext = persistenceContext;
}
@ -142,7 +140,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
final LockMode lockMode,
final boolean existsInDatabase,
final boolean isBeingReplicated,
final boolean loadedWithLazyPropertiesUnfetched,
final PersistenceContext persistenceContext) {
this.persister = ( factory == null ? null : factory.getEntityPersister( entityName ) );
this.id = id;
@ -154,7 +151,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
setCompressedValue( EnumState.LOCK_MODE, lockMode );
setCompressedValue( BooleanState.EXISTS_IN_DATABASE, existsInDatabase );
setCompressedValue( BooleanState.IS_BEING_REPLICATED, isBeingReplicated );
setCompressedValue( BooleanState.LOADED_WITH_LAZY_PROPERTIES_UNFETCHED, loadedWithLazyPropertiesUnfetched );
this.rowId = null; // this is equivalent to the old behavior...
this.persistenceContext = persistenceContext;
}
@ -410,11 +406,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
'(' + getStatus() + ')';
}
@Override
public boolean isLoadedWithLazyPropertiesUnfetched() {
return getCompressedValue( BooleanState.LOADED_WITH_LAZY_PROPERTIES_UNFETCHED );
}
@Override
public void serialize(ObjectOutputStream oos) throws IOException {
final Status previousStatus = getPreviousStatus();
@ -429,7 +420,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
oos.writeObject( getLockMode().toString() );
oos.writeBoolean( isExistsInDatabase() );
oos.writeBoolean( isBeingReplicated() );
oos.writeBoolean( isLoadedWithLazyPropertiesUnfetched() );
}
@ -593,8 +583,7 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
protected enum BooleanState {
EXISTS_IN_DATABASE(13),
IS_BEING_REPLICATED(14),
LOADED_WITH_LAZY_PROPERTIES_UNFETCHED(15);
IS_BEING_REPLICATED(14);
private final int offset;
private final int mask;

View File

@ -50,7 +50,6 @@ public final class ImmutableEntityEntry extends AbstractEntityEntry {
final EntityMode entityMode,
final String tenantId,
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched,
final PersistenceContext persistenceContext) {
this(
status,
@ -62,7 +61,6 @@ public final class ImmutableEntityEntry extends AbstractEntityEntry {
existsInDatabase,
persister,
disableVersionIncrement,
lazyPropertiesAreUnfetched,
// purposefully do not pass along the session/persistence-context : HHH-10251
null
);
@ -78,7 +76,6 @@ public final class ImmutableEntityEntry extends AbstractEntityEntry {
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched,
final PersistenceContext persistenceContext) {
super(
@ -91,7 +88,6 @@ public final class ImmutableEntityEntry extends AbstractEntityEntry {
existsInDatabase,
persister,
disableVersionIncrement,
lazyPropertiesAreUnfetched,
// purposefully do not pass along the session/persistence-context : HHH-10251
null
);
@ -113,12 +109,11 @@ public final class ImmutableEntityEntry extends AbstractEntityEntry {
final LockMode lockMode,
final boolean existsInDatabase,
final boolean isBeingReplicated,
final boolean loadedWithLazyPropertiesUnfetched,
final PersistenceContext persistenceContext) {
super( factory, entityName, id, status, previousStatus, loadedState, deletedState,
version, lockMode, existsInDatabase, isBeingReplicated, loadedWithLazyPropertiesUnfetched,
persistenceContext );
version, lockMode, existsInDatabase, isBeingReplicated, persistenceContext
);
}
@Override
@ -166,7 +161,6 @@ public final class ImmutableEntityEntry extends AbstractEntityEntry {
LockMode.valueOf( (String) ois.readObject() ),
ois.readBoolean(),
ois.readBoolean(),
ois.readBoolean(),
null
);
}

View File

@ -8,6 +8,7 @@
package org.hibernate.engine.internal;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.EntityEntry;
@ -43,7 +44,6 @@ public class ImmutableEntityEntryFactory implements EntityEntryFactory {
boolean existsInDatabase,
EntityPersister persister,
boolean disableVersionIncrement,
boolean lazyPropertiesAreUnfetched,
PersistenceContext persistenceContext) {
return new ImmutableEntityEntry(
status,
@ -55,7 +55,6 @@ public class ImmutableEntityEntryFactory implements EntityEntryFactory {
existsInDatabase,
persister,
disableVersionIncrement,
lazyPropertiesAreUnfetched,
persistenceContext
);
}

View File

@ -27,7 +27,6 @@ import org.hibernate.persister.entity.EntityPersister;
* @author Sanne Grinovero <sanne@hibernate.org>
*/
public final class MutableEntityEntry extends AbstractEntityEntry {
/**
* @deprecated the tenantId and entityMode parameters where removed: this constructor accepts but ignores them.
* Use the other constructor!
@ -45,10 +44,10 @@ public final class MutableEntityEntry extends AbstractEntityEntry {
final EntityMode entityMode,
final String tenantId,
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched,
final PersistenceContext persistenceContext) {
this( status, loadedState, rowId, id, version, lockMode, existsInDatabase,
persister,disableVersionIncrement, lazyPropertiesAreUnfetched, persistenceContext );
persister,disableVersionIncrement, persistenceContext
);
}
public MutableEntityEntry(
@ -61,11 +60,10 @@ public final class MutableEntityEntry extends AbstractEntityEntry {
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched,
final PersistenceContext persistenceContext) {
super( status, loadedState, rowId, id, version, lockMode, existsInDatabase, persister,
disableVersionIncrement, lazyPropertiesAreUnfetched, persistenceContext );
disableVersionIncrement, persistenceContext
);
}
/**
@ -84,15 +82,12 @@ public final class MutableEntityEntry extends AbstractEntityEntry {
final LockMode lockMode,
final boolean existsInDatabase,
final boolean isBeingReplicated,
final boolean loadedWithLazyPropertiesUnfetched,
final PersistenceContext persistenceContext) {
super( factory, entityName, id, status, previousStatus, loadedState, deletedState,
version, lockMode, existsInDatabase, isBeingReplicated, loadedWithLazyPropertiesUnfetched,
persistenceContext );
version, lockMode, existsInDatabase, isBeingReplicated, persistenceContext
);
}
/**
* Custom deserialization routine used during deserialization of a
* Session/PersistenceContext for increased performance.
@ -124,7 +119,6 @@ public final class MutableEntityEntry extends AbstractEntityEntry {
LockMode.valueOf( (String) ois.readObject() ),
ois.readBoolean(),
ois.readBoolean(),
ois.readBoolean(),
persistenceContext
);
}

View File

@ -8,6 +8,7 @@
package org.hibernate.engine.internal;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.EntityEntry;
@ -43,7 +44,6 @@ public class MutableEntityEntryFactory implements EntityEntryFactory {
boolean existsInDatabase,
EntityPersister persister,
boolean disableVersionIncrement,
boolean lazyPropertiesAreUnfetched,
PersistenceContext persistenceContext) {
return new MutableEntityEntry(
status,
@ -55,7 +55,6 @@ public class MutableEntityEntryFactory implements EntityEntryFactory {
existsInDatabase,
persister,
disableVersionIncrement,
lazyPropertiesAreUnfetched,
persistenceContext
);
}

View File

@ -455,8 +455,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
final LockMode lockMode,
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
boolean lazyPropertiesAreUnfetched) {
final boolean disableVersionIncrement) {
addEntity( entityKey, entity );
return addEntry(
entity,
@ -468,8 +467,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
lockMode,
existsInDatabase,
persister,
disableVersionIncrement,
lazyPropertiesAreUnfetched
disableVersionIncrement
);
}
@ -484,9 +482,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
final LockMode lockMode,
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
boolean lazyPropertiesAreUnfetched) {
final boolean disableVersionIncrement) {
final EntityEntry e;
if( (entity instanceof ManagedEntity) && ((ManagedEntity) entity).$$_hibernate_getEntityEntry() != null && status == Status.READ_ONLY) {
@ -505,7 +501,6 @@ public class StatefulPersistenceContext implements PersistenceContext {
existsInDatabase,
persister,
disableVersionIncrement,
lazyPropertiesAreUnfetched,
this
);
}
@ -1382,8 +1377,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
oldEntry.getLockMode(),
oldEntry.isExistsInDatabase(),
oldEntry.getPersister(),
oldEntry.isBeingReplicated(),
oldEntry.isLoadedWithLazyPropertiesUnfetched()
oldEntry.isBeingReplicated()
);
}

View File

@ -67,7 +67,6 @@ public final class TwoPhaseLoad {
* @param rowId The rowId for the entity
* @param object An optional instance for the entity being loaded
* @param lockMode The lock mode
* @param lazyPropertiesAreUnFetched Whether properties defined as lazy are yet un-fetched
* @param session The Session
*/
public static void postHydrate(
@ -77,7 +76,6 @@ public final class TwoPhaseLoad {
final Object rowId,
final Object object,
final LockMode lockMode,
final boolean lazyPropertiesAreUnFetched,
final SessionImplementor session) {
final Object version = Versioning.getVersion( values, persister );
session.getPersistenceContext().addEntry(
@ -90,8 +88,7 @@ public final class TwoPhaseLoad {
lockMode,
true,
persister,
false,
lazyPropertiesAreUnFetched
false
);
if ( version != null && LOG.isTraceEnabled() ) {
@ -264,11 +261,7 @@ public final class TwoPhaseLoad {
persistenceContext.setEntryStatus( entityEntry, Status.MANAGED );
}
persister.afterInitialize(
entity,
entityEntry.isLoadedWithLazyPropertiesUnfetched(),
session
);
persister.afterInitialize( entity, session );
if ( debugEnabled ) {
LOG.debugf(
@ -317,11 +310,13 @@ public final class TwoPhaseLoad {
}
private static boolean useMinimalPuts(SessionImplementor session, EntityEntry entityEntry) {
return ( session.getFactory().getSettings().isMinimalPutsEnabled()
&& session.getCacheMode()!=CacheMode.REFRESH )
|| ( entityEntry.getPersister().hasLazyProperties()
&& entityEntry.isLoadedWithLazyPropertiesUnfetched()
&& entityEntry.getPersister().isLazyPropertiesCacheable() );
if ( session.getFactory().getSessionFactoryOptions().isMinimalPutsEnabled() ) {
return session.getCacheMode() != CacheMode.REFRESH;
}
else {
return entityEntry.getPersister().hasLazyProperties()
&& entityEntry.getPersister().isLazyPropertiesCacheable();
}
}
/**
@ -335,7 +330,6 @@ public final class TwoPhaseLoad {
* @param object The entity instance
* @param persister The entity persister
* @param lockMode The lock mode
* @param lazyPropertiesAreUnFetched Are lazy properties still un-fetched?
* @param session The Session
*/
public static void addUninitializedEntity(
@ -343,7 +337,6 @@ public final class TwoPhaseLoad {
final Object object,
final EntityPersister persister,
final LockMode lockMode,
final boolean lazyPropertiesAreUnFetched,
final SessionImplementor session) {
session.getPersistenceContext().addEntity(
object,
@ -354,8 +347,7 @@ public final class TwoPhaseLoad {
lockMode,
true,
persister,
false,
lazyPropertiesAreUnFetched
false
);
}
@ -366,7 +358,6 @@ public final class TwoPhaseLoad {
* @param object The entity instance
* @param persister The entity persister
* @param lockMode The lock mode
* @param lazyPropertiesAreUnFetched Are lazy properties still un-fetched?
* @param version The version
* @param session The Session
*/
@ -375,7 +366,6 @@ public final class TwoPhaseLoad {
final Object object,
final EntityPersister persister,
final LockMode lockMode,
final boolean lazyPropertiesAreUnFetched,
final Object version,
final SessionImplementor session) {
session.getPersistenceContext().addEntity(
@ -387,8 +377,7 @@ public final class TwoPhaseLoad {
lockMode,
true,
persister,
false,
lazyPropertiesAreUnFetched
);
false
);
}
}

View File

@ -9,6 +9,7 @@ package org.hibernate.engine.spi;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.persister.entity.EntityPersister;
@ -124,8 +125,6 @@ public interface EntityEntry {
@Override
String toString();
boolean isLoadedWithLazyPropertiesUnfetched();
/**
* Custom serialization routine used during serialization of a
* Session/PersistenceContext for increased performance.

View File

@ -31,6 +31,5 @@ public interface EntityEntryFactory extends Serializable {
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
final boolean lazyPropertiesAreUnfetched,
final PersistenceContext persistenceContext);
}

View File

@ -10,6 +10,7 @@ import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
@ -235,7 +236,7 @@ public interface PersistenceContext {
/**
* Adds an entity to the internal caches.
*/
public EntityEntry addEntity(
EntityEntry addEntity(
final Object entity,
final Status status,
final Object[] loadedState,
@ -244,8 +245,7 @@ public interface PersistenceContext {
final LockMode lockMode,
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
boolean lazyPropertiesAreUnfetched);
final boolean disableVersionIncrement);
/**
* Generates an appropriate EntityEntry instance and adds it
@ -261,8 +261,7 @@ public interface PersistenceContext {
final LockMode lockMode,
final boolean existsInDatabase,
final EntityPersister persister,
final boolean disableVersionIncrement,
boolean lazyPropertiesAreUnfetched);
final boolean disableVersionIncrement);
/**
* Is the given collection associated with this persistence context?

View File

@ -6,10 +6,12 @@
*/
package org.hibernate.engine.spi;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer.InterceptorImplementor;
/**
* @author Steve Ebersole
*/
public interface PersistentAttributeInterceptor {
public interface PersistentAttributeInterceptor extends InterceptorImplementor {
public boolean readBoolean(Object obj, String name, boolean oldValue);

View File

@ -76,8 +76,7 @@ public abstract class AbstractReassociateEventListener implements Serializable {
LockMode.NONE,
true,
persister,
false,
true //will be ignored, using the existing Entry instead
false
);
new OnLockVisitor( source, id, object ).process( object, persister );

View File

@ -23,6 +23,7 @@ import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityEntryExtraState;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.spi.EventSource;
@ -96,6 +97,10 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
EntityPersister persister = source.getEntityPersister( entityName, entity );
Serializable generatedId = persister.getIdentifierGenerator().generate( source, entity );
if ( generatedId == null ) {
@ -241,7 +246,6 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
LockMode.WRITE,
useIdentityColumn,
persister,
false,
false
);

View File

@ -113,7 +113,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener {
LockMode.NONE,
true,
persister,
false,
false
);
}

View File

@ -675,7 +675,6 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
entity,
subclassPersister,
LockMode.NONE,
entry.areLazyPropertiesUnfetched(),
entry.getVersion(),
session
);
@ -728,10 +727,9 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
LockMode.NONE,
true,
subclassPersister,
false,
entry.areLazyPropertiesUnfetched()
false
);
subclassPersister.afterInitialize( entity, entry.areLazyPropertiesUnfetched(), session );
subclassPersister.afterInitialize( entity, session );
persistenceContext.initializeNonLazyCollections();
//PostLoad is needed for EJB3
@ -775,7 +773,6 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
result,
subclassPersister,
LockMode.NONE,
entry.areLazyPropertiesUnfetched(),
entry.getVersion(),
session
);
@ -822,10 +819,9 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
LockMode.NONE,
true,
subclassPersister,
false,
entry.areLazyPropertiesUnfetched()
false
);
subclassPersister.afterInitialize( result, entry.areLazyPropertiesUnfetched(), session );
subclassPersister.afterInitialize( result, session );
persistenceContext.initializeNonLazyCollections();
// upgrade the lock if necessary:
//lock(result, lockMode);

View File

@ -191,8 +191,7 @@ public class DefaultReplicateEventListener extends AbstractSaveEventListener imp
LockMode.NONE,
true,
persister,
true,
false
true
);
cascadeAfterReplicate( entity, persister, replicationMode, source );

View File

@ -313,8 +313,7 @@ public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener
LockMode.NONE,
true,
persister,
false,
true // assume true, since we don't really know, and it doesn't matter
false
);
persister.afterReassociate( entity, source );

View File

@ -1697,8 +1697,9 @@ public abstract class Loader {
final Loadable persister = (Loadable) getFactory().getEntityPersister( instanceEntityName );
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Initializing object from ResultSet: {0}", MessageHelper.infoString(
LOG.tracef(
"Initializing object from ResultSet: %s",
MessageHelper.infoString(
persister,
id,
getFactory()
@ -1706,7 +1707,7 @@ public abstract class Loader {
);
}
boolean eagerPropertyFetch = isEagerPropertyFetchEnabled( i );
boolean fetchAllPropertiesRequested = isEagerPropertyFetchEnabled( i );
// add temp entry so that the next step is circular-reference
// safe - only needed because some types don't take proper
@ -1716,7 +1717,6 @@ public abstract class Loader {
object,
persister,
lockMode,
!eagerPropertyFetch,
session
);
@ -1731,7 +1731,7 @@ public abstract class Loader {
object,
rootPersister,
cols,
eagerPropertyFetch,
fetchAllPropertiesRequested,
session
);
@ -1768,7 +1768,6 @@ public abstract class Loader {
rowId,
object,
lockMode,
!eagerPropertyFetch,
session
);

View File

@ -296,7 +296,6 @@ public class EntityReferenceInitializerImpl implements EntityReferenceInitialize
entityInstance,
concreteEntityPersister,
lockModeToAcquire,
!context.getLoadPlan().areLazyAttributesForceFetched(),
context.getSession()
);
@ -373,7 +372,6 @@ public class EntityReferenceInitializerImpl implements EntityReferenceInitialize
rowId,
entityInstance,
lockModeToAcquire,
!context.getLoadPlan().areLazyAttributesForceFetched(),
context.getSession()
);

View File

@ -43,6 +43,7 @@ public class Property implements Serializable, MetaAttributable {
private ValueGeneration valueGenerationStrategy;
private String propertyAccessorName;
private boolean lazy;
private String lazyGroup;
private boolean optional;
private java.util.Map metaAttributes;
private PersistentClass persistentClass;
@ -257,7 +258,15 @@ public class Property implements Serializable, MetaAttributable {
}
return lazy;
}
public String getLazyGroup() {
return lazyGroup;
}
public void setLazyGroup(String lazyGroup) {
this.lazyGroup = lazyGroup;
}
public boolean isOptimisticLocked() {
return optimisticLocked;
}

View File

@ -33,8 +33,10 @@ import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.StaleStateException;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeDescriptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
@ -65,6 +67,7 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.PersistenceContext.NaturalIdHelper;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.ValueInclusion;
@ -160,8 +163,6 @@ public abstract class AbstractEntityPersister
private final boolean hasSubselectLoadableCollections;
protected final String rowIdName;
private final Set lazyProperties;
// The optional SQL string defined in the where attribute
private final String sqlWhereString;
private final String sqlWhereStringTemplate;
@ -227,7 +228,7 @@ public abstract class AbstractEntityPersister
// SQL strings
private String sqlVersionSelectString;
private String sqlSnapshotSelectString;
private String sqlLazySelectString;
private Map<String,String> sqlLazySelectStringsByFetchGroup;
private String sqlIdentityInsertString;
private String sqlUpdateByRowIdString;
@ -379,8 +380,8 @@ public abstract class AbstractEntityPersister
return sqlSnapshotSelectString;
}
protected String getSQLLazySelectString() {
return sqlLazySelectString;
protected String getSQLLazySelectString(String fetchGroup) {
return sqlLazySelectStringsByFetchGroup.get( fetchGroup );
}
protected String[] getSQLDeleteStrings() {
@ -590,7 +591,6 @@ public abstract class AbstractEntityPersister
propertyColumnInsertable = new boolean[hydrateSpan][];
HashSet thisClassProperties = new HashSet();
lazyProperties = new HashSet();
ArrayList lazyNames = new ArrayList();
ArrayList lazyNumbers = new ArrayList();
ArrayList lazyTypes = new ArrayList();
@ -635,7 +635,6 @@ public abstract class AbstractEntityPersister
propertyColumnAliases[i] = colAliases;
if ( lazyAvailable && prop.isLazy() ) {
lazyProperties.add( prop.getName() );
lazyNames.add( prop.getName() );
lazyNumbers.add( i );
lazyTypes.add( prop.getValue().getType() );
@ -844,54 +843,68 @@ public abstract class AbstractEntityPersister
Template.renderWhereStringTemplate( string, factory.getDialect(), factory.getSqlFunctionRegistry() );
}
protected String generateLazySelectString() {
if ( !entityMetamodel.hasLazyProperties() ) {
return null;
protected Map<String,String> generateLazySelectStringsByFetchGroup() {
final BytecodeEnhancementMetadata enhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata();
if ( !enhancementMetadata.isEnhancedForLazyLoading()
|| !enhancementMetadata.getLazyAttributesMetadata().hasLazyAttributes() ) {
return Collections.emptyMap();
}
HashSet tableNumbers = new HashSet();
ArrayList columnNumbers = new ArrayList();
ArrayList formulaNumbers = new ArrayList();
for ( String lazyPropertyName : lazyPropertyNames ) {
// all this only really needs to consider properties
// of this class, not its subclasses, but since we
// are reusing code used for sequential selects, we
// use the subclass closure
int propertyNumber = getSubclassPropertyIndex( lazyPropertyName );
Map<String,String> result = new HashMap<String, String>();
int tableNumber = getSubclassPropertyTableNumber( propertyNumber );
tableNumbers.add( tableNumber );
final LazyAttributesMetadata lazyAttributesMetadata = enhancementMetadata.getLazyAttributesMetadata();
for ( String groupName : lazyAttributesMetadata.getFetchGroupNames() ) {
HashSet tableNumbers = new HashSet();
ArrayList columnNumbers = new ArrayList();
ArrayList formulaNumbers = new ArrayList();
int[] colNumbers = subclassPropertyColumnNumberClosure[propertyNumber];
for ( int colNumber : colNumbers ) {
if ( colNumber != -1 ) {
columnNumbers.add( colNumber );
for ( LazyAttributeDescriptor lazyAttributeDescriptor :
lazyAttributesMetadata.getFetchGroupAttributeDescriptors( groupName ) ) {
// all this only really needs to consider properties
// of this class, not its subclasses, but since we
// are reusing code used for sequential selects, we
// use the subclass closure
int propertyNumber = getSubclassPropertyIndex( lazyAttributeDescriptor.getName() );
int tableNumber = getSubclassPropertyTableNumber( propertyNumber );
tableNumbers.add( tableNumber );
int[] colNumbers = subclassPropertyColumnNumberClosure[propertyNumber];
for ( int colNumber : colNumbers ) {
if ( colNumber != -1 ) {
columnNumbers.add( colNumber );
}
}
int[] formNumbers = subclassPropertyFormulaNumberClosure[propertyNumber];
for ( int formNumber : formNumbers ) {
if ( formNumber != -1 ) {
formulaNumbers.add( formNumber );
}
}
}
int[] formNumbers = subclassPropertyFormulaNumberClosure[propertyNumber];
for ( int formNumber : formNumbers ) {
if ( formNumber != -1 ) {
formulaNumbers.add( formNumber );
}
if ( columnNumbers.size() == 0 && formulaNumbers.size() == 0 ) {
// only one-to-one is lazy fetched
continue;
}
result.put(
groupName,
renderSelect(
ArrayHelper.toIntArray( tableNumbers ),
ArrayHelper.toIntArray( columnNumbers ),
ArrayHelper.toIntArray( formulaNumbers )
)
);
}
if ( columnNumbers.size() == 0 && formulaNumbers.size() == 0 ) {
// only one-to-one is lazy fetched
return null;
}
return renderSelect(
ArrayHelper.toIntArray( tableNumbers ),
ArrayHelper.toIntArray( columnNumbers ),
ArrayHelper.toIntArray( formulaNumbers )
);
return result;
}
public Object initializeLazyProperty(String fieldName, Object entity, SessionImplementor session) {
final EntityEntry entry = session.getPersistenceContext().getEntry( entity );
final InterceptorImplementor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
assert interceptor != null : "Expecting bytecode interceptor to be non-null";
if ( hasCollections() ) {
final Type type = getPropertyType( fieldName );
@ -919,6 +932,7 @@ public abstract class AbstractEntityPersister
// Initialize it
session.initializeCollection( collection, false );
interceptor.attributeInitialized( fieldName );
if ( collectionType.isArrayType() ) {
session.getPersistenceContext().addCollectionHolder( collection );
@ -944,16 +958,17 @@ public abstract class AbstractEntityPersister
);
}
if ( session.getCacheMode().isGetEnabled() && hasCache() ) {
if ( session.getCacheMode().isGetEnabled() && hasCache() && isLazyPropertiesCacheable() ) {
final EntityRegionAccessStrategy cache = getCacheAccessStrategy();
final Object cacheKey = cache.generateCacheKey(id, this, session.getFactory(), session.getTenantIdentifier() );
final Object ce = CacheHelper.fromSharedCache( session, cacheKey, cache );
if ( ce != null ) {
final CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure( ce, factory );
if ( !cacheEntry.areLazyPropertiesUnfetched() ) {
//note early exit here:
return initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry );
}
final Object initializedValue = initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry );
interceptor.attributeInitialized( fieldName );
// NOTE EARLY EXIT!!!
return initializedValue;
}
}
@ -993,14 +1008,26 @@ public abstract class AbstractEntityPersister
throw new AssertionFailure( "no lazy properties" );
}
final InterceptorImplementor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
assert interceptor != null : "Expecting bytecode interceptor to be non-null";
LOG.trace( "Initializing lazy properties from datastore" );
try {
final String fetchGroup = getEntityMetamodel().getBytecodeEnhancementMetadata()
.getLazyAttributesMetadata()
.getFetchGroupName( fieldName );
final List<LazyAttributeDescriptor> fetchGroupAttributeDescriptors = getEntityMetamodel().getBytecodeEnhancementMetadata()
.getLazyAttributesMetadata()
.getFetchGroupAttributeDescriptors( fetchGroup );
final Set<String> initializedLazyAttributeNames = interceptor.getInitializedLazyAttributeNames();
final String lazySelect = getSQLLazySelectString( fetchGroup );
try {
Object result = null;
PreparedStatement ps = null;
try {
final String lazySelect = getSQLLazySelectString();
ResultSet rs = null;
try {
if ( lazySelect != null ) {
@ -1015,16 +1042,31 @@ public abstract class AbstractEntityPersister
rs.next();
}
final Object[] snapshot = entry.getLoadedState();
for ( int j = 0; j < lazyPropertyNames.length; j++ ) {
Object propValue = lazyPropertyTypes[j].nullSafeGet(
for ( LazyAttributeDescriptor fetchGroupAttributeDescriptor : fetchGroupAttributeDescriptors ) {
final boolean previousInitialized = initializedLazyAttributeNames.contains( fetchGroupAttributeDescriptor.getName() );
final Object loadedValue = fetchGroupAttributeDescriptor.getType().nullSafeGet(
rs,
lazyPropertyColumnAliases[j],
lazyPropertyColumnAliases[fetchGroupAttributeDescriptor.getLazyIndex()],
session,
entity
);
if ( initializeLazyProperty( fieldName, entity, session, snapshot, j, propValue ) ) {
result = propValue;
final boolean set = initializeLazyProperty(
fieldName,
entity,
session,
snapshot,
fetchGroupAttributeDescriptor.getLazyIndex(),
loadedValue
);
if ( previousInitialized ) {
// its already been initialized (e.g. by a write) so we don't want to overwrite
continue;
}
if ( set ) {
result = loadedValue;
interceptor.attributeInitialized( fetchGroupAttributeDescriptor.getName() );
}
}
}
finally {
@ -1048,9 +1090,8 @@ public abstract class AbstractEntityPersister
catch (SQLException sqle) {
throw getFactory().getSQLExceptionHelper().convert(
sqle,
"could not initialize lazy properties: " +
MessageHelper.infoString( this, id, getFactory() ),
getSQLLazySelectString()
"could not initialize lazy properties: " + MessageHelper.infoString( this, id, getFactory() ),
lazySelect
);
}
}
@ -1060,8 +1101,7 @@ public abstract class AbstractEntityPersister
final Object entity,
final SessionImplementor session,
final EntityEntry entry,
final CacheEntry cacheEntry
) {
final CacheEntry cacheEntry) {
LOG.trace( "Initializing lazy properties from second-level cache" );
@ -1109,10 +1149,6 @@ public abstract class AbstractEntityPersister
return getPropertySpaces();
}
protected Set getLazyProperties() {
return lazyProperties;
}
public boolean isBatchLoadable() {
return batchSize > 1;
}
@ -3475,8 +3511,8 @@ public abstract class AbstractEntityPersister
protected void logStaticSQL() {
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Static SQL for entity: %s", getEntityName() );
if ( sqlLazySelectString != null ) {
LOG.debugf( " Lazy select: %s", sqlLazySelectString );
for ( Map.Entry<String, String> entry : sqlLazySelectStringsByFetchGroup.entrySet() ) {
LOG.debugf( " Lazy select (%s) : %s", entry.getKey(), entry.getValue() );
}
if ( sqlVersionSelectString != null ) {
LOG.debugf( " Version select: %s", sqlVersionSelectString );
@ -3815,7 +3851,7 @@ public abstract class AbstractEntityPersister
//select SQL
sqlSnapshotSelectString = generateSnapshotSelectString();
sqlLazySelectString = generateLazySelectString();
sqlLazySelectStringsByFetchGroup = generateLazySelectStringsByFetchGroup();
sqlVersionSelectString = generateSelectVersionString();
if ( hasInsertGeneratedProperties() ) {
sqlInsertGeneratedValuesSelectString = generateInsertGeneratedValuesSelectString();
@ -4244,11 +4280,7 @@ public abstract class AbstractEntityPersister
if ( getEntityMetamodel().getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
LazyAttributeLoadingInterceptor interceptor = getEntityMetamodel().getBytecodeEnhancementMetadata().extractInterceptor( entity );
if ( interceptor == null ) {
getEntityMetamodel().getBytecodeEnhancementMetadata().injectInterceptor(
entity,
null,
session
);
getEntityMetamodel().getBytecodeEnhancementMetadata().injectInterceptor( entity, session );
}
else {
interceptor.setSession( session );
@ -4483,8 +4515,9 @@ public abstract class AbstractEntityPersister
return isVersioned() && getPropertyInsertability()[getVersionProperty()];
}
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
getEntityTuplizer().afterInitialize( entity, lazyPropertiesAreUnfetched, session );
@Override
public void afterInitialize(Object entity, SessionImplementor session) {
getEntityTuplizer().afterInitialize( entity, session );
}
public String[] getPropertyNames() {
@ -4609,7 +4642,7 @@ public abstract class AbstractEntityPersister
@Override
public boolean hasUninitializedLazyProperties(Object object) {
return getEntityTuplizer().hasUninitializedLazyProperties( object );
return entityMetamodel.getBytecodeEnhancementMetadata().hasUnFetchedAttributes( object );
}
@Override
@ -5143,7 +5176,6 @@ public abstract class AbstractEntityPersister
return new StandardCacheEntryImpl(
state,
persister,
persister.hasUninitializedLazyProperties( entity ),
version,
session,
entity
@ -5188,7 +5220,6 @@ public abstract class AbstractEntityPersister
return new StandardCacheEntryImpl(
state,
persister,
persister.hasUninitializedLazyProperties( entity ),
version,
session,
entity

View File

@ -8,6 +8,7 @@ package org.hibernate.persister.entity;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
@ -589,7 +590,7 @@ public interface EntityPersister extends OptimisticCacheSource, EntityDefinition
/**
* Called just after the entities properties have been initialized
*/
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session);
void afterInitialize(Object entity, SessionImplementor session);
/**
* Called just after the entity has been reassociated with the session

View File

@ -13,7 +13,7 @@ import org.hibernate.PropertyNotFoundException;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.property.access.spi.EnhancedGetterMethodImpl;
import org.hibernate.property.access.spi.EnhancedSetterMethodImpl;
import org.hibernate.property.access.spi.EnhancedSetterImpl;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.GetterFieldImpl;
import org.hibernate.property.access.spi.PropertyAccess;
@ -32,7 +32,6 @@ import org.hibernate.property.access.spi.SetterFieldImpl;
*/
public class PropertyAccessEnhancedImpl implements PropertyAccess {
private final PropertyAccessStrategyEnhancedImpl strategy;
private final Getter getter;
private final Setter setter;
@ -42,42 +41,50 @@ public class PropertyAccessEnhancedImpl implements PropertyAccess {
String propertyName) {
this.strategy = strategy;
// field represents the enhanced field on the entity
final Field field = fieldOrNull( containerJavaType, propertyName );
final Method getterMethod = getterMethodOrNull( containerJavaType, propertyName );
final Class propertyJavaType;
// need one of field or getterMethod to be non-null
if ( field == null && getterMethod == null ) {
String msg = String.format( "Could not locate field nor getter method for property named [%s#%s]",
containerJavaType.getName(),
propertyName );
throw new PropertyAccessBuildingException( msg );
}
else if ( field != null ) {
propertyJavaType = field.getType();
this.getter = resolveGetterForField( containerJavaType, propertyName, field );
}
else {
propertyJavaType = getterMethod.getReturnType();
this.getter = new EnhancedGetterMethodImpl( containerJavaType, propertyName, getterMethod );
if ( field == null ) {
throw new PropertyAccessBuildingException(
String.format(
"Could not locate field for property [%s] on bytecode-enhanced Class [%s]",
propertyName,
containerJavaType.getName()
)
);
}
final Method setterMethod = setterMethodOrNull( containerJavaType, propertyName, propertyJavaType );
// need one of field or setterMethod to be non-null
if ( field == null && setterMethod == null ) {
String msg = String.format( "Could not locate field nor getter method for property named [%s#%s]",
containerJavaType.getName(),
propertyName );
throw new PropertyAccessBuildingException( msg );
}
else if ( field != null ) {
this.setter = resolveSetterForField( containerJavaType, propertyName, field );
}
else {
this.setter = new EnhancedSetterMethodImpl( containerJavaType, propertyName, setterMethod );
}
this.getter = new GetterFieldImpl( containerJavaType, propertyName, field );
this.setter = resolveEnhancedSetterForField( containerJavaType, propertyName, field );
//
// // need one of field or getterMethod to be non-null
// if ( field == null && getterMethod == null ) {
// String msg = ;
// throw new PropertyAccessBuildingException( msg );
// }
// else if ( field != null ) {
// propertyJavaType = field.getType();
// this.getter = resolveGetterForField( containerJavaType, propertyName, field );
// }
// else {
// propertyJavaType = getterMethod.getReturnType();
// this.getter = new EnhancedGetterMethodImpl( containerJavaType, propertyName, field, getterMethod );
// }
//
// final Method setterMethod = setterMethodOrNull( containerJavaType, propertyName, propertyJavaType );
//
// // need one of field or setterMethod to be non-null
// if ( field == null && setterMethod == null ) {
// String msg = String.format( "Could not locate field nor getter method for property named [%s#%s]",
// containerJavaType.getName(),
// propertyName );
// throw new PropertyAccessBuildingException( msg );
// }
// else if ( field != null ) {
// this.setter = resolveSetterForField( containerJavaType, propertyName, field );
// }
// else {
// this.setter = new EnhancedSetterImpl( containerJavaType, propertyName, setterMethod );
// }
}
private static Field fieldOrNull(Class containerJavaType, String propertyName) {
@ -107,27 +114,26 @@ public class PropertyAccessEnhancedImpl implements PropertyAccess {
}
}
//
//
// private static Getter resolveGetterForField(Class<?> containerClass, String propertyName, Field field) {
// try {
// String enhancedGetterName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + propertyName;
// Method enhancedGetter = containerClass.getDeclaredMethod( enhancedGetterName );
// enhancedGetter.setAccessible( true );
// return new EnhancedGetterMethodImpl( containerClass, propertyName, field, enhancedGetter );
// }
// catch (NoSuchMethodException e) {
// // enhancedGetter = null --- field not enhanced: fallback to reflection using the field
// return new GetterFieldImpl( containerClass, propertyName, field );
// }
// }
private static Getter resolveGetterForField(Class<?> containerClass, String propertyName, Field field) {
try {
String enhancedGetterName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + propertyName;
Method enhancedGetter = containerClass.getDeclaredMethod( enhancedGetterName );
enhancedGetter.setAccessible( true );
return new EnhancedGetterMethodImpl( containerClass, propertyName, enhancedGetter );
}
catch (NoSuchMethodException e) {
// enhancedGetter = null --- field not enhanced: fallback to reflection using the field
return new GetterFieldImpl( containerClass, propertyName, field );
}
}
private static Setter resolveSetterForField(Class<?> containerClass, String propertyName, Field field) {
private static Setter resolveEnhancedSetterForField(Class<?> containerClass, String propertyName, Field field) {
try {
String enhancedSetterName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + propertyName;
Method enhancedSetter = containerClass.getDeclaredMethod( enhancedSetterName, field.getType() );
enhancedSetter.setAccessible( true );
return new EnhancedSetterMethodImpl( containerClass, propertyName, enhancedSetter );
return new EnhancedSetterImpl( containerClass, propertyName, enhancedSetter );
}
catch (NoSuchMethodException e) {
// enhancedSetter = null --- field not enhanced: fallback to reflection using the field

View File

@ -34,11 +34,13 @@ public class PropertyAccessStrategyResolverStandardImpl implements PropertyAcces
String explicitAccessStrategyName,
EntityMode entityMode) {
if ( ( BuiltInPropertyAccessStrategies.BASIC.getExternalName().equals( explicitAccessStrategyName ) ||
BuiltInPropertyAccessStrategies.FIELD.getExternalName().equals( explicitAccessStrategyName ) ||
BuiltInPropertyAccessStrategies.MIXED.getExternalName().equals( explicitAccessStrategyName ) ) &&
Managed.class.isAssignableFrom( containerClass ) ) {
return PropertyAccessStrategyEnhancedImpl.INSTANCE;
if ( BuiltInPropertyAccessStrategies.BASIC.getExternalName().equals( explicitAccessStrategyName )
|| BuiltInPropertyAccessStrategies.FIELD.getExternalName().equals( explicitAccessStrategyName )
|| BuiltInPropertyAccessStrategies.MIXED.getExternalName().equals( explicitAccessStrategyName ) ) {
if ( Managed.class.isAssignableFrom( containerClass ) ) {
// PROPERTY (BASIC) and MIXED are not valid for bytecode enhanced entities...
return PropertyAccessStrategyEnhancedImpl.INSTANCE;
}
}
if ( StringHelper.isNotEmpty( explicitAccessStrategyName ) ) {

View File

@ -8,6 +8,7 @@ package org.hibernate.property.access.spi;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
@ -30,44 +31,50 @@ public class EnhancedGetterMethodImpl implements Getter {
private final Class containerClass;
private final String propertyName;
private final Field field;
private final Method getterMethod;
public EnhancedGetterMethodImpl(Class containerClass, String propertyName, Method getterMethod) {
public EnhancedGetterMethodImpl(
Class containerClass,
String propertyName,
Field field,
Method getterMethod) {
this.containerClass = containerClass;
this.propertyName = propertyName;
this.field = field;
this.getterMethod = getterMethod;
}
private boolean isAttributeLoaded(Object owner) {
if ( owner instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) owner ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
return ( (LazyAttributeLoadingInterceptor) interceptor ).isAttributeLoaded( propertyName );
}
}
return true;
}
// private boolean isAttributeLoaded(Object owner) {
// if ( owner instanceof PersistentAttributeInterceptable ) {
// PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) owner ).$$_hibernate_getInterceptor();
// if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
// return ( (LazyAttributeLoadingInterceptor) interceptor ).isAttributeLoaded( propertyName );
// }
// }
// return true;
// }
@Override
public Object get(Object owner) {
try {
return field.get( owner );
// We don't want to trigger lazy loading of byte code enhanced attributes
if ( isAttributeLoaded( owner ) ) {
return getterMethod.invoke( owner );
}
return null;
}
catch (InvocationTargetException ite) {
throw new PropertyAccessException(
ite,
"Exception occurred inside",
false,
containerClass,
propertyName
);
// // We don't want to trigger lazy loading of byte code enhanced attributes
// if ( isAttributeLoaded( owner ) ) {
// return getterMethod.invoke( owner );
// }
// return null;
}
// catch (InvocationTargetException ite) {
// throw new PropertyAccessException(
// ite,
// "Exception occurred inside",
// false,
// containerClass,
// propertyName
// );
// }
catch (IllegalAccessException iae) {
throw new PropertyAccessException(
iae,
@ -134,7 +141,7 @@ public class EnhancedGetterMethodImpl implements Getter {
}
private Object readResolve() {
return new EnhancedGetterMethodImpl( containerClass, propertyName, resolveMethod() );
return new EnhancedGetterMethodImpl( containerClass, propertyName, resolveField(), resolveMethod() );
}
@SuppressWarnings("unchecked")
@ -148,5 +155,17 @@ public class EnhancedGetterMethodImpl implements Getter {
);
}
}
@SuppressWarnings("unchecked")
private Field resolveField() {
try {
return declaringClass.getDeclaredField( propertyName );
}
catch (NoSuchFieldException e) {
throw new PropertyAccessSerializationException(
"Unable to resolve field on deserialization : " + declaringClass.getName() + "#" + propertyName
);
}
}
}
}

View File

@ -20,10 +20,15 @@ import org.hibernate.internal.CoreMessageLogger;
import static org.hibernate.internal.CoreLogging.messageLogger;
/**
* A specialized Setter implementation for handling setting values into
* a into a bytecode-enhanced Class. The reason we need specialized handling
* is to render the fact that the
*
* @author Steve Ebersole
* @author Luis Barreiro
*/
public class EnhancedSetterMethodImpl implements Setter {
private static final CoreMessageLogger LOG = messageLogger( EnhancedSetterMethodImpl.class );
public class EnhancedSetterImpl implements Setter {
private static final CoreMessageLogger LOG = messageLogger( EnhancedSetterImpl.class );
private final Class containerClass;
private final String propertyName;
@ -31,7 +36,7 @@ public class EnhancedSetterMethodImpl implements Setter {
private final boolean isPrimitive;
public EnhancedSetterMethodImpl(Class containerClass, String propertyName, Method setterMethod) {
public EnhancedSetterImpl(Class containerClass, String propertyName, Method setterMethod) {
this.containerClass = containerClass;
this.propertyName = propertyName;
this.setterMethod = setterMethod;
@ -153,7 +158,7 @@ public class EnhancedSetterMethodImpl implements Setter {
}
private Object readResolve() {
return new EnhancedSetterMethodImpl( containerClass, propertyName, resolveMethod() );
return new EnhancedSetterImpl( containerClass, propertyName, resolveMethod() );
}
@SuppressWarnings("unchecked")

View File

@ -13,34 +13,47 @@ import java.lang.reflect.Constructor;
import org.hibernate.InstantiationException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass;
import org.jboss.logging.Logger;
/**
* Defines a POJO-based instantiator for use from the tuplizers.
*/
public class PojoInstantiator implements Instantiator, Serializable {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, PojoInstantiator.class.getName());
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PojoInstantiator.class.getName() );
private transient Constructor constructor;
private final Class mappedClass;
private final transient ReflectionOptimizer.InstantiationOptimizer optimizer;
private final boolean embeddedIdentifier;
private final Class proxyInterface;
private final boolean isAbstract;
public PojoInstantiator(
Class mappedClass,
ReflectionOptimizer.InstantiationOptimizer optimizer,
boolean embeddedIdentifier) {
this.mappedClass = mappedClass;
this.optimizer = optimizer;
this.embeddedIdentifier = embeddedIdentifier;
this.isAbstract = ReflectHelper.isAbstractClass( mappedClass );
try {
constructor = ReflectHelper.getDefaultConstructor(mappedClass);
}
catch ( PropertyNotFoundException pnfe ) {
LOG.noDefaultConstructor( mappedClass.getName() );
constructor = null;
}
}
public PojoInstantiator(Component component, ReflectionOptimizer.InstantiationOptimizer optimizer) {
this.mappedClass = component.getComponentClass();
this.isAbstract = ReflectHelper.isAbstractClass( mappedClass );
this.optimizer = optimizer;
this.proxyInterface = null;
this.embeddedIdentifier = false;
try {
@ -52,22 +65,6 @@ public class PojoInstantiator implements Instantiator, Serializable {
}
}
public PojoInstantiator(PersistentClass persistentClass, ReflectionOptimizer.InstantiationOptimizer optimizer) {
this.mappedClass = persistentClass.getMappedClass();
this.isAbstract = ReflectHelper.isAbstractClass( mappedClass );
this.proxyInterface = persistentClass.getProxyInterface();
this.embeddedIdentifier = persistentClass.hasEmbeddedIdentifier();
this.optimizer = optimizer;
try {
constructor = ReflectHelper.getDefaultConstructor( mappedClass );
}
catch ( PropertyNotFoundException pnfe ) {
LOG.noDefaultConstructor(mappedClass.getName());
constructor = null;
}
}
private void readObject(java.io.ObjectInputStream stream) throws ClassNotFoundException, IOException {
stream.defaultReadObject();
constructor = ReflectHelper.getDefaultConstructor( mappedClass );
@ -85,7 +82,7 @@ public class PojoInstantiator implements Instantiator, Serializable {
}
else {
try {
return constructor.newInstance( (Object[]) null );
return applyInterception( constructor.newInstance( (Object[]) null ) );
}
catch ( Exception e ) {
throw new InstantiationException( "Could not instantiate entity: ", mappedClass, e );
@ -93,6 +90,10 @@ public class PojoInstantiator implements Instantiator, Serializable {
}
}
protected Object applyInterception(Object entity) {
return entity;
}
public Object instantiate(Serializable id) {
final boolean useEmbeddedIdentifierInstanceAsEntity = embeddedIdentifier &&
id != null &&
@ -101,7 +102,6 @@ public class PojoInstantiator implements Instantiator, Serializable {
}
public boolean isInstance(Object object) {
return mappedClass.isInstance(object) ||
( proxyInterface!=null && proxyInterface.isInstance(object) ); //this one needed only for guessEntityMode()
return mappedClass.isInstance( object );
}
}

View File

@ -100,7 +100,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
*
* @return An appropriate Instantiator instance.
*/
protected abstract Instantiator buildInstantiator(PersistentClass mappingInfo);
protected abstract Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass mappingInfo);
/**
* Build an appropriate ProxyFactory for the given mapped entity.
@ -151,7 +151,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
hasCustomAccessors = foundCustomAccessor;
instantiator = buildInstantiator( mappingInfo );
instantiator = buildInstantiator( entityMetamodel, mappingInfo );
if ( entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter );
@ -486,7 +486,11 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
protected boolean shouldGetAllProperties(Object entity) {
return !hasUninitializedLazyProperties( entity );
if ( !getEntityMetamodel().getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
return true;
}
return !getEntityMetamodel().getBytecodeEnhancementMetadata().hasUnFetchedAttributes( entity );
}
@Override
@ -641,13 +645,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
@Override
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
}
@Override
public boolean hasUninitializedLazyProperties(Object entity) {
// the default is to simply not lazy fetch properties for now...
return false;
public void afterInitialize(Object entity, SessionImplementor session) {
}
@Override

View File

@ -1,50 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.tuple.entity;
import java.util.Set;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.engine.spi.SessionImplementor;
/**
* @author Steve Ebersole
*/
public class BytecodeEnhancementMetadataNonEnhancedPojoImpl implements BytecodeEnhancementMetadata {
private final Class entityClass;
private final String errorMsg;
public BytecodeEnhancementMetadataNonEnhancedPojoImpl(Class entityClass) {
this.entityClass = entityClass;
this.errorMsg = "Entity class [" + entityClass.getName() + "] is not enhanced";
}
@Override
public String getEntityName() {
return entityClass.getName();
}
@Override
public boolean isEnhancedForLazyLoading() {
return false;
}
@Override
public LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
@Override
public LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
}

View File

@ -9,6 +9,7 @@ package org.hibernate.tuple.entity;
import java.util.Set;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.engine.spi.SessionImplementor;
@ -18,10 +19,12 @@ import org.hibernate.engine.spi.SessionImplementor;
*/
public class BytecodeEnhancementMetadataNonPojoImpl implements BytecodeEnhancementMetadata {
private final String entityName;
private final LazyAttributesMetadata lazyAttributesMetadata;
private final String errorMsg;
public BytecodeEnhancementMetadataNonPojoImpl(String entityName) {
this.entityName = entityName;
this.lazyAttributesMetadata = LazyAttributesMetadata.nonEnhanced( entityName );
this.errorMsg = "Entity [" + entityName + "] is non-pojo, and therefore not instrumented";
}
@ -35,10 +38,14 @@ public class BytecodeEnhancementMetadataNonPojoImpl implements BytecodeEnhanceme
return false;
}
@Override
public LazyAttributesMetadata getLazyAttributesMetadata() {
return lazyAttributesMetadata;
}
@Override
public LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
@ -47,4 +54,9 @@ public class BytecodeEnhancementMetadataNonPojoImpl implements BytecodeEnhanceme
public LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
@Override
public boolean hasUnFetchedAttributes(Object entity) {
return false;
}
}

View File

@ -9,27 +9,52 @@ package org.hibernate.tuple.entity;
import java.util.Set;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.mapping.PersistentClass;
/**
* @author Steve Ebersole
*/
public class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhancementMetadata {
public static BytecodeEnhancementMetadata from(PersistentClass persistentClass) {
final Class mappedClass = persistentClass.getMappedClass();
final boolean enhancedForLazyLoading = PersistentAttributeInterceptable.class.isAssignableFrom( mappedClass );
final LazyAttributesMetadata lazyAttributesMetadata = enhancedForLazyLoading
? LazyAttributesMetadata.from( persistentClass )
: LazyAttributesMetadata.nonEnhanced( persistentClass.getEntityName() );
return new BytecodeEnhancementMetadataPojoImpl(
persistentClass.getEntityName(),
mappedClass,
enhancedForLazyLoading,
lazyAttributesMetadata
);
}
private final String entityName;
private final Class entityClass;
private final boolean enhancedForLazyLoading;
private final LazyAttributesMetadata lazyAttributesMetadata;
public BytecodeEnhancementMetadataPojoImpl(Class entityClass) {
public BytecodeEnhancementMetadataPojoImpl(
String entityName,
Class entityClass,
boolean enhancedForLazyLoading,
LazyAttributesMetadata lazyAttributesMetadata) {
this.entityName = entityName;
this.entityClass = entityClass;
this.enhancedForLazyLoading = PersistentAttributeInterceptable.class.isAssignableFrom( entityClass );
this.enhancedForLazyLoading = enhancedForLazyLoading;
this.lazyAttributesMetadata = lazyAttributesMetadata;
}
@Override
public String getEntityName() {
return entityClass.getName();
return entityName;
}
@Override
@ -37,6 +62,19 @@ public class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhancementM
return enhancedForLazyLoading;
}
@Override
public LazyAttributesMetadata getLazyAttributesMetadata() {
return lazyAttributesMetadata;
}
@Override
public boolean hasUnFetchedAttributes(Object entity) {
LazyAttributeLoadingInterceptor interceptor = isEnhancedForLazyLoading()
? extractInterceptor( entity )
: null;
return interceptor != null && interceptor.hasAnyUninitializedAttributes();
}
@Override
public LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
if ( !enhancedForLazyLoading ) {
@ -62,10 +100,7 @@ public class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhancementM
}
@Override
public LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException {
public LazyAttributeLoadingInterceptor injectInterceptor(Object entity, SessionImplementor session) {
if ( !enhancedForLazyLoading ) {
throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + "] is not enhanced for lazy loading" );
}
@ -80,7 +115,11 @@ public class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhancementM
);
}
final LazyAttributeLoadingInterceptor interceptor = new LazyAttributeLoadingInterceptor( session, uninitializedFieldNames, getEntityName() );
final LazyAttributeLoadingInterceptor interceptor = new LazyAttributeLoadingInterceptor(
getEntityName(),
lazyAttributesMetadata.getLazyAttributeNames(),
session
);
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( interceptor );
return interceptor;
}

View File

@ -16,10 +16,10 @@ import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.property.access.internal.PropertyAccessStrategyMapImpl;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.proxy.map.MapProxyFactory;
import org.hibernate.tuple.DynamicMapInstantiator;
@ -63,7 +63,7 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
}
@Override
protected Instantiator buildInstantiator(PersistentClass mappingInfo) {
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) {
return new DynamicMapInstantiator( mappingInfo );
}
@ -99,11 +99,6 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
return Map.class;
}
@Override
public boolean isInstrumented() {
return false;
}
@Override
public EntityNameResolver[] getEntityNameResolvers() {
return new EntityNameResolver[] {BasicEntityNameResolver.INSTANCE};

View File

@ -143,7 +143,7 @@ public class EntityMetamodel implements Serializable {
versioned = persistentClass.isVersioned();
if ( persistentClass.hasPojoRepresentation() ) {
bytecodeEnhancementMetadata = new BytecodeEnhancementMetadataPojoImpl( persistentClass.getMappedClass() );
bytecodeEnhancementMetadata = BytecodeEnhancementMetadataPojoImpl.from( persistentClass );
}
else {
bytecodeEnhancementMetadata = new BytecodeEnhancementMetadataNonPojoImpl( persistentClass.getEntityName() );

View File

@ -7,6 +7,7 @@
package org.hibernate.tuple.entity;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.EntityNameResolver;
@ -188,10 +189,9 @@ public interface EntityTuplizer extends Tuplizer {
* Called just after the entities properties have been initialized.
*
* @param entity The entity being initialized.
* @param lazyPropertiesAreUnfetched Are defined lazy properties currently unfecthed
* @param session The session initializing this entity.
*/
void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session);
void afterInitialize(Object entity, SessionImplementor session);
/**
* Does this entity, for this mode, present a possibility for proxying?
@ -228,21 +228,6 @@ public interface EntityTuplizer extends Tuplizer {
* @return The java class to which generated proxies will be typed
*/
Class getConcreteProxyClass();
/**
* Does the given entity instance have any currently uninitialized lazy properties?
*
* @param entity The entity to be check for uninitialized lazy properties.
* @return True if uninitialized lazy properties were found; false otherwise.
*/
boolean hasUninitializedLazyProperties(Object entity);
/**
* Is it an instrumented POJO?
*
* @return {@code true} if the entity class is instrumented; {@code false} otherwise.
*/
boolean isInstrumented();
/**
* Get any {@link EntityNameResolver EntityNameResolvers} associated with this {@link Tuplizer}.

View File

@ -0,0 +1,65 @@
/*
* 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.tuple.entity;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.tuple.PojoInstantiator;
/**
* @author Steve Ebersole
*/
public class PojoEntityInstantiator extends PojoInstantiator {
private final EntityMetamodel entityMetamodel;
private final Class proxyInterface;
private final boolean applyBytecodeInterception;
public PojoEntityInstantiator(
EntityMetamodel entityMetamodel,
PersistentClass persistentClass,
ReflectionOptimizer.InstantiationOptimizer optimizer) {
super(
persistentClass.getMappedClass(),
optimizer,
persistentClass.hasEmbeddedIdentifier()
);
this.entityMetamodel = entityMetamodel;
this.proxyInterface = persistentClass.getProxyInterface();
this.applyBytecodeInterception = PersistentAttributeInterceptable.class.isAssignableFrom( persistentClass.getMappedClass() );
}
@Override
protected Object applyInterception(Object entity) {
if ( !applyBytecodeInterception ) {
return entity;
}
PersistentAttributeInterceptor interceptor = new LazyAttributeLoadingInterceptor(
entityMetamodel.getName(),
entityMetamodel.getBytecodeEnhancementMetadata()
.getLazyAttributesMetadata()
.getLazyAttributeNames(),
null
);
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( interceptor );
return entity;
}
@Override
public boolean isInstance(Object object) {
return super.isInstance( object ) ||
//this one needed only for guessEntityMode()
( proxyInterface!=null && proxyInterface.isInstance(object) );
}
}

View File

@ -8,8 +8,6 @@ package org.hibernate.tuple.entity;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@ -53,10 +51,11 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
private final Class mappedClass;
private final Class proxyInterface;
private final boolean lifecycleImplementor;
private final Set<String> lazyPropertyNames;
private final ReflectionOptimizer optimizer;
private final boolean isBytecodeEnhanced;
public PojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
this.mappedClass = mappedEntity.getMappedClass();
@ -64,16 +63,6 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass );
this.isBytecodeEnhanced = entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
Iterator iter = mappedEntity.getPropertyClosureIterator();
Set<String> tmpLazyPropertyNames = new HashSet<String>( );
while ( iter.hasNext() ) {
Property property = (Property) iter.next();
if ( property.isLazy() ) {
tmpLazyPropertyNames.add( property.getName() );
}
}
lazyPropertyNames = tmpLazyPropertyNames.isEmpty() ? null : Collections.unmodifiableSet( tmpLazyPropertyNames );
String[] getterNames = new String[propertySpan];
String[] setterNames = new String[propertySpan];
Class[] propTypes = new Class[propertySpan];
@ -200,12 +189,12 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
}
@Override
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
if ( optimizer == null ) {
return new PojoInstantiator( persistentClass, null );
return new PojoEntityInstantiator( entityMetamodel, persistentClass, null );
}
else {
return new PojoInstantiator( persistentClass, optimizer.getInstantiationOptimizer() );
return new PojoEntityInstantiator( entityMetamodel, persistentClass, optimizer.getInstantiationOptimizer() );
}
}
@ -281,38 +270,35 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
//TODO: need to make the majority of this functionality into a top-level support class for custom impl support
@Override
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
// new bytecode enhancement lazy interception
public void afterInitialize(Object entity, SessionImplementor session) {
// moving to multiple fetch groups, the idea of `lazyPropertiesAreUnfetched` really
// needs to become either:
// 1) the names of all un-fetched fetch groups
// 2) the names of all fetched fetch groups
// probably (2) is best
//
// ultimately this comes from EntityEntry, although usage-search seems to show it is never updated there.
//
// also org.hibernate.persister.entity.AbstractEntityPersister.initializeLazyPropertiesFromDatastore()
// needs to be re-worked
if ( entity instanceof PersistentAttributeInterceptable ) {
if ( lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ) {
PersistentAttributeInterceptor interceptor = new LazyAttributeLoadingInterceptor( session, lazyPropertyNames, getEntityName() );
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( interceptor );
final LazyAttributeLoadingInterceptor interceptor = getEntityMetamodel().getBytecodeEnhancementMetadata().extractInterceptor( entity );
if ( interceptor == null ) {
getEntityMetamodel().getBytecodeEnhancementMetadata().injectInterceptor( entity, session );
}
}
// also clear the fields that are marked as dirty in the dirtyness tracker
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
}
@Override
public boolean hasUninitializedLazyProperties(Object entity) {
if ( getEntityMetamodel().hasLazyProperties() ) {
if ( entity instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
return ( (LazyAttributeLoadingInterceptor) interceptor ).hasAnyUninitializedAttributes();
else {
if ( interceptor.getLinkedSession() == null ) {
interceptor.setSession( session );
}
}
}
return false;
}
@Override
public boolean isInstrumented() {
return isBytecodeEnhanced;
// clear the fields that are marked as dirty in the dirtyness tracker
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
}
@Override

View File

@ -6,10 +6,6 @@
*/
package org.hibernate.engine.spi;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
@ -18,8 +14,13 @@ import java.io.ObjectOutputStream;
import org.hibernate.LockMode;
import org.hibernate.engine.internal.MutableEntityEntry;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Tests for setting and getting the enum/boolean values stored in the compressed state int.
*
@ -35,7 +36,6 @@ public class EntityEntryTest {
assertEquals( Status.MANAGED, entityEntry.getStatus() );
assertEquals( true, entityEntry.isExistsInDatabase() );
assertEquals( true, entityEntry.isBeingReplicated() );
assertEquals( true, entityEntry.isLoadedWithLazyPropertiesUnfetched() );
}
@Test
@ -47,7 +47,6 @@ public class EntityEntryTest {
assertEquals( Status.MANAGED, entityEntry.getStatus() );
assertEquals( true, entityEntry.isExistsInDatabase() );
assertEquals( true, entityEntry.isBeingReplicated() );
assertEquals( true, entityEntry.isLoadedWithLazyPropertiesUnfetched() );
// When
entityEntry.setLockMode( LockMode.PESSIMISTIC_READ );
@ -57,7 +56,6 @@ public class EntityEntryTest {
assertEquals( Status.MANAGED, entityEntry.getStatus() );
assertEquals( true, entityEntry.isExistsInDatabase() );
assertEquals( true, entityEntry.isBeingReplicated() );
assertEquals( true, entityEntry.isLoadedWithLazyPropertiesUnfetched() );
}
@Test
@ -73,7 +71,6 @@ public class EntityEntryTest {
assertEquals( Status.DELETED, entityEntry.getStatus() );
assertEquals( true, entityEntry.isExistsInDatabase() );
assertEquals( true, entityEntry.isBeingReplicated() );
assertEquals( true, entityEntry.isLoadedWithLazyPropertiesUnfetched() );
}
@Test
@ -89,7 +86,6 @@ public class EntityEntryTest {
assertEquals( Status.GONE, entityEntry.getStatus() );
assertEquals( false, entityEntry.isExistsInDatabase() );
assertEquals( true, entityEntry.isBeingReplicated() );
assertEquals( true, entityEntry.isLoadedWithLazyPropertiesUnfetched() );
}
@Test
@ -108,23 +104,30 @@ public class EntityEntryTest {
assertEquals( Status.MANAGED, deserializedEntry.getStatus() );
assertEquals( true, deserializedEntry.isExistsInDatabase() );
assertEquals( true, deserializedEntry.isBeingReplicated() );
assertEquals( true, deserializedEntry.isLoadedWithLazyPropertiesUnfetched() );
}
private EntityEntry createEntityEntry() {
return new MutableEntityEntry(
Status.MANAGED, // status
new Object[]{}, // loadedState
1L, // rowId
42L, // id
23L, // version
LockMode.OPTIMISTIC, // lockMode
true, // existsInDatabase
null, // persister
true, // disableVersionIncrement
true, // lazyPropertiesAreUnfetched
getPersistenceContextMock() // persistenceContext)
// status
Status.MANAGED,
// loadedState
new Object[]{},
// rowId
1L,
// id
42L,
// version
23L,
// lockMode
LockMode.OPTIMISTIC,
// existsInDatabase
true,
// persister
null,
// disableVersionIncrement
true,
getPersistenceContextMock()
);
}

View File

@ -19,19 +19,21 @@ import org.hibernate.tuple.entity.PojoEntityTuplizer;
*/
public class DynamicEntityTuplizer extends PojoEntityTuplizer {
public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
}
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
return new DynamicInstantiator( persistentClass.getEntityName() );
}
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
// allows defining a custom proxy factory, which is responsible for
// generating lazy proxies for a given entity.
//
// Here we simply use the default...
return super.buildProxyFactory( persistentClass, idGetter, idSetter );
}
public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
}
@Override
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
return new DynamicInstantiator( persistentClass.getEntityName() );
}
@Override
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
// allows defining a custom proxy factory, which is responsible for
// generating lazy proxies for a given entity.
//
// Here we simply use the default...
return super.buildProxyFactory( persistentClass, idGetter, idSetter );
}
}

View File

@ -27,6 +27,7 @@ import org.hibernate.test.bytecode.enhancement.lazy.LazyLoadingIntegrationTestTa
import org.hibernate.test.bytecode.enhancement.lazy.LazyLoadingTestTask;
import org.hibernate.test.bytecode.enhancement.lazy.basic.LazyBasicFieldAccessTestTask;
import org.hibernate.test.bytecode.enhancement.lazy.basic.LazyBasicPropertyAccessTestTask;
import org.hibernate.test.bytecode.enhancement.lazy.group.LazyGroupAccessTestTask;
import org.hibernate.test.bytecode.enhancement.lazyCache.InitFromCacheTestTask;
import org.hibernate.test.bytecode.enhancement.merge.CompositeMergeTestTask;
import org.hibernate.test.bytecode.enhancement.pk.EmbeddedPKTestTask;
@ -72,6 +73,12 @@ public class EnhancerTest extends BaseUnitTestCase {
EnhancerTestUtils.runEnhancerTestTask( LazyCollectionLoadingTestTask.class );
}
@Test
@TestForIssue( jiraKey = "HHH-10267" )
public void testLazyGroups() {
EnhancerTestUtils.runEnhancerTestTask( LazyGroupAccessTestTask.class );
}
@Test(timeout = 10000)
@TestForIssue( jiraKey = "HHH-10055" )
@FailureExpected( jiraKey = "HHH-10055" )

View File

@ -7,6 +7,8 @@
package org.hibernate.test.bytecode.enhancement.basic;
import java.util.Set;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
/**
@ -112,4 +114,14 @@ public class ObjectAttributeMarkerInterceptor implements PersistentAttributeInte
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
return WRITE_MARKER;
}
@Override
public Set<String> getInitializedLazyAttributeNames() {
return null;
}
@Override
public void attributeInitialized(String name) {
}
}

View File

@ -34,6 +34,13 @@ public class Child {
@LazyToOne(LazyToOneOption.NO_PROXY)
Parent parent;
public Child() {
}
public Child(String name) {
this.name = name;
}
public Long getId() {
return id;
}

View File

@ -18,6 +18,9 @@ import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* @author Luis Barreiro
*/
@ -43,8 +46,9 @@ public class LazyLoadingTestTask extends AbstractEnhancerTestTask {
Parent parent = new Parent();
parent.setChildren(new ArrayList<Child>());
for ( int i = 0; i < CHILDREN_SIZE; i++ ) {
final Child child = new Child();
final Child child = new Child( "Child #" + i );
child.setParent( parent );
parent.getChildren().add( child );
s.persist( child );
lastChildID = child.getId();
}
@ -62,11 +66,17 @@ public class LazyLoadingTestTask extends AbstractEnhancerTestTask {
Child loadedChild = s.load( Child.class, lastChildID );
Object nameByReflection = EnhancerTestUtils.getFieldByReflection( loadedChild, "name" );
Assert.assertNotNull( "Non-lazy field 'name' was not loaded", nameByReflection );
Object parentByReflection = EnhancerTestUtils.getFieldByReflection( loadedChild, "parent" );
Assert.assertNull( "Lazy field 'parent' is initialized", parentByReflection );
Assert.assertFalse( loadedChild instanceof HibernateProxy );
Parent loadedParent = loadedChild.getParent();
assertThat( loadedChild.getName(), notNullValue() );
assertThat( loadedParent, notNullValue() );
assertThat( loadedChild.getParent(), notNullValue() );
EnhancerTestUtils.checkDirtyTracking( loadedChild );

View File

@ -0,0 +1,88 @@
/*
* 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.group;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.LazyGroup;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
/**
* @author Steve Ebersole
*/
@Entity
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
@Basic( fetch = FetchType.LAZY )
String nickName;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
Parent parent;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@LazyGroup( "SECONDARY" )
Parent alternateParent;
public Child() {
}
public Child(String name, String nickName) {
this.name = name;
this.nickName = nickName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public Parent getAlternateParent() {
return alternateParent;
}
public void setAlternateParent(Parent alternateParent) {
this.alternateParent = alternateParent;
}
}

View File

@ -0,0 +1,132 @@
/*
* 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.group;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.junit.Assert;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
/**
* @author Steve Ebersole
*/
public class LazyGroupAccessTestTask extends AbstractEnhancerTestTask {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[] { Child.class, Parent.class };
}
@Override
public void prepare() {
Configuration cfg = new Configuration();
cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "false" );
super.prepare( cfg );
Session s = getFactory().openSession();
s.beginTransaction();
Child c1 = new Child( "steve", "hibernater" );
Child c2 = new Child( "sally", "Joe Mama" );
Parent p1 = new Parent( "Hibernate" );
Parent p2 = new Parent( "Swimming" );
c1.setParent( p1 );
p1.getChildren().add( c1 );
c1.setAlternateParent( p2 );
p2.getAlternateChildren().add( c1 );
c2.setAlternateParent( p1 );
p1.getAlternateChildren().add( c2 );
c2.setParent( p2 );
p2.getChildren().add( c2 );
s.save( p1 );
s.save( p2 );
s.getTransaction().commit();
s.close();
}
@Override
public void execute() {
Session s = getFactory().openSession();
s.beginTransaction();
Child c1 = (Child) s.createQuery( "from Child c where c.name = :name" ).setString( "name", "steve" ).uniqueResult();
// verify the expected initial loaded state
assertLoaded( c1, "name" );
assertNotLoaded( c1, "nickName" );
assertNotLoaded( c1, "parent" );
assertNotLoaded( c1, "alternateParent" );
// Now lets access nickName which ought to initialize nickName and parent, but not alternateParent
c1.getNickName();
assertLoaded( c1, "nickName" );
assertLoaded( c1, "parent" );
assertNotLoaded( c1, "alternateParent" );
assertEquals( "Hibernate", c1.getParent().getNombre() );
assertFalse( c1.getParent() instanceof HibernateProxy );
Child c2 = (Child) s.createQuery( "from Child c where c.name = :name" ).setString( "name", "sally" ).uniqueResult();
// verify the expected initial loaded state
assertLoaded( c2, "name" );
assertNotLoaded( c2, "nickName" );
assertNotLoaded( c2, "parent" );
assertNotLoaded( c2, "alternateParent" );
// Now lets access alternateParent which ought to initialize alternateParent and nothing else
c2.getAlternateParent();
assertNotLoaded( c2, "nickName" );
assertNotLoaded( c2, "parent" );
assertLoaded( c2, "alternateParent" );
assertEquals( "Hibernate", c2.getAlternateParent().getNombre() );
assertFalse( c2.getAlternateParent() instanceof HibernateProxy );
s.getTransaction().commit();
s.close();
}
private void assertLoaded(Object owner, String name) {
// NOTE we assume null == not-loaded
Object fieldByReflection = EnhancerTestUtils.getFieldByReflection( owner, name );
assertNotNull( "Expecting field '" + name + "' to be loaded, but it was not", fieldByReflection );
}
private void assertNotLoaded(Object owner, String name) {
// NOTE we assume null == not-loaded
Object fieldByReflection = EnhancerTestUtils.getFieldByReflection( owner, name );
assertNull( "Expecting field '" + name + "' to be not loaded, but it was", fieldByReflection );
}
@Override
protected void cleanup() {
Session s = getFactory().openSession();
s.beginTransaction();
s.createQuery( "delete Child" ).executeUpdate();
s.createQuery( "delete Parent" ).executeUpdate();
s.getTransaction().commit();
s.close();
}
}

View File

@ -0,0 +1,71 @@
/*
* 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.group;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
/**
* @author Steve Ebersole
*/
@Entity
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String nombre;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
List<Child> children = new ArrayList<Child>();
@OneToMany(mappedBy = "alternateParent", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
List<Child> alternateChildren = new ArrayList<Child>();
public Parent() {
}
public Parent(String nombre) {
this.nombre = nombre;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
public List<Child> getAlternateChildren() {
return alternateChildren;
}
public void setAlternateChildren(List<Child> alternateChildren) {
this.alternateChildren = alternateChildren;
}
}

View File

@ -36,6 +36,7 @@ public abstract class AbstractCachingTestTask implements EnhancerTestTask {
StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();
registryBuilder.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" );
registryBuilder.applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" );
registryBuilder.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
registryBuilder.addService( ClassLoaderService.class, new ClassLoaderServiceImpl( Thread.currentThread().getContextClassLoader() ) );
StandardServiceRegistry registry = registryBuilder.build();

View File

@ -8,10 +8,14 @@ package org.hibernate.test.bytecode.enhancement.lazyCache;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.cache.BaseRegion;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
@ -20,42 +24,47 @@ import static org.junit.Assert.assertTrue;
public class InitFromCacheTestTask extends AbstractCachingTestTask {
@Override
public void execute() {
Session s;
Transaction tx;
EntityPersister p = sessionFactory().getEntityPersister( Document.class.getName() );
assertTrue( p.hasCache() );
BaseRegion region = (BaseRegion) p.getCacheAccessStrategy().getRegion();
s = sessionFactory().openSession();
tx = s.beginTransaction();
Session s = sessionFactory().openSession();
s.beginTransaction();
s.persist( new Document("HiA", "Hibernate book", "Hibernate is....") );
tx.commit();
s.getTransaction().commit();
s.close();
s = sessionFactory().openSession();
tx = s.beginTransaction();
s.createQuery("from Document fetch all properties").uniqueResult();
tx.commit();
s.beginTransaction();
Document d = (Document) s.createQuery( "from Document fetch all properties").uniqueResult();
assertTrue( Hibernate.isPropertyInitialized( d, "text") );
assertTrue( Hibernate.isPropertyInitialized( d, "summary") );
s.getTransaction().commit();
s.close();
StandardCacheEntryImpl cacheEntry = (StandardCacheEntryImpl) region.getDataMap().get( p.getCacheAccessStrategy().generateCacheKey( d.getId(), p, sessionFactory(), null ) );
assertNotNull( cacheEntry );
sessionFactory().getStatistics().clear();
s = sessionFactory().openSession();
tx = s.beginTransaction();
Document d = (Document) s.createCriteria(Document.class).uniqueResult();
s.beginTransaction();
d = (Document) s.createCriteria(Document.class).uniqueResult();
assertFalse( Hibernate.isPropertyInitialized( d, "text") );
assertFalse( Hibernate.isPropertyInitialized(d, "summary") );
assertEquals( "Hibernate is....", d.getText() );
assertTrue( Hibernate.isPropertyInitialized(d, "text") );
assertTrue( Hibernate.isPropertyInitialized(d, "summary") );
tx.commit();
s.getTransaction().commit();
s.close();
assertEquals( 2, sessionFactory().getStatistics().getPrepareStatementCount() );
s = sessionFactory().openSession();
tx = s.beginTransaction();
s.beginTransaction();
d = s.get(Document.class, d.getId());
assertFalse( Hibernate.isPropertyInitialized(d, "text") );
assertFalse( Hibernate.isPropertyInitialized(d, "summary") );
tx.commit();
s.getTransaction().commit();
s.close();
}
}

View File

@ -11,6 +11,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
@ -45,9 +46,9 @@ import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.type.CollectionType;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;
@ -453,7 +454,8 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
}
@Override
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
public void afterInitialize(Object entity, SessionImplementor session) {
}
@Override

View File

@ -22,10 +22,12 @@ public class MyEntityTuplizer extends PojoEntityTuplizer {
super( entityMetamodel, mappedEntity );
}
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
@Override
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
return new MyEntityInstantiator( persistentClass.getEntityName() );
}
@Override
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
// allows defining a custom proxy factory, which is responsible for
// generating lazy proxies for a given entity.

View File

@ -26,14 +26,17 @@ public class MyEntityTuplizer extends PojoEntityTuplizer {
super( entityMetamodel, mappedEntity );
}
@Override
public EntityNameResolver[] getEntityNameResolvers() {
return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };
}
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
@Override
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
return new MyEntityInstantiator( persistentClass.getEntityName() );
}
@Override
public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {
String entityName = ProxyHelper.extractEntityName( entityInstance );
if ( entityName == null ) {
@ -42,6 +45,7 @@ public class MyEntityTuplizer extends PojoEntityTuplizer {
return entityName;
}
@Override
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
// allows defining a custom proxy factory, which is responsible for
// generating lazy proxies for a given entity.

View File

@ -10,6 +10,7 @@ import java.io.Serializable;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
@ -45,9 +46,9 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;
@ -324,7 +325,6 @@ public class CustomPersister implements EntityPersister {
clone,
this,
LockMode.NONE,
false,
session
);
TwoPhaseLoad.postHydrate(
@ -333,7 +333,6 @@ public class CustomPersister implements EntityPersister {
null,
clone,
LockMode.NONE,
false,
session
);
TwoPhaseLoad.initializeEntity(
@ -561,7 +560,7 @@ public class CustomPersister implements EntityPersister {
}
@Override
public void afterInitialize(Object entity, boolean fetched, SessionImplementor session) {
public void afterInitialize(Object entity, SessionImplementor session) {
}
@Override
@ -594,7 +593,6 @@ public class CustomPersister implements EntityPersister {
return new StandardCacheEntryImpl(
state,
this,
this.hasUninitializedLazyProperties( entity ),
version,
session,
entity

View File

@ -474,7 +474,7 @@ public class PersisterClassProviderTest {
}
@Override
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
public void afterInitialize(Object entity, SessionImplementor session) {
}
@Override

View File

@ -213,7 +213,6 @@ public abstract class EnhancerTestUtils extends BaseUnitTestCase {
false,
null,
false,
false,
null
);
}

View File

@ -16,7 +16,7 @@ import org.hibernate.cache.spi.Region;
/**
* @author Strong Liu
*/
class BaseRegion implements Region {
public class BaseRegion implements Region {
protected final Map cache = new ConcurrentHashMap();
private final String name;
private static int timeout = Timestamper.ONE_MS * 60000; //60s
@ -69,4 +69,8 @@ class BaseRegion implements Region {
public int getTimeout() {
return timeout;
}
public Map getDataMap() {
return cache;
}
}