[Hibernate] HB3 Code Metrics

2005-02-06 Thread Gavin King
According to sloccount,
Hibernate3/src/: 63,401 LOC
Hibernate3/test/: 25,132 LOC (Java code only, XML not counted)
HibernateExt/: 25,331 LOC (Java code only)
So, we are way past 100 000 LOC total….
;)
--
Gavin King
+61 410 534 454
+1 404 822 8349
callto://gavinking
Hibernate
[EMAIL PROTECTED]
http://hibernate.org
JBoss Inc
[EMAIL PROTECTED]
http://jboss.com

---
This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting
Tool for open source databases. Create drag-&-drop reports. Save time
by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc.
Download a FREE copy at http://www.intelliview.com/go/osdn_nl
___
hibernate-devel mailing list
hibernate-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/hibernate-devel


[Hibernate] Is it worth contributing this code or posting it somewhere?

2005-02-06 Thread Adrian Ridner
I would like your opinion if this code is the type of thing you would ever add to Hibernate or if we should take the time to post it in our website for download.  I saw some postings in the User Forum asking for similar things, but you guys would know better.  It is currently working with Hibernate 2.1.8. The code deals with having everything in the mapping files be lazy="true"  and allowing the user to load an object and specify the object graph to load for that object in the code. Instead of using Hibernate.initialize() (n+1 queries approach), it optimizes said queries by using left join fetch on all the properties and all collections, being "smart" enough to issue only one query per collection. Note the number of properties loaded does not affect the number of queries issued.

The code below is a sample from one of our DAOs, which extends from our BaseHibernateDAO (it has convenience methods and object graph loading methods). I indented it one more level every time an object is added for a deeper node in the graph (I doubt all mail clients will maintain the indentation, and it helps quite a bit, so I posted it here also http://remilon.com/maintainindentation.html ). WIthout getting into a lot schema specifics, it loads an 'Advertisement' bean and a variety of its collections and their objects. This is a particularly deep object graph, as an illustration.

public Advertisement getAdvertisementTree(int advertisementId) {
LazyInitializer init = new LazyInitializer();
init

.addCollection(Advertisement.COL_ADVERTISEMENTKEYPHRASES_BY_ADVERTISEMENT_ID, "advkp")
.addNamedProperty("advkp", Advertisementkeyphrase.PROP_KEYPHRASE, "kp")
.addNamedProperty("kp", Keyphrase.PROP_PHRASE)
.addNamedCollection("advkp", Advertisementkeyphrase.COL_ARTIFACTS, "art1")
.addNamedCollection("art1", Artifact.COL_BIDS)
.addNamedCollection("art1", Artifact.COL_DESTINATION_PAGES, "destpg1")
.addNamedProperty("destpg1", DestinationPage.PROP_SITE)
.addNamedCollection("art1", Artifact.COL_ROUTINGS, "routings1")
.addNamedProperty("routings1", Routing.PROP_SITE)
.addCollection(Advertisement.COL_CREATIVES_BY_ADVERTISEMENT_ID, "ct")
.addNamedProperty("ct", Creative.PROP_ARTIFACT, "art2")
.addNamedCollection("art2", Artifact.COL_BIDS)
.addNamedCollection("art2", Artifact.COL_DESTINATION_PAGES, "destpg2")
.addNamedProperty("destpg2", DestinationPage.PROP_SITE);
.addNamedCollection("art2", Artifact.COL_ROUTINGS, "routings2")
.addNamedProperty("routings2", Routing.PROP_SITE);


Map wMap = new HashMap();
wMap.put("id", new Integer(advertisementId));

// This specifies the where conditions, order by, paging and if it is loading a collection 
// or single object as the root node
FetchRestrictionParameters params = new FetchRestrictionParameters(init);
params.setWhereCondition("ad.advertisementId = :id");
params.setWhereParameters(wMap);

return (Advertisement)loadClassFetchByRestriction(Advertisement.class, "ad", params);
}	  

The constants in the different beans (ie. Advertisementkeyphrase.PROP_KEYPHRASE) represent the java names for the properties and collections (obviously prefixed...). We actually have an ant task that runs after hbm2java that reads the mapping files and automatically adds all those to the base beans, because we are lazy ;) The possible signatures are: 

.addNamedProperty(String aliasOfObjectToLoadPropertyFrom, String propertyName, String aliasForThisNewProperty)
.addNamedCollection(String aliasOfObjectToLoadCollectionFrom, String collectionName, String aliasForThisNewCollection)

// alias not needed if you won't be loading objects of the node
.addNamedProperty(String aliasOfObjectToLoadPropertyFrom, String propertyName)
.addNamedCollection(String aliasOfObjectToLoadCollectionFrom, String collectionName)

Does this make sense?  Is this something that would interest anyone and how should we proceed?

For those who made it this far and care, here is some specific background:

We have worked with Hibernate for a while now, and it is a great product! We develop both web apps and standalone apps, dealing with medium-sized databases: ~40-70 tables (largest table holding ~5-10 million rows). After 6 to 9 months though, we started noticing the following 'deficiencies' in our code base:

1- Multiple apps that access the same DBs duplicated mapping files, POJOs and queries/ dao code which could be re-used. 
2- We were not automatically generating said mapping files and POJOs. 
3- There were a lot of queries being issued for deeper object graphs with lots of collections, regardless if we used lazy="false" or Hibernate.initialize() (n+1 issue...)

We quickly realized the best strategy *for us* was to have all the the files auto-generated from the schema (bottom up approach). This was easily achieved by customizing some of the middlegen velocity scripts (fixing some minor conflicts, adding a few options, etc.) and then running hbm2java. I have not fully read the changes in the Hibernate 3 toolset, but it appears these tools are getti