我试图实现提供的akka-http rest示例 https://github.com/ArchDev/akka-http-rest 但是我坚持
[ERROR] [08/28/2016 10:35:34.091] [default-akka.actor.default-dispatcher-8] [akka.actor.ActorSystemImpl(default)] Error during processing of request HttpRequest(HttpMethod(POST),http://127.0.0.1:9000/v1/auth/signIn,List(Host: 127.0.0.1:9000, Connection: keep-alive, Cache-Control: no-cache, Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop, User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36, Postman-Token: ec513598-b8bc-87ca-8eba-743b214fe1fa, Accept: */*, Accept-Encoding: gzip, deflate, Accept-Language: en-US, en;q=0.8, Timeout-Access: <function1>),HttpEntity.Strict(application/json, {
"login": "admin",
"password": "admin"
}),HttpProtocol(HTTP/1.1))
slick.SlickException: This DBMS allows only a single AutoInc column to be returned from an INSERT
at slick.driver.JdbcStatementBuilderComponent$JdbcCompiledInsert.buildReturnColumns(JdbcStatementBuilderComponent.scala:69)
at slick.driver.JdbcActionComponent$ReturningInsertActionComposerImpl.x$12$lzycompute(JdbcActionComponent.scala:633)
at slick.driver.JdbcActionComponent$ReturningInsertActionComposerImpl.x$12(JdbcActionComponent.scala:633)
at slick.driver.JdbcActionComponent$ReturningInsertActionComposerImpl.keyColumns$lzycompute(JdbcActionComponent.scala:633)
at slick.driver.JdbcActionComponent$ReturningInsertActionComposerImpl.keyColumns(JdbcActionComponent.scala:633)
at slick.driver.JdbcActionComponent$ReturningInsertActionComposerImpl.preparedInsert(JdbcActionComponent.scala:636)
at slick.driver.JdbcActionComponent$InsertActionComposerImpl$SingleInsertAction.run(JdbcActionComponent.scala:504)
at slick.driver.JdbcActionComponent$SimpleJdbcDriverAction.run(JdbcActionComponent.scala:32)
at slick.driver.JdbcActionComponent$SimpleJdbcDriverAction.run(JdbcActionComponent.scala:29)
at slick.backend.DatabaseComponent$DatabaseDef$$anon$2.liftedTree1$1(DatabaseComponent.scala:237)
at slick.backend.DatabaseComponent$DatabaseDef$$anon$2.run(DatabaseComponent.scala:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
这是Scala代码: 注册API:
path("signUp") {
pathEndOrSingleSlash {
post {
entity(as[UserEntity]) { userEntity =>
complete(Created -> signUp(userEntity).map(_.asJson))
}
}
}
}
UserEntityTable.scala
package oc.api.models.db
/**
* Created by sujit on 8/27/16.
*/
import oc.api.models.UserEntity
import oc.api.utils.DatabaseService
trait UserEntityTable {
protected val databaseService: DatabaseService
import databaseService.driver.api._
class Users(tag: Tag) extends Table[UserEntity](tag, "users") {
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def username = column[String]("username")
def password = column[String]("password")
def * = (id, username, password) <> ((UserEntity.apply _).tupled, UserEntity.unapply)
}
protected val users = TableQuery[Users]
}
UserEntity.scala
package oc.api.models
/**
* Created by sujit on 8/27/16.
*/
case class UserEntity(id: Option[Long] = None, username: String, password: String) {
require(!username.isEmpty, "username.empty")
require(!password.isEmpty, "password.empty")
}
case class UserEntityUpdate(username: Option[String] = None, password: Option[String] = None) {
def merge(user: UserEntity): UserEntity = {
UserEntity(user.id, username.getOrElse(user.username), password.getOrElse(user.password))
}
}
AuthService.scala
package oc.api.services
import oc.api.models.{TokenEntity, UserEntity}
import oc.api.models.db.TokenEntityTable
import oc.api.utils.DatabaseService
import scala.concurrent.{ExecutionContext, Future}
/**
* Created by sujit on 8/27/16.
*/
class AuthService(val databaseService: DatabaseService)(usersService: UsersService)(implicit executionContext: ExecutionContext) extends TokenEntityTable {
import databaseService._
import databaseService.driver.api._
def signUp(newUser: UserEntity): Future[TokenEntity] = {
usersService.createUser(newUser).flatMap(user => createToken(user))
}
def authenticate(token: String): Future[Option[UserEntity]] =
db.run((for {
token <- tokens.filter(_.token === token)
user <- users.filter(_.id === token.userId)
} yield user).result.headOption)
def createToken(user: UserEntity): Future[TokenEntity] = db.run(tokens returning tokens += TokenEntity(userId = user.id))
}
由于我是Scala和Slick的新手,无论如何,即使我已在模型
中定义O.AutoInc
,仍可提供此异常发生的原因信息
答案 0 :(得分:1)
似乎在
def createToken(user: UserEntity): Future[TokenEntity] = db.run(tokens returning tokens += TokenEntity(userId = user.id))
您正在尝试返回令牌列表,而您的dbms只允许返回一个:slick.SlickException: This DBMS allows only a single AutoInc column to be returned from an INSERT
这对你有用吗?
def createToken(user: UserEntity): Future[TokenEntity] = db.run((self returning self) += TokenEntity(userId = user.id))
答案 1 :(得分:1)
我认为您的TokenEntity
看起来像这样,其中id
会自动增加并自动创建token
:
case class TokenEntity(id: Option[Long] = None, userId: Long, token: String)
现在,您要求DBMS在插入操作中返回多个列(id
,userId
和token
),这些列不受支持。改变
def createToken(user: UserEntity): Future[TokenEntity] = db.run(tokens returning tokens += TokenEntity(userId = user.id))
到
def createToken(user: UserEntity): Future[TokenEntity] = db.run(
tokens returning tokens.map(_.userId) into((token, id) => token.copy(id = Some(id)) += TokenEntity(userId = user.id))
)
在此处指定要在插入时返回的列id
。以下into
方法合并token
和生成的密钥。有关更详细的说明,请参阅Inserting。