无法创建定义通用行为的特征

  • 本文关键字:特征 创建 定义 scala
  • 更新时间 :
  • 英文 :


遵循特征定义了表示数据库的类应该实现的常用方法。它有一个方法getOneById它接受一个id(比如对应于表的主键)并返回一些值或Noneid可以是单个值(例如电子邮件 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:Intemail:String作为主键,在这种情况下,查询中的代码将.where(QueryBuilder.eq(partitionKeyColumns(0), id.bucketId))).and(QueryBuilder.eq(partitionKeyColumns(1), id.email))
  • Product表可以将bucketId:IntproductCode: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,然后用partitionKeyColumnszip它,fold并使用QueryBuilder来制作您的"where"子句。

最新更新