类型 MapColumn、SetColumn、JsonColumn 需要所有者和记录。这些值究竟是什么?
Types MapColumn, SetColumn, JsonColumn needs owner and record. What actually are these values?
比如我有
type MapColumn[Owner <: com.websudos.phantom.dsl.CassandraTable[Owner, Record], Record, K, V] =
com.websudos.phantom.column.MapColumn[Owner, Record, K, V]
K
和 V
很明显,但是所有者和记录?我应该在那里输入什么?
phantom 的全部力量在于它能够围绕您的数据模型进行映射并返回类型安全的结果,或者说我在编写它时就想到了。 Owner
类型参数是用户编写的 table 的类型,它是必需的,因此您可以执行以下操作:
select.where(_.id eqs id)
看起来很简单,但诀窍在于,如果没有经过优化的类型参数,编译器可以 "memorize" 您在 table 中任意定义的列,您将永远无法 "know" 在 DSL 代码中用户写入了哪些列。
因此 DSL 必须知道您将通过扩展 CassandraTable
.
创建的 table 的最终类型
case class MyRecord(id: UUID, name: String)
class MyTable extends CassandraTable[MyTable, MyRecord] {
object id extends UUIDColumn(this) with PartitionKey[UUID]
// MyTable is Owner and MyRecord is Record.
object mapColumn extends MapColumn[MyTable, MyRecord, String, String](this)
}
所以这就是为什么所有的查询构建器都是从 table: Owner
到其他东西的函数。即使上面只是 shorthand 表示法:
select.where(table => table.id eqs id)
Record
类型使 Cassandra 结果类型安全。通过告诉你的 table 什么情况 class 它环绕,phantom 能够使用隐式 api 方法将所有结果映射回这种情况 class,而不是处理类似的事情:
res.getString("mystring")
这样的事情在引擎盖下是不可见的处理,并且由返回的 Cassandra 行产生的幻影 "knows" 属于 case class
中的哪个字段。它非常简洁且效率更高,因为您真的不想关心驱动程序如何处理客户端和数据库之间的 Netty 缓冲区和 CQL 消息交换的内部解析,您只需要返回记录。
因此需要 Record
与 fromRow
方法相结合,它们不仅在那些列中传递,而且在每一列中传递。唯一的区别是使用 StringColumn
,编译器能够为您推断 T
和 R
的类型,因此您不必键入它。
这是因为:
type StringColumn[
Owner <: CassandraTable[Owner, Record],
Record
] = com.websudos.phantom.column.PrimitiveColumn[Owner, Record, String]
所以实际上所有的专栏都需要这个。集合需要用户提供的一个额外参数(或两个在映射的情况下),因此编译器无法像 StringColumn
或 BooleanColumn
那样推断类型,因此您需要手动输入它们。
在 phantom 1.26.0+ 中,这已经改变,额外的类型参数现在也是不可见的,所以你可以输入以下内容,而不必指定 Owner
和 Record
.
object map extends MapColumn[String, String](this)
比如我有
type MapColumn[Owner <: com.websudos.phantom.dsl.CassandraTable[Owner, Record], Record, K, V] =
com.websudos.phantom.column.MapColumn[Owner, Record, K, V]
K
和 V
很明显,但是所有者和记录?我应该在那里输入什么?
phantom 的全部力量在于它能够围绕您的数据模型进行映射并返回类型安全的结果,或者说我在编写它时就想到了。 Owner
类型参数是用户编写的 table 的类型,它是必需的,因此您可以执行以下操作:
select.where(_.id eqs id)
看起来很简单,但诀窍在于,如果没有经过优化的类型参数,编译器可以 "memorize" 您在 table 中任意定义的列,您将永远无法 "know" 在 DSL 代码中用户写入了哪些列。
因此 DSL 必须知道您将通过扩展 CassandraTable
.
case class MyRecord(id: UUID, name: String)
class MyTable extends CassandraTable[MyTable, MyRecord] {
object id extends UUIDColumn(this) with PartitionKey[UUID]
// MyTable is Owner and MyRecord is Record.
object mapColumn extends MapColumn[MyTable, MyRecord, String, String](this)
}
所以这就是为什么所有的查询构建器都是从 table: Owner
到其他东西的函数。即使上面只是 shorthand 表示法:
select.where(table => table.id eqs id)
Record
类型使 Cassandra 结果类型安全。通过告诉你的 table 什么情况 class 它环绕,phantom 能够使用隐式 api 方法将所有结果映射回这种情况 class,而不是处理类似的事情:
res.getString("mystring")
这样的事情在引擎盖下是不可见的处理,并且由返回的 Cassandra 行产生的幻影 "knows" 属于 case class
中的哪个字段。它非常简洁且效率更高,因为您真的不想关心驱动程序如何处理客户端和数据库之间的 Netty 缓冲区和 CQL 消息交换的内部解析,您只需要返回记录。
因此需要 Record
与 fromRow
方法相结合,它们不仅在那些列中传递,而且在每一列中传递。唯一的区别是使用 StringColumn
,编译器能够为您推断 T
和 R
的类型,因此您不必键入它。
这是因为:
type StringColumn[
Owner <: CassandraTable[Owner, Record],
Record
] = com.websudos.phantom.column.PrimitiveColumn[Owner, Record, String]
所以实际上所有的专栏都需要这个。集合需要用户提供的一个额外参数(或两个在映射的情况下),因此编译器无法像 StringColumn
或 BooleanColumn
那样推断类型,因此您需要手动输入它们。
在 phantom 1.26.0+ 中,这已经改变,额外的类型参数现在也是不可见的,所以你可以输入以下内容,而不必指定 Owner
和 Record
.
object map extends MapColumn[String, String](this)