PDA

View Full Version : why HibernateTemplate.FindByNamedParam try to persist changed instance?


tariq.tong
05-23-2007, 04:01 AM
I met a problem when use HibernateTemplate.FindByNamedParam to query database. It seems FindByNamedParam tries to persist changed instances when executing, which is expected not to. While I'm not sure it's HibernateTemplate.FindByNamedParam try to do this.

The problem is:
You can refer to the DAO Layer code below, a duplicated key sql exception of db updating thrown in the line of HibernateTemplate.FindByNamedParam(.......).

The scenario is:
A user want to update her user information, e.g. username, while username is not allowed to duplicate with others'.

The code sequence is as follows:
Presentation layer uses OpenSessionInView mode.
1. in presentation layer get the user persistent instance from service layer
2. in presentation layer update the user's username to duplicate with another user's username
3. in presentation layer call saveOrupdate method of service layer to verify duplication and persist the changed instance if verification OK

The code is like this:
Presentation Layer

//code below is in one session
User user= UserService.FindUserById(userId); //FindUserById is in a transaction
...
user.Username = "xxx"; //"xxx" duplicate with another user

UserService.SaveOrUpdate(user); //SaveOrUpdate is in another transaction


Service Layer

[Transaction()]
public bool SaveOrUpdate(User user)
{
try
{
User existUser = UserDAO.FindByUsername(user.Username);
if (existUser != null && existUser.Id != user.Id)
return false;

existUser = UserDAO.FindByEmail(user.Email);
if (existUser !=null && existUser.Id != user.Id)
return false;

UserDAO.SaveOrUpdate (user);
return true;
}
catch (Exception e)
{
throw new ServiceException(e.Message, e);
}
}


DAO Layer

public User FindByUsername(string username)
{
IList users = HibernateTemplate.FindByNamedParam("from User user " +
"where user.Username = :username",
"username",
username);
if (users != null && users.Count == 1)
return users[0] as User;
else if (users == null || users.Count ==0)
return null;
else
throw new DataAccessException("More than one user with the same username.");
}


Hope to get your help soon.
Thank you very much!
Tariq