Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用slick play2普通SQL将记录插入事务中的3个表时出现异常_Scala_Playframework_Slick - Fatal编程技术网

Scala 使用slick play2普通SQL将记录插入事务中的3个表时出现异常

Scala 使用slick play2普通SQL将记录插入事务中的3个表时出现异常,scala,playframework,slick,Scala,Playframework,Slick,我的设想如下: 在我的PG DB中有3个表(用户、安全、密码) 当最终用户试图将self注册到我的数据库中时,代码将检查用户表中是否存在该用户 如果存在,只需返回一个None。否则,将记录插入同一事务中的(用户、安全、密码) 以下是我的代码: def selectUserCountQuery1(user: User): DBIO[Int] = { sql"""SELECT COUNT(user_id) FROM users WHERE provider_id = ${user.provide

我的设想如下:

  • 在我的PG DB中有3个表(用户、安全、密码)
  • 当最终用户试图将self注册到我的数据库中时,代码将检查用户表中是否存在该用户
  • 如果存在,只需返回一个None。否则,将记录插入同一事务中的(用户、安全、密码)
  • 以下是我的代码:

    def selectUserCountQuery1(user: User): DBIO[Int] = {
      sql"""SELECT COUNT(user_id) FROM users WHERE provider_id = ${user.providerId} AND phone_num = ${user.phoneNumber}""".as[Int].head
    }
    
    
    def insertUserQuery(user: User): DBIO[Int] = {
        sqlu"""INSERT INTO users VALUES (${user.userId}, ${user.deviceToken},${user.phoneNumber},${user.providerId},
            ${user.gender},${user.email},${user.createTime},${user.loginName},${user.nickName},${user.currentPlatform},${user.roles},${user.avatarUrl})"""
    }
    
    def insertPasswordQuery(passwordInfo: PasswordInfo): DBIO[Int] = {
      sqlu"""INSERT INTO password_info VALUES (${passwordInfo.userId}, ${passwordInfo.hasher},
             ${passwordInfo.passwordHash}, ${passwordInfo.salt})"""
    }
    
    def insertSecurityTokenQuery(accessToken: UserSecurityToken): DBIO[Int] = {
      sqlu"""INSERT INTO user_security_token VALUES (${accessToken.userId}, ${accessToken.platform},
             ${accessToken.token}, ${accessToken.token_time})"""
    }
    
    
    def registerUser (user: User, password: String): Future[Option[UserProfile]] = {
      val passwordHash = MD5PasswordGenerator.generateMD5WithEncoder(password)
      val passwordInfo : PasswordInfo = PasswordInfo(user.userId, Some("MD5"), passwordHash, Some(""))
      val tokenStr: String = JwtTokenSecurity.jwtTokenString(user.userId, user.currentPlatform)
      val accessToken : UserSecurityToken = UserSecurityToken(user.userId, user.currentPlatform, tokenStr, 1)
    
      val actions = for {
        count <- selectUserCountQuery1(user) if count == 0
        status1 <- insertUserQuery(user)
        status2 <- insertPasswordQuery(passwordInfo)
        status3 <- insertSecurityTokenQuery(accessToken)
      } yield(count)
    
      db.run(actions.transactionally).map {
        count  => count match {
          case 0 => Some(UserProfile.user2UserProfile(user, passwordInfo, accessToken))
          case _ => None
        }
      }
    }
    
    这太奇怪了,如果我去掉了保护条件(count==0),也没有例外。但是用户信息会不断地插入到数据库中


    有专家帮我吗

    防护
    DBIO.withFilter
    的工作方式类似于
    Future.withFilter
    :不匹配谓词会导致
    NoTouchElementException
    失败

    相反,您可以使用
    flatMap
    执行分支:

    val actions = selectUserCountQuery1(user).flatMap {
      case 0 => for {
        status1 <- insertUserQuery(user)
        status2 <- insertPasswordQuery(passwordInfo)
        status3 <- insertSecurityTokenQuery(accessToken)
      } yield 0
    
      case n => DBIO.successful(n)
    }
    
    db.run(actions.transactionally).map {
      case 0 => Some(UserProfile.user2UserProfile(user, passwordInfo, accessToken))
      case _ => None
    }
    
    val actions=selectUserCountQuery1(用户).flatMap{
    案例0=>{
    状态1无
    }
    
    val actions = selectUserCountQuery1(user).flatMap {
      case 0 => for {
        status1 <- insertUserQuery(user)
        status2 <- insertPasswordQuery(passwordInfo)
        status3 <- insertSecurityTokenQuery(accessToken)
      } yield 0
    
      case n => DBIO.successful(n)
    }
    
    db.run(actions.transactionally).map {
      case 0 => Some(UserProfile.user2UserProfile(user, passwordInfo, accessToken))
      case _ => None
    }