访问非懒惰的val时的NPE

时间:2013-11-25 23:43:12

标签: scala lift slick

EDIT2:

所以另一个人对此表示反对: 我仍然不知道为什么会这样,但我现在有一个与jOOQ类似的问题和方言我必须这样做。我的代码在这里看起来像这样:

object MyDB {
    private lazy val dialect = SQLDialect.POSTGRES
    def withSession[T](f: DSLContext => T) = f(DSL.using(getConnectionPool, dialect))
}

如果我删除“懒惰”,当我尝试在https://github.com/jOOQ/jOOQ/blob/version-3.2.0/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java

的第552行执行jOOQ查询时它会爆炸

这恰好是评估方言的一条线。在我添加了懒惰后,一切都按预期工作。

也许这是LiftWeb的线程问题,并且执行线程没有看到val的正确值?我不知道......

编辑:

我找到了一种方法来做我想要的只是通过在第一个破碎版本中添加一个懒惰的值。所以懒惰的vals一切都很好。 但是我会让它保持开放,因为我不知道如何解释这种行为。

原帖:

所以我试图在Slick中使用参数化查询。 我的代码如下,我的问题是当我尝试从webapplication(liftweb,使用sbt启动的容器)中运行它时,我得到一个NPE(请参阅注释)(应用程序创建一个给定字符串的类PlayerListCollector的对象) “可乐”) 当我从Eclipse中执行App作为App时,底部的println工作正常。

class PlayerListCollector(term: String) {
  import PlayerListCollector._
  val searchResult = executeSearch(term)
}

object PlayerListCollector extends Loggable with App{
  private val searchNameCurrent = Parameters[String].flatMap {
    case (term) => {
      for {
        p <- Players if p.uberName.isNotNull
        n <- p.displayName if (n.displayName.toLowerCase.like(term))
      } yield (p.id, n.displayName)
    }
  }

  private def executeSearch(term: String) = {
    val lowerTerm = "%"+term.toLowerCase()+"%"
    logger info "HELLO " +lowerTerm // prints HELLO %cola%
    val foo = searchNameCurrent(lowerTerm) // NPE right in this line
    logger info foo // never executed from here on ...
    val byCurrent = foo.list
    logger info byCurrent

    [...]
  }

  // this works if run directly from within eclipse!
  println(DB withSession {
    searchNameCurrent("%cola%").list
  })
}

当我将代码更改为如下所示时,问题就消失了:

[...]
object PlayerListCollector extends Loggable with App{

  private def executeSearch(term: String) = {
      val searchNameCurrent = Parameters[String].flatMap {
        case (term) => {
          for {
            p <- Players if p.uberName.isNotNull
            n <- p.displayName if (n.displayName.toLowerCase.like(term))
          } yield (p.id, n.displayName)
        }
      }

    val lowerTerm = "%"+term.toLowerCase()+"%"
    logger info "HELLO " +lowerTerm // prints HELLO %cola%
    val foo = searchNameCurrent(lowerTerm) // executes just fine when the query is in a local val
    logger info foo
    val byCurrent = foo.list
    logger info byCurrent // prints expected output

    [...]
  }
  [...]
}

我不知道为什么会发生这种情况。 是不是将参数化的查询放在只有一次填充值的val中,这样就不需要多次编译了?

1 个答案:

答案 0 :(得分:0)

事实证明我在这些对象上使用了App-Trait(http://www.scala-lang.org/api/current/index.html#scala.App)。 阅读大胖子告诫我告诉我们发生了什么。