I'm doing my first steps with Hibernate and came across a (beginner's?) problem which I was unable to solve.
I reduced the problem to a tiny example to clarify the problem.
The domain objects in this example are:
- User
- Role
where the user has (or rather: must have) one role.
The Hibernate Mappings look as follows:
[User.hbm.xml]
Code:
<hibernate-mapping>
<class name="idx.forum.bean.User" table="users">
<id name="id" type="integer" column="id" unsaved-value="null">
<generator class="hilo"/>
</id>
<property name="login" type="string" column="login" unique="true"
not-null="true" length="16" />
<property name="password" type="string" column="pwd" not-null="true"
length="16" />
<many-to-one name="role" class="idx.forum.bean.Role" column="role"
not-null="true" />
</class>
</hibernate-mapping>
[Role.hbm.xml]
Code:
<hibernate-mapping>
<class name="idx.forum.bean.Role" table="roles">
<id name="id" type="integer" column="id" unsaved-value="null">
<generator class="hilo"/>
</id>
<property name="name" type="string" column="name" unique="true"
not-null="true" length="16" />
</class>
</hibernate-mapping>
Now I created a role, stored it, created a user, assigned the role to the user, and stored it too.
That worked very well, and the new records show in the DB as intended:
Code:
Table 'users':
oid=35510
id=32768
login=pwalser
pwd=abcde
first_name=Peter
last_name=Walser
role=1
Table 'roles':
oid=35506
id=1
name=Developer
Then I tried to read the user and its role from the DB using Hibernate:
(Note: the user and role's toString() methods just print the properties and their values)
Code:
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=session=sessionFactory.openSession();
Transaction tx=session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
Iterator users=criteria.list().iterator();
while (users.hasNext())
{
User user=(User)users.next();
System.out.println(user.getLogin()+" is a "+user.getRole().getName());
System.out.println(user.getRole());
}
tx.commit();
session.flush();
session.close();
Output:
- pwalser is a
null- Role [id=1, name=Developer ]
Expected result would be:
- pwalser is a
Developer- Role [id=1, name=Developer ]
The user has been read correctly, the correct role is attached also but hasn't been populated with the data from the DB (role.getId() and role.getName() are both null).
The toString() method however returns the values as if the role had been initialized correctly, even if both properties are null (due to the bytecode enhancements).
I consulted some books and online tutorials, which hinted out that the Role population can be invoked using Hibernate.initialize(Object).
Unfortunately this didn't solve my problem:
Code:
while (users.hasNext())
{
User user=(User)users.next();
System.out.println("Initialized: "+Hibernate.isInitialized(user.getRole()));
Hibernate.initialize(user.getRole());
System.out.println("Initialized: "+Hibernate.isInitialized(user.getRole()));
System.out.println(user.getLogin()+" is a "+user.getRole().getName());
System.out.println(user.getRole());
}
Output:
- Initialized: false
- Initialized: true
- pwalser is a null
- Role [id=1, name=Developer ]
Note: when I output the user and its role in the same session that created them, the output is correct ("pwalser is a Developer"), but I suppose this is due to caching.
I'm totally puzzled now.
Perhaps one of you sees a mistake and may give me some hints about what's wrong or what's missing?
Lots of thanks in advance,
Peter :)