Eager loading - HHH-3552
aslak Jun 2, 2009 8:37 AMHi Adam!
I've been banging my head agains the wall due to lack of http://opensource.atlassian.com/projects/hibernate/browse/HHH-3552 for some time now..
so long that I figured I would have a go at it.. :)
The easies way, as far as I can see(without having any deep understanding of the code) seems to be to add a set of Eager proxies
the same way the Lazy proxies are added, but without the lazy loading of the delegate from the Initializor.
This is what I've changed so far..
public class PropertyAuditingData { ... private String fetchType = "LAZY"; ... public String getFetchType() { return fetchType; } public void setFetchType(String fetchType) { this.fetchType = fetchType; } ... } public class AuditedPropertiesReader { ... private boolean fillPropertyData(XProperty property, PropertyAuditingData propertyData, ... setFetchMode(property, propertyData); ... } private void setFetchMode(XProperty property, PropertyAuditingData propertyData) { OneToMany oneToMany = property.getAnnotation(OneToMany.class); if(oneToMany != null) { propertyData.setFetchType(oneToMany.fetch().toString()); } ManyToOne manyToOne = property.getAnnotation(ManyToOne.class); if(manyToOne != null) { propertyData.setFetchType(manyToOne.fetch().toString()); } OneToOne oneToOne = property.getAnnotation(OneToOne.class); if(oneToOne != null) { propertyData.setFetchType(oneToOne.fetch().toString()); } ManyToMany manyToMany = property.getAnnotation(ManyToMany.class); if(manyToMany != null) { propertyData.setFetchType(manyToMany.fetch().toString()); } } .., } public final class CollectionMetadataGenerator { ... private void addMapper(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData) { ... } else if (type instanceof BagType) { Class<? extends List> listProxyType = ListProxy.class; if("EAGER".equals(propertyAuditingData.getFetchType())) { listProxyType = EagerListProxy.class; } currentMapper.addComposite(propertyAuditingData.getPropertyData(), new BasicCollectionMapper<List>(commonCollectionMapperData, ArrayList.class, listProxyType, elementComponentData)); } else if (type instanceof ListType) { ... } ... } public abstract class EagerCollectionProxy<U, T extends Collection<U>> implements Collection<U>, Serializable { ... public EagerCollectionProxy(Initializor<T> initializor) { delegate = initializor.initialize(); } ... } public class EagerListProxy<U> extends EagerCollectionProxy<U, List<U>> implements List<U>, Serializable { ... public EagerListProxy(org.hibernate.envers.entities.mapper.relation.lazy.initializor.Initializor<List<U>> initializor) { super(initializor); } ... }
The code above only add eager support to JPA annotated beans of BagType for now..
Is this the right way to go?
Some questions:
How to add support for eager loading based on hibernate xml configuration? (is it even supported?)
All the org.hibernate.envers.entities.mapper.relation PropertyMapper implementations seem to be tightly connected
to the org.hibernate.envers.entities.mapper.relation.lazy.initializor.Initializor implementations witch is a part of the lazy package.
Should the Initializors be moved out of the lazy package to a higher level and reused inbetween eager/lazy, or should there be implemented a new set of mappers to create the eager proxies(maybe use the value directly, without the need for a proxy)?
IE:
protected AbstractCollectionMapper(CommonCollectionMapperData commonCollectionMapperData, Class<? extends T> collectionClass, Class<? extends T> proxyClass) { this.commonCollectionMapperData = commonCollectionMapperData; this.collectionClass = collectionClass; try { proxyConstructor = proxyClass.getConstructor(Initializor.class); } catch (NoSuchMethodException e) { throw new AuditException(e); } }
Are there other parts that need changes??
-aslak-