为 Seq 提供 Get 实例
provide Get instance for Seq
例如,我有一些带有一些参数的实体和两个数据库表,代表这些实体:
entity param
╔════╦═════════╗ ╔═══════════╦════════╗
║ id ║ name ║ ║ entity_id ║ value ║
╠════╬═════════╣ ╠═══════════╬════════╣
║ 1 ║ "One" ║ ║ 1 ║ "aaa" ║
║ 2 ║ "Two" ║ ║ 1 ║ "bbb" ║
║ 3 ║ "Three" ║ ║ 1 ║ "ccc" ║
╚════╩═════════╝ ╚═══════════╩════════╝
还有一个 Scala 模型:
case class Entity(id: Long, name: String, params: Seq[String])
我想通过 Doobie
检索这些数据,但我不能直接对 Entity
实例进行检索,因为 params
是一个字符串序列,而不是只是字符串:
val sql = sql"select e.id, e.name, p.value from entity e left join param p on e.id = p.entity_id"
sql.query[Entity].to[Seq] //Error Cannot find or construct a Read instance for type: Entity
有什么技巧可以为 Seq
提供 Get
实例吗?
如果没有,有什么办法,Doobie
提供检索这样的数据:
- 写基元而不是
Entity
类型:
sql.query[(Long, String, String)].to[Seq]
并将此元组序列组合到 Entity
实例。
可能不方便,因为表可能有很多列,是什么导致将这个长元组复制粘贴到每个新查询中。
- 将此基元组合成另一种情况 类:
case class EntityRow(id: Long, name: String)
case class ParamRow(value: String)
sql.query[(EntityRow, ParamRow)].to[Seq]
并组成 Entity
实例,如 1.
.
- 类似于
2.
,但使用HNil
:
val entity = Long :: String :: HNil
val param = String :: HNil
sql.query[entity ++ param].to[Seq]
并组成 Entity
实例,如 1.
.
我不知道这种方式有什么优点或缺点,因为 shapeless
对我来说是个新事物。
- 使用两个单独的查询检索数据:
val entities = sql"select id, name from entity".query[EntityRow].to[Seq]
val params = sql"select value from param".query[ParamRow].to[Seq]
可能不如通过单个查询那么性能。
- 还有别的方法吗?
谢谢。
您的案例 class Entity
期望 params
与 id 和 name 列组合在一起作为字符串列表,
而 sql 查询 select e.id, e.name, p.value from entity e left join param p on e.id = p.entity_id
将 return 包含 id、名称和值的行
joined entity
╔════╦═════════╦════════╗
║ id ║ name ║ value ║
╠════╬═════════╬════════╣
║ 1 ║ "One" ║ "aaa" ║
║ 1 ║ "One" ║ "bbb" ║
║ 1 ║ "One" ║ "ccc" ║
║ 2 ║ "Two" ║ ║
║ 3 ║ "Three" ║ ║
╚════╩═════════╩════════╝
这不是您想要的。
为此,我们需要重写 sql 查询,如下所示
val entities = sql"select e.id, e.name, GROUP_CONCAT(p.value SEPARATOR ',') as params from entity e left join param p on e.id = p.entity_id group by e.id, e.name".query[Entity]
现在您可以轻松地将 sql 查询输出映射到您的案例 class。
例如,我有一些带有一些参数的实体和两个数据库表,代表这些实体:
entity param
╔════╦═════════╗ ╔═══════════╦════════╗
║ id ║ name ║ ║ entity_id ║ value ║
╠════╬═════════╣ ╠═══════════╬════════╣
║ 1 ║ "One" ║ ║ 1 ║ "aaa" ║
║ 2 ║ "Two" ║ ║ 1 ║ "bbb" ║
║ 3 ║ "Three" ║ ║ 1 ║ "ccc" ║
╚════╩═════════╝ ╚═══════════╩════════╝
还有一个 Scala 模型:
case class Entity(id: Long, name: String, params: Seq[String])
我想通过 Doobie
检索这些数据,但我不能直接对 Entity
实例进行检索,因为 params
是一个字符串序列,而不是只是字符串:
val sql = sql"select e.id, e.name, p.value from entity e left join param p on e.id = p.entity_id"
sql.query[Entity].to[Seq] //Error Cannot find or construct a Read instance for type: Entity
有什么技巧可以为 Seq
提供 Get
实例吗?
如果没有,有什么办法,Doobie
提供检索这样的数据:
- 写基元而不是
Entity
类型:
sql.query[(Long, String, String)].to[Seq]
并将此元组序列组合到Entity
实例。
可能不方便,因为表可能有很多列,是什么导致将这个长元组复制粘贴到每个新查询中。 - 将此基元组合成另一种情况 类:
case class EntityRow(id: Long, name: String)
case class ParamRow(value: String)
sql.query[(EntityRow, ParamRow)].to[Seq]
并组成Entity
实例,如1.
. - 类似于
2.
,但使用HNil
:
val entity = Long :: String :: HNil
val param = String :: HNil
sql.query[entity ++ param].to[Seq]
并组成Entity
实例,如1.
.
我不知道这种方式有什么优点或缺点,因为shapeless
对我来说是个新事物。 - 使用两个单独的查询检索数据:
val entities = sql"select id, name from entity".query[EntityRow].to[Seq]
val params = sql"select value from param".query[ParamRow].to[Seq]
可能不如通过单个查询那么性能。 - 还有别的方法吗?
谢谢。
您的案例 class Entity
期望 params
与 id 和 name 列组合在一起作为字符串列表,
而 sql 查询 select e.id, e.name, p.value from entity e left join param p on e.id = p.entity_id
将 return 包含 id、名称和值的行
joined entity
╔════╦═════════╦════════╗
║ id ║ name ║ value ║
╠════╬═════════╬════════╣
║ 1 ║ "One" ║ "aaa" ║
║ 1 ║ "One" ║ "bbb" ║
║ 1 ║ "One" ║ "ccc" ║
║ 2 ║ "Two" ║ ║
║ 3 ║ "Three" ║ ║
╚════╩═════════╩════════╝
这不是您想要的。 为此,我们需要重写 sql 查询,如下所示
val entities = sql"select e.id, e.name, GROUP_CONCAT(p.value SEPARATOR ',') as params from entity e left join param p on e.id = p.entity_id group by e.id, e.name".query[Entity]
现在您可以轻松地将 sql 查询输出映射到您的案例 class。