“错误注入构造函数";使用带有播放和scala的Slick 3.1映射枚举时 [英] "Error injecting constructor" when mapping Enumeration using Slick 3.1 with play and scala
问题描述
我有以下课程.请注意已注释掉的角色行.
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屋!