下面列出了怎么用org.hibernate.engine.spi.PersistentAttributeInterceptable的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public void set(Object target, Object value, SessionFactoryImplementor factory) {
super.set( target, value, factory );
// This sets the component relation for dirty tracking purposes
if ( target instanceof CompositeOwner && value instanceof CompositeTracker ) {
( (CompositeTracker) value ).$$_hibernate_setOwner( propertyName, (CompositeOwner) target );
}
// This marks the attribute as initialized, so it doesn't get lazy loaded afterwards
if ( target instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) target ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
interceptor.attributeInitialized( propertyName );
}
}
}
@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 LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
if ( !enhancedForLazyLoading ) {
throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + "] is not enhanced for lazy loading" );
}
if ( !entityClass.isInstance( entity ) ) {
throw new IllegalArgumentException(
String.format(
"Passed entity instance [%s] is not of expected type [%s]",
entity,
getEntityName()
)
);
}
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor == null ) {
return null;
}
return (LazyAttributeLoadingInterceptor) interceptor;
}
@Override
public LazyAttributeLoadingInterceptor injectInterceptor(Object entity, SharedSessionContractImplementor session) {
if ( !enhancedForLazyLoading ) {
throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + "] is not enhanced for lazy loading" );
}
if ( !entityClass.isInstance( entity ) ) {
throw new IllegalArgumentException(
String.format(
"Passed entity instance [%s] is not of expected type [%s]",
entity,
getEntityName()
)
);
}
final LazyAttributeLoadingInterceptor interceptor = new LazyAttributeLoadingInterceptor(
getEntityName(),
lazyAttributesMetadata.getLazyAttributeNames(),
session
);
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( interceptor );
return interceptor;
}
/**
* Check if the property is initialized. If the named property does not exist
* or is not persistent, this method always returns <tt>true</tt>.
*
* @param proxy The potential proxy
* @param propertyName the name of a persistent attribute of the object
* @return true if the named property of the object is not listed as uninitialized; false otherwise
*/
public static boolean isPropertyInitialized(Object proxy, String propertyName) {
final Object entity;
if ( proxy instanceof HibernateProxy ) {
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
return false;
}
else {
entity = li.getImplementation();
}
}
else {
entity = proxy;
}
if ( entity instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
return ( (LazyAttributeLoadingInterceptor) interceptor ).isAttributeLoaded( propertyName );
}
}
return true;
}
protected void addInterceptorHandling(CtClass managedCtClass) {
// interceptor handling is only needed if class has lazy-loadable attributes
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) {
return;
}
log.debugf( "Weaving in PersistentAttributeInterceptable implementation on [%s]", managedCtClass.getName() );
managedCtClass.addInterface( loadCtClassFromClass( PersistentAttributeInterceptable.class ) );
FieldWriter.addFieldWithGetterAndSetter(
managedCtClass,
loadCtClassFromClass( PersistentAttributeInterceptor.class ),
EnhancerConstants.INTERCEPTOR_FIELD_NAME,
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
EnhancerConstants.INTERCEPTOR_SETTER_NAME
);
}
private DynamicType.Builder<?> addInterceptorHandling(DynamicType.Builder<?> builder, TypeDescription managedCtClass) {
// interceptor handling is only needed if class has lazy-loadable attributes
if ( enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) {
log.debugf( "Weaving in PersistentAttributeInterceptable implementation on [%s]", managedCtClass.getName() );
builder = builder.implement( PersistentAttributeInterceptable.class );
builder = addFieldWithGetterAndSetter(
builder,
PersistentAttributeInterceptor.class,
EnhancerConstants.INTERCEPTOR_FIELD_NAME,
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
EnhancerConstants.INTERCEPTOR_SETTER_NAME
);
}
return builder;
}
private boolean isEnhanced(final Class<?> modifiedClass) {
Set<Class> interfaces = new HashSet<Class>(Arrays.asList(modifiedClass.getInterfaces()));
//Assert it now implements these three interfaces:
return interfaces.contains(ManagedEntity.class) &&
interfaces.contains(PersistentAttributeInterceptable.class) &&
interfaces.contains(SelfDirtinessTracker.class);
}
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() );
}
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
);
}
@Override
public void afterInitialize(Object entity, SharedSessionContractImplementor 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 ) {
final LazyAttributeLoadingInterceptor interceptor = getEntityMetamodel().getBytecodeEnhancementMetadata().extractInterceptor( entity );
if ( interceptor == null ) {
getEntityMetamodel().getBytecodeEnhancementMetadata().injectInterceptor( entity, session );
}
else {
if ( interceptor.getLinkedSession() == null ) {
interceptor.setSession( session );
}
}
}
// clear the fields that are marked as dirty in the dirtyness tracker
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
}
@SuppressWarnings("SimplifiableIfStatement")
private static boolean isInitialized(PersistentAttributeInterceptable interceptable) {
final LazyAttributeLoadingInterceptor interceptor = extractInterceptor( interceptable );
return interceptable == null || interceptor == null || !interceptor.hasAnyUninitializedAttributes();
}
@Override
public void clear() {
for ( Object o : proxiesByKey.values() ) {
if ( o == null ) {
//entry may be GCd
continue;
}
((HibernateProxy) o).getHibernateLazyInitializer().unsetSession();
}
for ( Entry<Object, EntityEntry> objectEntityEntryEntry : entityEntryContext.reentrantSafeEntityEntries() ) {
// todo : I dont think this need be reentrant safe
if ( objectEntityEntryEntry.getKey() instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) objectEntityEntryEntry.getKey() ).$$_hibernate_getInterceptor();
if ( interceptor instanceof LazyAttributeLoadingInterceptor ) {
( (LazyAttributeLoadingInterceptor) interceptor ).unsetSession();
}
}
}
for ( Map.Entry<PersistentCollection, CollectionEntry> aCollectionEntryArray : IdentityMap.concurrentEntries( collectionEntries ) ) {
aCollectionEntryArray.getKey().unsetSession( getSession() );
}
arrayHolders.clear();
entitiesByKey.clear();
entitiesByUniqueKey.clear();
entityEntryContext.clear();
// entityEntries.clear();
parentsByChild.clear();
entitySnapshotsByKey.clear();
collectionsByKey.clear();
collectionEntries.clear();
if ( unownedCollections != null ) {
unownedCollections.clear();
}
proxiesByKey.clear();
nullifiableEntityKeys.clear();
if ( batchFetchQueue != null ) {
batchFetchQueue.clear();
}
// defaultReadOnly is unaffected by clear()
hasNonReadOnlyEntities = false;
if ( loadContexts != null ) {
loadContexts.cleanup();
}
naturalIdXrefDelegate.clear();
}
private void createClearDirtyCollectionMethod(CtClass managedCtClass) throws CannotCompileException {
try {
final StringBuilder body = new StringBuilder();
body.append(
String.format(
"private void %1$s() {%n" +
" if (%2$s == null) { %2$s = new %3$s(); }%n" +
" %4$s lazyInterceptor = null;%n",
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME,
COLLECTION_TRACKER_IMPL,
LazyAttributeLoadingInterceptor.class.getName()
)
);
if ( PersistentAttributesHelper.isAssignable( managedCtClass, PersistentAttributeInterceptable.class.getName() ) ) {
body.append(
String.format(
" if(%1$s != null && %1$s instanceof %2$s) lazyInterceptor = (%2$s) %1$s;%n%n",
EnhancerConstants.INTERCEPTOR_FIELD_NAME,
LazyAttributeLoadingInterceptor.class.getName()
)
);
}
for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
body.append(
String.format(
" // collection field [%1$s]%n" +
" if (lazyInterceptor == null || lazyInterceptor.isAttributeLoaded(\"%1$s\")) {%n" +
" if (%1$s == null) { %2$s.add(\"%1$s\", -1); }%n" +
" else { %2$s.add(\"%1$s\", %1$s.size()); }%n" +
" }%n%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
body.append( "}" );
MethodWriter.write( managedCtClass, body.toString() );
}
catch (CannotCompileException cce) {
throw cce;
}
}
/**
* Binds a property to Hibernate runtime meta model. Deals with cascade strategy based on the Grails domain model
*
* @param grailsProperty The grails property instance
* @param prop The Hibernate property
* @param mappings The Hibernate mappings
*/
protected void bindProperty(PersistentProperty grailsProperty, Property prop, InFlightMetadataCollector mappings) {
// set the property name
prop.setName(grailsProperty.getName());
if (isBidirectionalManyToOneWithListMapping(grailsProperty, prop)) {
prop.setInsertable(false);
prop.setUpdateable(false);
} else {
prop.setInsertable(getInsertableness(grailsProperty));
prop.setUpdateable(getUpdateableness(grailsProperty));
}
AccessType accessType = AccessType.getAccessStrategy(
grailsProperty.getMapping().getMappedForm().getAccessType()
);
if(accessType == AccessType.FIELD) {
EntityReflector.PropertyReader reader = grailsProperty.getReader();
Method getter = reader != null ? reader.getter() : null;
if(getter != null && getter.getAnnotation(Traits.Implemented.class) != null) {
prop.setPropertyAccessorName(TraitPropertyAccessStrategy.class.getName());
}
else {
prop.setPropertyAccessorName( accessType.getType() );
}
}
else {
prop.setPropertyAccessorName( accessType.getType() );
}
prop.setOptional(grailsProperty.isNullable());
setCascadeBehaviour(grailsProperty, prop);
// lazy to true
final boolean isToOne = grailsProperty instanceof ToOne && !(grailsProperty instanceof Embedded);
PersistentEntity propertyOwner = grailsProperty.getOwner();
boolean isLazyable = isToOne ||
!(grailsProperty instanceof Association) && !grailsProperty.equals(propertyOwner.getIdentity());
if (isLazyable) {
final boolean isLazy = getLaziness(grailsProperty);
prop.setLazy(isLazy);
if (isLazy && isToOne && !(PersistentAttributeInterceptable.class.isAssignableFrom(propertyOwner.getJavaClass()))) {
// handleLazyProxy(propertyOwner, grailsProperty);
}
}
}
private static LazyAttributeLoadingInterceptor extractInterceptor(PersistentAttributeInterceptable interceptable) {
return (LazyAttributeLoadingInterceptor) interceptable.$$_hibernate_getInterceptor();
}