gpt4 book ai didi

scala - 在数据访问层重用Slick的DB驱动代码

转载 作者:行者123 更新时间:2023-12-02 04:05:28 25 4
gpt4 key购买 nike

我正在尝试使用 Slick 3.0 进行数据访问。在查阅了各种 github 示例后,我得出了以下设计。

注入(inject) DataSource 和 Driver 实例的单例 Slick 对象

class Slick(dataSource: DataSource, val driver: JdbcDriver)  {

val db = driver.api.Database.forDataSource(dataSource)

}

定义映射的每个数据库表的特征

该特征混合在构造查询的上层中。

trait RecipeTable {

protected val slick: Slick

// the ugly import that have to be added when Slick API is used
import slick.driver.api._

type RecipeRow = (Option[Long], String)

class RecipeTable(tag: Tag) extends Table[RecipeRow](tag, "recipe") {

def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")

def * = (id, name)
}

protected val recipes = TableQuery[RecipeTable]
}

现在有一个明显的缺点,在每个 *Table 特征以及混合它的每个地方,我都需要重复 import slick.driver.api._为了将 Slick 的所有东西都纳入范围内。

这是我想避免的事情。理想情况下,导入仅定义一次并在下游组件中重用。

您能否提出解决此类重复问题的设计方案?

我的灵感主要来自this例如,但是导入也在那里重复。

最佳答案

这种“丑陋”的导入实际上是 slick 设计的一件好事。但是您的灵活使用方式可以改进如下,

创建一个特征,它将提供JdbcDriver

package demo.slick.dbl

trait SlickDriverComponent {
val driver: JdbcDriver
}

trait SlickDBComponent extends SlickDriverComponent {
val db: driver.api.Database
}

现在将您的 DAO 特征定义为依赖于此特征的特征,

package demo.slick.dao

import demo.slick.dbl.SlickDBComponent

trait RecipeDAO { self: SlickDBComponent =>

import driver.api._

type RecipeRow = (Option[Long], String)

class RecipeTable(tag: Tag) extends Table[RecipeRow](tag, "recipe") {

def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")

def * = (id, name)
}

val recipes = TableQuery[RecipeTable]

def get5Future = db.run(recipes.take(5).result)

}

当涉及到实际与数据库连接并执行操作时,

package demo.slick.dbl

trait MySqlDriverProvider extends SlickDriverComponent {
val driver = slick.driver.MySQLDriver
}

object MySqlDBConnection extends MySqlDriverProvider {
val connection = driver.api.Database.forConfig("mysql")
}

trait MySqlDBProvider extends SlickDBComponent {
val driver = slick.driver.MySQLDriver
val db: Database = MySqlDBConnection.connection
}

trait PostgresDriverProvider extends SlickDriverComponent {
val driver = slick.driver.PostgresDriver
}

object PostgresDBConnection extends PostgresDriverProvider {
val connection = driver.api.Database.forConfig("postgres")
}

trait PostgresDBProvider extends SlickDBComponent {
val driver = slick.driver.PostgresDriver
val db: Database = PostgresDBConnection.connection
}

现在最终定义您的 DAO 对象,如下所示,

package demo.slick.dao

import demo.slick.dbl.MySqlDBProvider

object MySqlRecipeDAO extends RecipeDAO with MySqlDBProvider

object PostgresRecipeDAO extends RecipeDAO with PostgresDBProvider

现在,您可以按如下方式使用它们,

pakcage demo.slick

import scala.util.{Failure, Success, Try}
import scala.concurrent.ExecutionContext.Implicits.global

import demo.slick.RecipeDAO

object App extends Application {
val recipesFuture = MysqlRecipeDAO.get5Future

recipesFuture.onComplete({
case Success(seq) => println("Success :: found :: " + seq)
case Failure(ex) => println("Failure :: failed :: " + ex.getMessage)
})
}

现在...众所周知,不同的数据库具有不同的功能集,因此您可用的“东西”将取决于所使用的驱动程序。

因此,每次都需要丑陋的导入,以便您可以编写一次 DAO 特征,然后能够将它们与您想要的任何数据库特定驱动程序实现一起使用。

关于scala - 在数据访问层重用Slick的DB驱动代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39776823/

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