-->
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.  [ 8 posts ] 
Author Message
 Post subject: Associate new Object behaviour like loaded object behaviour
PostPosted: Fri Aug 11, 2006 8:34 am 
Newbie

Joined: Mon Sep 19, 2005 3:08 am
Posts: 19
Example:


UserRole u = getById(UserRole.class, userId, roleId);
....
User user = u.getUser();(*)

hibernate will return user assigned to this UserRole class and this is OK,

but

UserRole u = new UserRole(userId, roleId, dateEntered);
this.insert(u);
User user = u.getUser();(**)

this will return NULL for user.

How to make that (**) return user object as (*)?

in UserRole.hbm file I have something like:
...
<many-to-one name="user" class="User" fetch="select" >
<column name="userId" not-null="true" />
</many-to-one>
..


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 11, 2006 8:48 am 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
Need to see the code for this UserRole constructor:

Code:
UserRole u = new UserRole(userId, roleId, dateEntered);


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 11, 2006 9:35 am 
Newbie

Joined: Mon Sep 19, 2005 3:08 am
Posts: 19
Ananasi wrote:
Need to see the code for this UserRole constructor:

Code:
UserRole u = new UserRole(userId, roleId, dateEntered);

This is just example, same will happen with this constructor:
Code:
UserRole u = new UserRole(userId, roleId);

dateEntered is here just to see that there can be more fields.

Code:
public UserRole(Integer userId, Integer roleId, Date dateEntered) {
this.userId = userId;
this.roleId = roleId;
this.dateEntered = dateEntered;
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 11, 2006 10:30 am 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
Pass actual User and Role objects to a constructor instead of passing just the foreign keys, and then construct it using those objects.

Code:
public UserRole(User user, Role role, Date dateEntered) {
this.user = user;
user.getUserRoles.add(this);
this.role = role;
role.getUserRoles.add(this);
this.dateEntered = dateEntered;
}


The this.user = user and user.getUserRoles.add(this) will associate the User object to the UserRole and vice versa, and the this.role = role and role.getUserRoles.add(this) will associate the Role to the UserRole and vice versa. If Hibernate is configured properly, then it will handle the associations and insertions. There are a couple ways this code can be improved (getUserRoles() in the User and Role classes needs to be null safed wrt the collections, probably better to add the bidirectional pairings in the setUser() and setRole() methods of the UserRole class and then call those in the constructor).

Do yourself a favor and pass around references to the POJOs instead of the primary keys (the only place I ever use the primary keys are in load methods to load a single POJO). Break out of those JDBC/SQL shackles and be free! :D


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 2:36 am 
Newbie

Joined: Mon Sep 19, 2005 3:08 am
Posts: 19
Ananasi wrote:
Pass actual User and Role objects to a constructor instead of passing just the foreign keys, and then construct it using those objects.

Code:
public UserRole(User user, Role role, Date dateEntered) {
this.user = user;
user.getUserRoles.add(this);
this.role = role;
role.getUserRoles.add(this);
this.dateEntered = dateEntered;
}


Ok, I know that, but I'm want to avoid extra coding. With this solution I need to read user and role object by my self. In first example:
Code:
UserRole u = getById(UserRole.class, userId, roleId);
User user = u.getUser();(*)
hibernate will return user assigned to this UserRole class and this is OK,

hibernate do all reading, and in this example you posted, I have to read it and add it, and I want to avoid that.
Is there a way that hibernate do that for me as in (*) example?

It is weird that after:
Code:
UserRole u = getById(UserRole.class, userId, roleId);
User user = u.getUser();(*)


and after this:
Code:
UserRole u = new UserRole(userId, roleId, dateEntered);
this.insert(u);
User user = u.getUser();(**)


or
Code:
UserRole u = new UserRole(userId, roleId, dateEntered);
this.insert(u);
UserRole u = getById(UserRole.class, userId, roleId);
User user = u.getUser();(***)


user object returned from (*) is realy User object, and
user object returned from (**) and (***) is null?

Note than in (*) and (***) I have same code for reading userRole and user object!!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 8:54 am 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
After the insert, Hibernate will use it's first level cache to resolve the UserRole after insertion. By using the foreign keys to insert data, it will not resolve the joined classes until the UserRole object is evicted. If you have to do it this way, after your insert, evict the UserRole object and then reread it from Hibernate. For example,

Code:
UserRole u = new UserRole(userId, roleId, dateEntered);
this.insert(u);
hibernateSession.evict(u); <=====
UserRole u = getById(UserRole.class, userId, roleId);
User user = u.getUser();


An alternative to evicting and rereading is to resolve the associations inside the aforementioned constructor, but that introduces a strong dependecy on Hibernate in your domain layer, not a good thing to say the least.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 9:38 am 
Newbie

Joined: Mon Sep 19, 2005 3:08 am
Posts: 19
Ananasi wrote:
After the insert, Hibernate will use it's first level cache to resolve the UserRole after insertion. By using the foreign keys to insert data, it will not resolve the joined classes until the UserRole object is evicted. If you have to do it this way, after your insert, evict the UserRole object and then reread it from Hibernate. For example,

Code:
UserRole u = new UserRole(userId, roleId, dateEntered);
this.insert(u);
hibernateSession.evict(u); <=====
UserRole u = getById(UserRole.class, userId, roleId);
User user = u.getUser();


An alternative to evicting and rereading is to resolve the associations inside the aforementioned constructor, but that introduces a strong dependecy on Hibernate in your domain layer, not a good thing to say the least.


Code:
UserRole ur = new UserRole(userId, roleId, dateEntered);
this.insert(ur);
[i]- ur after this method should be same as this ur:[/i]
UserRole ur = getById(UserRole.class, userId, roleId);

and this make sense, but it is not the case...

So, after insert, I need to evict inserted data, and hibernate will than read same data as evicted data from database and than associate foreign keys to joinned classes.
There is one unnecessary reading from database!
Is this a bug in hibernate logic?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 9:52 am 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
Nope, it's just a consequence of loading your domain object using the foreign keys instead of the foreign domain objects. Really, we are only talking a couple lines of code here:

In UserRole.java:
Code:
public UserRole(User user, Role role, Date dateEntered) {
this.user = user;
user.getUserRoles.add(this);
this.role = role;
role.getUserRoles.add(this);
this.dateEntered = dateEntered;
}


Service layer method:
Code:
public UserRole createUserRole(Integer userId, Integer roleId, Date dateEntered) {
  User user = userDao.getUser(userId);
  Role role = roleDao.getRole(roleId);
  UserRole userRole = new UserRole(user, role, dateEntered);
  session.insert(userRole);
  return userRole;
}


This maintains your flexibility to create objects using their foreign keys, but will still associate the User and Role objects properly while maintaining proper separation of concerns.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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.