Irons UK wrote:
Pulseammo, I've been following this thread out of interest. Can you help me understand how you have created a transient instance of Foo in your code example?
From what I understand the instance of Foo will be persisted when you flush the session. Is this not the case?
Thanks,
-Irons
Of course, I'll try to explain as best as I can (Long post coming up, skip to "HERES THE ANSWER" if you want it in short ;P).
Ok, first it's important to know a bit about a certain feature of Java, to do with the class loader, I think (I'm not quite sure, this may be part of the reflection API).
So first, you need to know the "different" way to instantiate a class without using the "new" keyword, lets take an example:
Code:
String s = String.class.newInstance();
The above code is just like calling:
Code:
String s = new String();
(i.e. the new keyword is prolly just some syntactical sugar).
When calling String.class, a Class object is returned, with the parametrised type (as in generics) of String, in full Class<String>.
Now, why does this matter? In hibernate you can map with:
Code:
<class entity-name="Foo" name="beans.HibernateFoo" table="foo">
i.e. I've simplified my mapping name down to "Foo" instead of "beans.HibernateFoo". So at runtime I need to know, what Class object has the string "Foo" been mapped to? This is held inside the SessionFactory.getClassMetaData(String entity-name) mapping.
Now, if I call something in hibernate like:
Code:
Session s = SessionFactory.getCurrentSession();
s.get("Foo", 1);
first of all, that ID needs to exist in the database, and second of all, yes, the get method will generate a persistent object (it's obviously also not a blank object etc, but the idea here is the a method called on session is linked into the persistence stuff).
Now
HERE's THE ANSWER COMING UP ;)!
The reason that hibernate doesn't create a persistent object, is because the code:
Code:
SessionFactory.getClassMetaData("Foo").getMappedClass(EntityMode e);
is NOT linked to the database or persistence mechanism, it is only a mapping file generated from your XML, one of whose functions is to return a entity-name to Class object mapping (getMappedClass method).
In this case, getMappedClass will return a Class<Foo> object, and using the beginning of my post, you use plain old java tricks to instantiate a new one:
Code:
Class<Foo> f = SessionFactory.getClassMetaData("Foo").getMappedClass(EntityMode e);
Foo f = f.newInstance();
Remembering all the while that newInstance() is in no way linked to hibernate, and that Foo is merely an interface! You've therefore decoupled your app, and got your DAO class to build you a new HibernateFoo.
NOTE:
This only has purpose if you use the GenericHibernateDao abstract superclass for your DAO subclasses, if you don't, then you may as well hardwire each of your DAO class create methods to return their specific subtype, then you're still decoupled:
Code:
public class HibernateFooDao implements FooDao {
public Foo create() {
return new HibernateFoo();
}
}
This would also be ok, but you have masses of extra code to write by not using the GenericHibernateDao class found here:
http://www.hibernate.org/328.html
I hope this wasn't too much of a difficult read there. Does that make sense Irons? I can try again ;). Also, you understand why I want to do things this way with the generic hibernate dao classes rather than hard wire each individual dao right?
Hope this helps!