Squeryl自定义字段类型

时间:2012-08-29 10:15:01

标签: scala squeryl

我正在尝试在Squeryl中创建自定义字段类型。此字段表示Isin code,因此它由字符串字段备份。在example on the documentation之后,我在创建新的isin之前添加了一个简单的验证(更不用说Isin代码是什么或验证过程如何工作):

trait Domain[A] { self: CustomType[A] =>
  def validate(a: A): Unit

  validate(value)
}

class Isin(v: String) extends StringField(v) with Domain[String] {
  println("instantiating Isin")
  override def validate(s: String) {
    println("calling validate with " + s)
    assert(checkIsin(s))
  }

  private def checkIsin(isin: String): Boolean = {
    // never mind the exact procedure
  }
}

我添加了一些println来了解发生了什么。我在像

这样的模型中使用这个字段
case class Asset(
  val id: Long = 0,
  val isin: Isin
) extends KeyedEntity[Long]

object Asset {
  import Database.assets

  def create(isinCode: String) {
    inTransaction {
      assets.insert(new Asset(isin = new Isin(isinCode)))
    }
  }
}

现在,当我调用Asset.create("US0378331005")(一个有效的ISIN)时,我得到一个例外。在堆栈跟踪中,事实证明此异常是由于init上的null方法调用,该值应该传递给checkIsin。实际上,println语句打印

calling validate with US0378331005
Instantiating Isin
calling validate with

所以似乎validate方法实际上被调用了两次,但第二次获得了null值。

  

出了什么问题?

1 个答案:

答案 0 :(得分:1)

这里有几个问题。首先,您似乎正在使用Lift Record,如果是这种情况,您将错误地实现验证逻辑。验证记录字段的正确方法是覆盖

def validations: List[ValidationFunction]

其中ValidationFunction是类型别名

type ValidationFunction = ValueType => List[FieldError]

在您的情况下,ValueType == String。

下一个问题是你的领域特质。因为您对validate的调用被内联到类定义中,所以在构造字段时将调用它。显然,此时没有设置值,因此这就是您看到引用空值的println的原因。我想你看到它们的顺序与你的应用程序流程有关。您有一个已验证的现有记录,然后创建一个新记录,触发接下来的两个println语句。