2016-08-04 84 views
1

我正在用Spring MVC设计web应用程序。Java中服务层的多线程

我在安全更新电子邮件和注册新用户时遇到了一些问题。 电子邮件对每个用户都是唯一的。

这是我的方法,它是由控制器用于注册用户调用:

@Override 
    public void registerUser(Client newUser) throws DuplicateEmailException { 

     if(!isEmailUnique(newUser.getEmail())){ 
      throw new DuplicateEmailException("User with the same email is registered" 
        + " in system already"); 
     } 

     newUser.setPassword(encodePassword(newUser.getPassword())); 
     newUser.setRole(UserRole.ROLE_CLIENT); 
     newUser.setStatus(UserStatus.ACTIVE); 
     newUser.setEmailStatus(EmailStatus.NOTCONFIRMED); 
     newUser.setRegistrationTime(LocalDateTime.now()); 

     clientDao.save(newUser); 


    } 

这是更新的电子邮件方法:

@Override 
    public void updateUserEmail(String email, String newEmail, String password) 
      throws InvalidPasswordException, DuplicateEmailException { 
     Client client = getClientByEmail(email); 
     if(!isPasswordRight(password, client.getPassword())){ 
      throw new InvalidPasswordException("Password doesn't match to real"); 
     } 

     if(email.equals(newEmail)){ 
      return; 
     } 

     if(!isEmailUnique(newEmail)){ 
      throw new DuplicateEmailException(
        "Such email is registered in system already"); 
     } 

     client.setEmail(newEmail); 
     client.setEmailStatus(EmailStatus.NOTCONFIRMED); 
    } 

有可能的情况下,当某些用户点击按钮对于注册,registerUser(Client newUser)方法检查电子邮件的唯一性,同时第二个用户想要更新电子邮件,并且在clientDao.save(newUser)被调用之前,updateUserEmail(String email, String newEmail, String password)检查电子邮件的唯一性,如果两个用户的电子邮件是平等的,我会g等两个相同的电子邮件在db - 这是不可接受的。

我的服务层都标有@Translactional注解,会话自动关闭交易之前冲刷和用户保存在数据库整理registerUser(..)方法

所以以后只,请告诉我,我可以使用哪些工具在Java中的多线程为了解决这个问题?

回答

4

您可以通过将isEmailUnique方法滚动到保存功能并使save方法同步来以编程方式执行此操作。

更好的解决办法是让电子邮件列有一个唯一约束在DB,以确保没有重复都不能让它进入你的数据集无论身在何处的应用程序,或者甚至是应用程序,它们来自。

+0

但在我更新的电子邮件方法中,我没有使用save方法,我从db获取Client实例并在此持久实例上设置字段。 – Yuriy

+0

处理唯一性问题是您真正想避免在应用程序中执行的事情,如果您可以管理它。这是因为即使您在一个JVM中解决了并发问题,如果您横向扩展到应用程序的多个实例,您现在需要管理多个应用程序之间的并发性,这可能是一个非常难以解决的问题。我强烈建议你在DB端处理这个问题。 –

+0

因此,我捕获异常,如果我尝试保存具有重复电子邮件的对象,则会调用异常。谢谢:) – Yuriy