-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Problem with lazy initialization
PostPosted: Thu Nov 24, 2005 5:21 am 
Newbie

Joined: Wed Nov 23, 2005 11:27 am
Posts: 7
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 :)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 8:39 am 
Senior
Senior

Joined: Mon Aug 22, 2005 5:45 am
Posts: 146
could you post your hibernate.cfg.xml or whatever config you use to setup your SessionFactory, pls.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 9:50 am 
Newbie

Joined: Wed Nov 23, 2005 11:27 am
Posts: 7
axismundi wrote:
could you post your hibernate.cfg.xml or whatever config you use to setup your SessionFactory, pls.


My 'hibernate.cfg.xml':

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration
    PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

   <!-- Generated by idxCodegen -->

   <session-factory>

   <property name="connection.driver_class">org.postgresql.Driver</property>
   <property name="connection.url">jdbc:postgresql://localhost:5432/idxblog_db</property>
   <property name="connection.username">idxblog_user</property>
   <property name="connection.password">????????</property>
   <property name="show_sql">true</property>
   <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
 
   <mapping resource="idx/forum/bean/User.hbm.xml"/>
   <mapping resource="idx/forum/bean/Role.hbm.xml"/>

   </session-factory>
   
</hibernate-configuration>


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 10:04 am 
Beginner
Beginner

Joined: Tue Nov 22, 2005 4:53 pm
Posts: 41
Location: Netherlands
What does your Role class looks like ?

Seeing that the the toString() returns correct values, tha last option I can think of is that the getters op the Role class aren't correct.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 10:10 am 
Senior
Senior

Joined: Mon Aug 22, 2005 5:45 am
Posts: 146
hm, the cfg.xml is standard and cannot be the root of your problem.

I wonder if you use hibernate 2 or 3?
Because since hibernate 3.0 lazy loading has been enabled by default.

but on the other hand, even if lazy loading is enabled user.getRole().getName() should work straightforward, at least as far as you don't deal with detached objects.

have you tried to remove your transaction management code?
I don't see that you need in here.
how about this code using hql:

SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=session=sessionFactory.openSession();
Iterator users=session.createQuery("from User").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());
}
session.close();

_________________
Please don't forget to give credit, if my posting helped to solve your problem.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 10:11 am 
Newbie

Joined: Wed Nov 23, 2005 11:27 am
Posts: 7
The Role bean is extended from a generated base class called RoleBase:

Code:
package idx.forum.bean;

public class Role extends idx.forum.bean.RoleBase
{

   public Role()
   {
   }
   
   public Role(String name)
   {
      setName(name);
   }
}


Base class:

Code:
package idx.forum.bean;

public abstract class RoleBase
{
   private String name;
   private Integer id;

   public final String getName()
   {
      return name;
   }

   public final void setName(String value)
   {
      this.name = value;
   }

   public final Integer getId()
   {
      return id;
   }

   public final void setId(Integer value)
   {
      this.id = value;
   }

   public String toString()
   {
      StringBuffer buffer = new StringBuffer();
      buffer.append("Role [");
      buffer.append("id=" + id + ", ");
      buffer.append("name=" + name + ", ");
      buffer.append("]");
      return buffer.toString();
   }
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 10:19 am 
Newbie

Joined: Wed Nov 23, 2005 11:27 am
Posts: 7
axismundi wrote:
I wonder if you use hibernate 2 or 3?

I'm using Hibernate 3.0.5

Quote:
but on the other hand, even if lazy loading is enabled user.getRole().getName() should work straightforward, at least as far as you don't deal with detached objects.


Yes, but in that case I would at least expect a LazyInitializationException to be thrown.

Quote:
have you tried to remove your transaction management code?

Yes, but it had no influence on the result.

Quote:
how about this code using hql: [...]


Just tired it, but the result remains the same...

I suppose that something very elemental is missing, I just can't figure out what. :(


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 10:25 am 
Senior
Senior

Joined: Mon Aug 22, 2005 5:45 am
Posts: 146
we got it:

"public final void setName(String value) "


never declare your bean-methods (getter/setters) final!

hibernate 3.0.5 does not warn on factory building, hibernate 3.1 does!

remove "final" and it will work.

_________________
Please don't forget to give credit, if my posting helped to solve your problem.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 10:42 am 
Newbie

Joined: Wed Nov 23, 2005 11:27 am
Posts: 7
axismundi wrote:
never declare your bean-methods (getter/setters) final!


Whew, now it works well!

Thanks a lot, axismundi, you saved my day :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.