I've been wreaking havoc on the Struts mailing list with a related issue, but I believe I have everything sorted out. Never the one to leave a solved issue without a published solution (I HATE finding replies that say, "I solved it!" with no further explanation!), here's what I've come up with:
Prerequisites: Class entityClass, Configuration configuration, custom Iterable converter for an iterator (I heart Java 5), SessionFactory sessionFactory
Code:
PersistentClass entityMapping = configuration.getClassMapping( entityClass );
Property idProperty = entityMapping.getIdentifierProperty();
for ( Property property : getProperties( entityMapping ) )
{
Type type = property.getType();
if ( type.isEntityType() )
{
if ( ( (EntityType)type ).isOneToOne() )
{
// one-to-one
}
else
{
// many-to-one
}
}
else if ( type.isCollectionType() )
{
PersistentClass associatedClass = configuration.getClassMapping( ( (AssociationType)type ).getAssociatedEntityName( (SessionFactoryImplementor)sessionFactory ) );
try
{
associatedClass.getProperty( entityClass.getName() );
// one-to-many
}
catch ( MappingException e )
{
try
{
associatedClass.getProperty( pluralize( entityName ) );
// many-to-many
}
catch ( MappingException e )
{
// Double-U Tee Ef?
throw something;
}
}
}
else
{
// basic property
}
}
Couple of points:
1) This is a highly abbreviated version of my copy, I tried to keep it as simple as I could. It contains errors, because I typed it by reference, didn't test it, and assume people interested in my problem can figure things out well enough from what I've written.
2) This is not as generic as it could be--it relies on my own design habits towards entities (hence the "pluralize" thing).
3) IMHO (to the Hibernate developers): it might be nice to get rid of the getXXXIterator() methods, and return the full map/list/set instead. Worried about modifications? Use Collections.unmodifiableXXX(). I've done a few benchmarks on the differences myself, and found none. I know this is anecdotal, but certain situations make the whole iterator vs. collection thing a little cumbersome to code around.
4) I don't particularly like the lines reading "associatedClass.getProperty(...)" surrounded by try/catch. The first situation is an expected one (many-to-many instead of one-to-many) and shouldn't need an exception handler that gets hit on an expected condition. It's likely a combination of my method and my lack of knowledge on how the configuration-related classes work, but I thought I'd point it out anyways.
5) I'm a little confused about having to cast a SessionFactory to a SessionFactoryImplementor. Is this a no-no? (Bonus: Why does the getAssociatedEntityName need it?)
6) I really, really hope I can cache the Getter and Setter objects returned by property.getGetter() and property.getSetter().
7) The "deprecated" JavaDoc (or better yet, the Deprecated annotation) is a much, much, much better IDE-friendly alternative to "// todo : remove" for prospective developers (See org.hibernate.mapping.Property). I wasted a few hours trying to figure out what was going on with the getMethod() accessor of (S|G)etter before I tried (g|s)et() instead.
8) A textarea control is a really bad place to type code.
9) Apparently, "couple" doesn't always mean 2.
10) (The most important point): Thanks tenwit! :)
- sil
BTW: The ordered list tag doesn't seem to work... and phpbb.com isn't responding (?).