Scala 使用Squeryl和基类抽象CRUD操作
我加入了那些试图使用Squeryl作为我的web应用ORM框架的人们的行列。(为了记录在案,我使用Scalatra作为实际的web框架——但我不认为这是一个Scalatra问题。)这意味着我加入了试图构建一个有效的抽象层来干燥我们的常见操作的行列。例如,很常见这样的例子:Scala 使用Squeryl和基类抽象CRUD操作,scala,scalatra,squeryl,Scala,Scalatra,Squeryl,我加入了那些试图使用Squeryl作为我的web应用ORM框架的人们的行列。(为了记录在案,我使用Scalatra作为实际的web框架——但我不认为这是一个Scalatra问题。)这意味着我加入了试图构建一个有效的抽象层来干燥我们的常见操作的行列。例如,很常见这样的例子: // First Model package com.myproj import com.myproj.Schema class Foo() extends KeyedEntity { val id = 0 def
// First Model
package com.myproj
import com.myproj.Schema
class Foo() extends KeyedEntity {
val id = 0
def getAll() = { from(Schema.Foo)(s => select(s)) }
}
// Different Model
package com.myproj
import com.myproj.Schema
class Bar() extends KeyedEntity {
val id = 0
def getAll() = { from(Schema.Boo)(s => select(s)) }
}
所以一方面,我在挖掘Squeryl的语法有多简洁。另一方面:这是相当重复的。我想要的更像:
// Base
class BaseEntity extends KeyedEntity {
val id = 0
def getAll() = { from(table)(s => select(s)) }
}
// New model
class Foo extends BaseEntity
// New model
class Bar extends BaseEntity
所以我大部分时间都在工作。扩展KeyedEntity
非常简单。只有一个问题:究竟如何在BaseEntity
中定义一个表,以便扩展它的类可以访问它?老实说,这可能从根本上是我对Scala类型系统的理解不够成熟的问题。无论如何,我在这里摆姿势
我试过两种方法:
BaseEntity
中声明val表
。这让我陷入了一个非常荒谬的类型检查混乱val table:table[T]
仅当我还将T定义为一个类型时才起作用,然后子类在尝试提供不同类型的表时会导致编译器错误李>
表
参数李>
TypeTags
。然而,海报并没有提供足够的信息让我理解他的实现val table=FindTables(此)
}
// Schema
package com.myproj.schema
object MySchema extends Schema {
val foo = table[Foo]("foos")
val bar = table[Bar]("bars")
}
// BaseEntity
package com.myproj.models
import com.myproj.schema.MySchema
abstract class BaseEntity extends Keyedentity[Long] {
val id: Long = 0
val table = MySchema.findTablesFor(this).head
}
// Class
package com.myproj.models
case class Foo (
val name: String,
val extra: Option[String]
) extends BaseEntity {
def this() = this("", None)
}
像这样设置FindTables for
始终返回空迭代器。它进行编译,但在运行时由于试图在空迭代器上调用head而抛出错误(正如您所说的)。处理错误不是问题;找不到桌子有点麻烦
想法
val table:table[T]仅在我还将T定义为一个类型时才起作用,然后子类在尝试提供不同类型的表时会导致编译器错误
你可以用一个self类型来实现这一点。我不确定我会推荐它,但它应该可以:
class BaseEntity[T] {
self: T =>
val table: Table[T]
}
那么您的实现将如下所示:
class MyEntity extends BaseEntity[MyEntity]
使用FindTables可能是更好的解决方案。没有什么可以阻止您将一个类映射到一个Squeryl模式中的多个表。你可以:
val tableA = table[MyEntity]
val tableB = table[MyEntity]
因此,需要为所有匹配的表返回一个Iterable。如果您知道不打算这样做,您可以使用第一个结果:
val table = MySchema.findTableFor(this).head
请注意,如果找不到相关表,这将引发异常。首先,感谢您的快速响应!非常感谢。第二:
MySchema.findTablesFor(this)
只返回大小为0的Iterable。我将用更彻底的代码更新我的帖子——我一定是做错了什么。首先,将表成员更改为def,或者至少更改为lazy val以推迟其计算。您可以在此处查看FindTables的功能:。定义表会将其添加到_tables集合:。我只能想象这是一个操作顺序问题。不幸的是,无论是lazy val table
还是def table
都没有任何区别——它运行,但仍然无法找到表。我使用的是Scala 2.10.2——有没有可能这是一个兼容性问题?(作为记录:如果我更明确地调用Squiryl的函数——比如说,但是从(MySchema.Foo)(s=>select(s))——它工作得很好,MySchema.create.wird也是如此。)我不确定哪里出了问题。我根据您的示例创建了这个测试用例:运行它会得到一个“foos”输出,这意味着一个表是foundWELP。看起来问题一定在我使用的堆栈中的其他地方,尽管我不知道具体在哪里。我会到处找的,看看能不能找到什么。再次感谢你的帮助!