gpt4 book ai didi

scala - 为 slick 构建通用 DAO

转载 作者:行者123 更新时间:2023-12-01 17:03:17 25 4
gpt4 key购买 nike

我厌倦了总是执行如下操作,以便使用 slick 为每个我的域实体进行数据库访问。

database withSession {
implicit session =>
val entities = TableQuery[EntityTable]
val id = //Some ID
val q = for {
e <- entities if e.id === id
} yield (e)
val entity = q.first
}

(注意:EntityTable 的定义如 here 所示)

所以我决定需要一个通用的数据库访问对象来为我处理这个问题。用法应该类似于

[...]
val entityDAO = new GenericDAO[Entity, EntityTable, String]()
[...]

database withSession { implicit session =>
val id = // Some ID
val entity = entityDAO.get(id)
}

我对 GenericDAO 实现的尝试如下所示

class GenericDAO[T, TB, PK](implicit session: Session) {
val entities = TableQuery[TB] // Line 1

def get(id: PK): T = {
val q = for {
e <- entities
} yield (e)
val res: T = q.first
res
}
}

但是第 1 行给我留下了一个编译器错误,指出 TB 参数有问题。

Multiple markers at this line - type arguments [TB] conform to the bounds of none of the overloaded alternatives of value apply: [E <: scala.slick.lifted.AbstractTable[]]=> scala.slick.lifted.TableQuery[E,E#TableElementType] [E <: scala.slick.lifted.AbstractTable[]](cons: scala.slick.lifted.Tag => E)scala.slick.lifted.TableQuery[E,E#TableElementType] - wrong number of type parameters for overloaded method value apply with alternatives: [E <: scala.slick.lifted.AbstractTable[]]=> scala.slick.lifted.TableQuery[E,E#TableElementType] [E <:
scala.slick.lifted.AbstractTable[
]](cons: scala.slick.lifted.Tag => E)scala.slick.lifted.TableQuery[E,E#TableElementType]

对于这个问题有什么建议吗?或者也许我错了,应该以另一种方式实现。我愿意接受任何解决方案。谢谢!

最佳答案

首先,你可以这样写

val entities = TableQuery[EntityTable] // put in a central place for re-use

然后

database.withSession(
(for {
e <- entities if e.id === /*Some ID*/
} yield e).first()(_)
)

或者这个

database.withSession(entities.filter(_.id === /*Some ID*/).first()(_))

或者这个

val get = entities.findBy(_.id) // <- reuse this
database.withSession(get(/*Some ID*/).first()(_))

为简洁起见。这可能会让你的整个 DAO 变得不必要(这太棒了:)!)。

关于您收到的错误消息。 TableQuery[TB]是一个宏,它是 TableQuery(tag => new TB(tag)) 的简写, TB必须是Table并支持对象创建。您不能只使用 TableQuery从 DAO 包装器获得的无约束类型参数上的宏。你可以约束 TB <: Table[_]但它仍然不支持对象创建,这是您在 Scala 中无法限制的。您只能向 DAO 提供一个工厂(一种常见的模式是获取一个工厂作为隐式参数),但是当您只需编写一次 TableQuery 并将其存储在全局可访问的位置时,这一切都没有意义。

更新:

该快捷方式以相同的方式适用于所有这些方法。这是简单的 Scala。你只需要把方法变成一个函数,然后传递给高阶函数withSession,它需要一个从session到anything的函数。请注意,某些 Slick 方法有一个空参数列表,这需要 ()(_)把它们变成一个函数,有些只有隐式参数列表,只需要 (_) 。例如。 database.withSession(entities.filter(_.id === /*Some ID*/).delete(_)) .

如果您想知道_ 。 Scala 将方法与函数区分开来。定义foo(a: A, b: B, ...): R是一个方法,但可以转换为 (A,B,C) => R 类型的函数使用foo _ 。这种转换称为 eta 扩展,通过谷歌搜索可以找到更多信息。有时,当需要一个函数,但您提供了一个方法时,Scala 编译器会推断 _并且您不必明确地编写它。您还可以提供一些参数并使用 _代替您还不想应用的参数。在这种情况下,您部分应用该方法并返回一个函数。这就是我们在这里所做的。我们使用_在方法通常期望 session 并返回需要 session 的函数的地方。到底什么时候你必须使用 _(_)()(_)与方法签名以及隐式参数列表、无效方法、具有空参数列表的方法之间的详细相互作用有关,这是在某些时候值得研究的一般 Scala 知识。

关于scala - 为 slick 构建通用 DAO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21729852/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com