以下trait定义了表示数据库的类应该实现的常用方法。它有一个方法getOneById
,它接受id
(比如对应表的主键)并返回一些值或None
。 id
可以是单个值(例如电子邮件ID)或多个值(例如桶ID和电子邮件ID),例如,bucket = 1和email =" 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))
我怎么能写出这样的通用特征?
答案 0 :(得分:1)
同样,您正在混合类型和类型参数。如果您希望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
。
答案 1 :(得分:0)
我觉得你在这里陷入困境。也许退一步考虑是否花费大量精力编写一个参数化的Repository实际上比为不同的类具有不同的Repositories更好。
话虽如此,我认为在这里达到你想要的最简单的方法是将Id特性设为Product
,然后使用zip
和{{1}设置partitionKeyColumns
使用fold
制作“where”子句。