遵循特征定义了表示数据库的类应该实现的常用方法。它有一个方法getOneById
它接受一个id
(比如对应于表的主键)并返回一些值或None
。id
可以是单个值(例如电子邮件 ID)或多个值(例如存储桶 ID 和电子邮件 ID),例如,存储桶 = 1 和电子邮件 ="mc@mc.com"。
abstract trait Repository[I,M] {
def getOneById(id: I): Option[M]
}
实现可以是(使用下面的I
我不知道该定义什么I
)。User
是一个case class
class CassandraRepository[I ,User] (session: Session, tablename: String, partitionKeyColumns: List[String]) extends Repository [I,User] {
def getOneById(id:I): M = {
/*eg. select * from users where bucket=1 and email='mc@mc.com';*/
val selectStmt =
select()
.from(tablename)
.where(QueryBuilder.eq(partitionKeyColumns(0), `some value from id should come here`)).and(QueryBuilder.eq(partitionKeyColumns(1), `if multiple ids, some other value of id should come here`))
.limit(1)
val resultSet = session.execute(selectStmt)
val row = resultSet.one() //get 1st value only
row.toUser(); //assume a function which converts row data to User case class
}
I
应该是什么?我想我把这些值表示为case class
但是我如何在这里传递case class
,因为不同的类可能有不同的字段,具体取决于所搜索的表。例如
User
表可以将bucketId:Int
和email:String
作为主键,在这种情况下,查询中的代码将.where(QueryBuilder.eq(partitionKeyColumns(0), id.bucketId))).and(QueryBuilder.eq(partitionKeyColumns(1), id.email))
Product
表可以将bucketId:Int
和productCode:Int
作为主键,在这种情况下,查询中的代码将.where(QueryBuilder.eq(partitionKeyColumns(0), id.bucketId))).and(QueryBuilder.eq(partitionKeyColumns(1), id.productCode))
我怎么能写出这么通用的特质?
同样,您混淆了类型和类型参数。如果你也想CassandraRepository
是通用的,你会有例如
class CassandraRepository[I, M](...) extends Repository[I, M] {
// calls conditions and fromRow
def getOneById(id: I): Option[M] = ...
// abstract methods which will be implemented differently depending on I and M
def conditions(id: I): List[Clause]
def fromRow(row: Row): M
}
case class UserKey(bucketId: Int, email: String)
object CassandraUserRepository extends CassandraRepository[UserKey, User](...) {
// note that here you don't use I and M, but concrete types
def conditions(id: UserKey) = List(
QueryBuilder.eq("bucketId", id.bucketId),
QueryBuilder.eq("email", id.email)
)
def fromRow(row: Row): User = ...
}
实际上,您可以使用 Rich 答案中的解决方案来避免抽象conditions
。
我想你在这里陷入了困境。也许退后一步,考虑一下投入大量精力编写一个参数化存储库是否实际上比为不同的类使用不同的存储库更好。
话虽如此,我认为实现您想要的最简单的方法是使 Id 特征成为Product
,然后用partitionKeyColumns
zip
它,fold
并使用QueryBuilder
来制作您的"where"子句。