“错误注入构造函数";使用带有播放和scala的Slick 3.1映射枚举时 [英] "Error injecting constructor" when mapping Enumeration using Slick 3.1 with play and scala

查看:89
本文介绍了“错误注入构造函数";使用带有播放和scala的Slick 3.1映射枚举时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程.请注意已注释掉的角色行.

I have the following classes. please note the commented-out Role lines.

用户模型:

case class User(
  uid: Option[Long] = None,
//  role: Option[Role.Role] = None,
  firstName: String,
  lastName: String,
  middleName: Option[String] = None,
  email: String,
  avatarUrl: Option[String],
  created: DateTime = DateTime.now,
  modified: DateTime = DateTime.now
)

UserComponent和UserDAO:

UserComponent and UserDAO:

import javax.inject._
import scala.concurrent.Future
import org.krazykat.whatsupdoc.models.User
import play.api.db.slick.{HasDatabaseConfigProvider, DatabaseConfigProvider}
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import slick.driver.{JdbcProfile, JdbcDriver}
import org.joda.time.DateTime
import com.github.tototoshi.slick.GenericJodaSupport
import java.sql.Time

trait UsersComponent { self: HasDatabaseConfigProvider[JdbcProfile]  =>
  import driver.api._

  object PortableJodaSupport extends GenericJodaSupport(driver.asInstanceOf[JdbcDriver])
  import PortableJodaSupport._


//  implicit val roleMapper = MappedColumnType.base[Role.Role, String](
//    e => e.toString,
//    s => Role.withName(s)
//  )


  class Users(tag: Tag) extends Table[User](tag, "USERS") {

    def uid = column[Long]("USER_ID", O.PrimaryKey, O.AutoInc)
//    def role = column[Role.Role]("ROLE") 
    def firstName = column[String]("FIRST_NAME")
    def lastName = column[String]("LAST_NAME")
    def middleName = column[String]("MIDDLE_NAME")
    def email = column[String]("EMAIL")
    def avatarUrl = column[String]("AVATAR_URL")
    def created =  column[DateTime]("CREATED")
    def modified = column[DateTime]("MODIFIED")

    def * = (uid.?, firstName, lastName, middleName.?, email, avatarUrl.?, created, modified) <> (User.tupled, User.unapply _)
  }
}


/**
 * @author ehud
 */
@Singleton
class UsersDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends UsersComponent with HasDatabaseConfigProvider[JdbcProfile] {
  import driver.api._

  val users = TableQuery[Users]

  def count = db.run(users.length.result)

  def getById(uid: Long) = 
    db.run(users.filter(_.uid === uid).result.headOption)

  def insert(user: User) =
    db.run((users returning users.map(_.uid)) += user).map(id => id)

  def delete(user: User) =
    db.run(users.filter(_.uid === user.uid).delete)

  def update(uid: Long, user: User) = {
    val userToUpdate: User = user.copy(Some(uid))
    db.run(users.filter(_.uid === uid).update(userToUpdate))
  }
}

和测试规范:

class UsersSpec extends Specification {


  def dateIs(date: java.util.Date, str: String) = new java.text.SimpleDateFormat("yyyy-MM-dd").format(date) == str

  trait WithDatabaseConfig {
    lazy val (driver, db) = {
      val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
      (dbConfig.driver, dbConfig.db)
    }
  }

  "User model" should {   
    def usersDao(implicit app: Application) = {
      val app2UsersDAO = Application.instanceCache[UsersDAO]
      app2UsersDAO(app)
    }

    "be inserted to db correctly" in new WithApplication with WithDatabaseConfig {
      import driver.api._

      val userInsertresult = Await.result(usersDao.insert(
        User(None, "firstname", "lastname", Some("middlename"), "me@me.com", Some("avatar"), DateTime.now, DateTime.now)), 
        Duration.Inf
      )
      val count = Await.result(usersDao.count, Duration.Inf)
      count mustEqual 1
    }

运行此规范时,它会成功.很好.

when i run this spec, it succeeds. great.

现在我想向用户添加角色.所以我创建了以下角色类:

now i want to add a role to my user. so i created the following Role class:

object Role extends Enumeration{

  type Role = Value

  val None = Value("NONE")
  val Admin = Value("ADMIN")
  val Root = Value("ROOT")
} 

并取消注释相关行(并将其添加到任何实例化调用中),并更新演进文件(角色部分存储为VARCHAR).现在,当规范运行时,我得到以下异常:

and uncomment the relevant lines (and add it to any instanciation call), and update the evolutions file (the Role part is stored as a VARCHAR). now, when the spec runs, i get the following exception:

[error]   ! be inserted to db correctly
[error]    Unable to provision, see the following errors:
[error]    
[error]    1) Error injecting constructor, java.lang.NullPointerException
[error]      at UsersDAO.<init>(UsersDAO.scala:59)
[error]      at UsersDAO.class(UsersDAO.scala:59)
[error]      while locating UsersDAO
[error]    
[error]    1 error (InjectorImpl.java:1025)
[error] com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1025)
[error] com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
[error] play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:321)
[error] play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:316)
[error] play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234)
[error] play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234)
[error] play.utils.InlineCache.fresh(InlineCache.scala:69)
[error] play.utils.InlineCache.apply(InlineCache.scala:55)

我尝试在线研究,但是我发现的所有关于如何进行枚举的Slick样本似乎都是我的,并且在Slick上下文中不会出现注入错误.

I tried researching online, but all the Slick samples I found on how to do Enumerations seem like mine, and the injection error does not show up in the Slick context.

有什么主意吗?

推荐答案

此处的问题是,您尝试使用UsersComponent特征中HasDatabaseConfigProvider特征中的driver.api.MappedColumnType. 但是目前尚未注入UsersComponent初始化驱动程序,这会导致NPE. 您可以将roleMapper值设置为lazy或将其从val更改为def:

The problem here is that you are trying to use driver.api.MappedColumnType from the HasDatabaseConfigProvider trait in the UsersComponent trait. But at the moment of the UsersComponent initialization driver is not injected yet, that causes NPE. You can either make your roleMapper val lazy or change it from val to def:

implicit lazy val roleMapper = ...

OR

implicit def roleMapper = ...

这篇关于“错误注入构造函数";使用带有播放和scala的Slick 3.1映射枚举时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆