Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用Squeryl和基类抽象CRUD操作_Scala_Scalatra_Squeryl - Fatal编程技术网

Scala 使用Squeryl和基类抽象CRUD操作

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

我加入了那些试图使用Squeryl作为我的web应用ORM框架的人们的行列。(为了记录在案,我使用Scalatra作为实际的web框架——但我不认为这是一个Scalatra问题。)这意味着我加入了试图构建一个有效的抽象层来干燥我们的常见操作的行列。例如,很常见这样的例子:

// 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
    。然而,海报并没有提供足够的信息让我理解他的实现
  • 前面提到的SO帖子有一条注释,其中建议使用org.squeryl.Schema.findtables方法。再次谈到潜在的新手问题:我还没有在如何实现这一点上取得进展。我试过这样的方法:

    类BaseEntity{
    val table=FindTables(此)
    }

  • 但后来,我得到了一个Iterable,我有点不确定该怎么处理它

    所以。有没有“正确”的方法?当然,有一种干净的方法可以将CRUD操作转移到基类中——我似乎无法理解

    编辑

    下面是我用Squiryl 9.5-6得到的:

    // 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。看起来问题一定在我使用的堆栈中的其他地方,尽管我不知道具体在哪里。我会到处找的,看看能不能找到什么。再次感谢你的帮助!