如何从 play framework dao singleton 中提取光滑的实体
How to extract slick entities from play framework dao singleton
我一直在使用 Play 框架、Slick 和 Postgresql 创建一个新项目,但我不明白如何从 DAO 中提取实体。大多数教程显示实体(class 扩展 table)是 dao 单例中的 class 的示例。
其实我也这样做过:
import javax.inject.{Inject, Singleton}
import org.joda.time.DateTime
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.jdbc.JdbcProfile
import scala.concurrent.{ExecutionContext, Future}
@Singleton
class CardDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
(implicit executionContext: ExecutionContext) extends HasDatabaseConfigProvider[JdbcProfile] {
import dbConfig.profile.api._
val Cards = TableQuery[CardsTable]
private[dao] class CardsTable(tag: Tag) extends Table[Card](tag, "card") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name", O.Unique)
def value = column[BigDecimal]("value")
def currencyId = column[Int]("currency_id")
def created = column[DateTime]("created")
def active = column[Boolean]("active")
override def * = (id, name, value, currencyId, created) <> (Card.tupled, Card.unapply)
}
def all(): Future[Seq[Card]] = db.run(Cards.result)
}
没关系。我不介意在这里有一个实体,但是当我创建另一个 DAO 时,我无法访问我的 TableQuery(加入 tables 或创建外键),因为它只是单例中的一个字段。
我试图提取 CardsTable 以将 class 与包含 TableQuery 的伴随对象分开,但事实证明列方法,O,foreignKey 来自 HasDatabaseConfigProvider 特征(导入 dbConfig.profile.api._),所以我'我不确定,但我想我必须将 dbConfig 隐式传递给 class.
你会怎么做?这只是项目的开始,所以真的不想在这一点上犯一些新手错误。
感谢 Łukasz,我找到了方法:
trait Tables {
this: HasDatabaseConfigProvider[JdbcProfile] => {}
import dbConfig.profile.api._
val Cards = TableQuery[CardsTable]
val FaceValues = TableQuery[FaceValuesTable]
val Currencies = TableQuery[CurrenciesTable]
val Cryptocurrencies = TableQuery[CryptocurrenciesTable]
val Wallets = TableQuery[WalletsTable]
val Transactions = TableQuery[TransactionsTable]
class CryptocurrenciesTable(tag: Tag) extends Table[Cryptocurrency](tag, "cryptocurrency") with ActiveAndCreated[Cryptocurrency] {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name", O.Unique)
def cryptocurrencyCode = column[String]("cryptocurrency_code", O.Unique)
def blockchainExplorerUrl = column[String]("blockchain_explorer_url")
def iconSvg = column[String]("icon_svg")
override def * = (id, name, cryptocurrencyCode, blockchainExplorerUrl, iconSvg, created) <>
(Cryptocurrency.tupled, Cryptocurrency.unapply)
}
class FaceValuesTable(tag: Tag) extends Table[FaceValue](tag, "face_value") with ActiveAndCreated[FaceValue] {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def value = column[BigDecimal]("value")
def currencyId = column[Int]("currency_id")
def cardId = column[Int]("card_id")
def card = foreignKey("card_fk", cardId, Cards)(_.id)
def currency = foreignKey("currency_fk", currencyId, Currencies)(_.id)
override def * = (id, value, currencyId, cardId) <> (FaceValue.tupled, FaceValue.unapply)
}
...
}
简单道的特点:
trait Dao extends HasDatabaseConfigProvider[JdbcProfile] with Tables
现在所有的 DAO 都非常简单:
@Singleton
class WalletDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
(implicit executionContext: ExecutionContext) extends Dao {
import dbConfig.profile.api._
def find(walletAddress: WalletAddress): Future[Option[Wallet]] = {
val query = for {
wallet <- Wallets
cryptocurrency <- Cryptocurrencies if cryptocurrency.id === wallet.id &&
cryptocurrency.cryptocurrencyCode === walletAddress.cryptocurrency
} yield wallet
db.run(query.result.headOption)
}
def find(walletId: Int): Future[Option[Wallet]] = db.run(Wallets.filter(_.id === walletId).result.headOption)
def save(wallet: Wallet): Future[Int] = db.run(Wallets += wallet)
}
我一直在使用 Play 框架、Slick 和 Postgresql 创建一个新项目,但我不明白如何从 DAO 中提取实体。大多数教程显示实体(class 扩展 table)是 dao 单例中的 class 的示例。
其实我也这样做过:
import javax.inject.{Inject, Singleton}
import org.joda.time.DateTime
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.jdbc.JdbcProfile
import scala.concurrent.{ExecutionContext, Future}
@Singleton
class CardDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
(implicit executionContext: ExecutionContext) extends HasDatabaseConfigProvider[JdbcProfile] {
import dbConfig.profile.api._
val Cards = TableQuery[CardsTable]
private[dao] class CardsTable(tag: Tag) extends Table[Card](tag, "card") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name", O.Unique)
def value = column[BigDecimal]("value")
def currencyId = column[Int]("currency_id")
def created = column[DateTime]("created")
def active = column[Boolean]("active")
override def * = (id, name, value, currencyId, created) <> (Card.tupled, Card.unapply)
}
def all(): Future[Seq[Card]] = db.run(Cards.result)
}
没关系。我不介意在这里有一个实体,但是当我创建另一个 DAO 时,我无法访问我的 TableQuery(加入 tables 或创建外键),因为它只是单例中的一个字段。
我试图提取 CardsTable 以将 class 与包含 TableQuery 的伴随对象分开,但事实证明列方法,O,foreignKey 来自 HasDatabaseConfigProvider 特征(导入 dbConfig.profile.api._),所以我'我不确定,但我想我必须将 dbConfig 隐式传递给 class.
你会怎么做?这只是项目的开始,所以真的不想在这一点上犯一些新手错误。
感谢 Łukasz,我找到了方法:
trait Tables {
this: HasDatabaseConfigProvider[JdbcProfile] => {}
import dbConfig.profile.api._
val Cards = TableQuery[CardsTable]
val FaceValues = TableQuery[FaceValuesTable]
val Currencies = TableQuery[CurrenciesTable]
val Cryptocurrencies = TableQuery[CryptocurrenciesTable]
val Wallets = TableQuery[WalletsTable]
val Transactions = TableQuery[TransactionsTable]
class CryptocurrenciesTable(tag: Tag) extends Table[Cryptocurrency](tag, "cryptocurrency") with ActiveAndCreated[Cryptocurrency] {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name", O.Unique)
def cryptocurrencyCode = column[String]("cryptocurrency_code", O.Unique)
def blockchainExplorerUrl = column[String]("blockchain_explorer_url")
def iconSvg = column[String]("icon_svg")
override def * = (id, name, cryptocurrencyCode, blockchainExplorerUrl, iconSvg, created) <>
(Cryptocurrency.tupled, Cryptocurrency.unapply)
}
class FaceValuesTable(tag: Tag) extends Table[FaceValue](tag, "face_value") with ActiveAndCreated[FaceValue] {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def value = column[BigDecimal]("value")
def currencyId = column[Int]("currency_id")
def cardId = column[Int]("card_id")
def card = foreignKey("card_fk", cardId, Cards)(_.id)
def currency = foreignKey("currency_fk", currencyId, Currencies)(_.id)
override def * = (id, value, currencyId, cardId) <> (FaceValue.tupled, FaceValue.unapply)
}
...
}
简单道的特点:
trait Dao extends HasDatabaseConfigProvider[JdbcProfile] with Tables
现在所有的 DAO 都非常简单:
@Singleton
class WalletDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
(implicit executionContext: ExecutionContext) extends Dao {
import dbConfig.profile.api._
def find(walletAddress: WalletAddress): Future[Option[Wallet]] = {
val query = for {
wallet <- Wallets
cryptocurrency <- Cryptocurrencies if cryptocurrency.id === wallet.id &&
cryptocurrency.cryptocurrencyCode === walletAddress.cryptocurrency
} yield wallet
db.run(query.result.headOption)
}
def find(walletId: Int): Future[Option[Wallet]] = db.run(Wallets.filter(_.id === walletId).result.headOption)
def save(wallet: Wallet): Future[Int] = db.run(Wallets += wallet)
}