Hi everyone.
I have the following situation: suppose I have an application that allows users to register if they don't have an account yet. The form takes the new user's login and password, and passes that to a method in an instance of a stateful session bean (User is an entity, and the specs state login should be unique accross the whole system):
Code:
User currentUser = ... // create the current instance based on the form input
//this was passed with the @In annotation from Seam in the original listing
...
public String doRegister() {
List existing = em.createQuery("select u.username from User u where u.username = :login").setParameter("login", currentUser.getUsername())
.getResultList();
if (existing.size() != 0) {
facesMessages.add("User exists!");
return null;
} else {
em.persist(currentUser);
facesMessages.add("Registration complete.");
return "login";
}
}
(The above listing originates from listing 17.16, "Java Persistance with Hibernate"- a great book by the way, thanks for that guys!)
Suppose two new users are simultanously trying to register, with the same login. What happens is:
1. user A calls this method, and there is not a user with this login
2. user hasn't pressed the OK button that would create the new account
3. now user B calls the same method, and there still is no user with the login they chose, so everyone is happy
4. now user A commits the transaction, persisting the new User instance
5. user B tries to commit the transaction, but this time the login already exists (user A was there first)!
What we have now is that there are two users with the same login, which violates the rule. If we add a unique constraint on the LOGIN column, user B will get an exception of some type.
Is this what should happen? I mean, maybe Hibernate gives another, more elegant, solution? How should situations like that be dealt with? Some locks or something? But locking would prevent others from registering if user A went for lunch.
Thanks.