可选表和非可选表之间的联合
Union between optional and non-optional tables
我有两个查询 select 记录了需要进行并集的位置,其中一个是左连接,另一个是常规(即内部)连接。
这是左连接案例:
def regularAccountRecords = for {
(customer, account) <- customers joinLeft accounts on (_.accountId === _.accountId) // + some other special conditions
} yield (customer, account)
这是常规的连接案例:
def specialAccountRecords = for {
(customer, account) <- customers join accounts on (_.accountId === _.accountId) // + some other special conditions
} yield (customer, account)
现在我想合并两个记录集:
regularAccountRecords ++ specialAccountRecords
显然这不起作用,因为在常规连接情况下它 returns Query[(Customer, Account),...]
而在左连接情况下它 returns Query[(Customer, Rep[Option[Account]]),...]
这导致类型不匹配错误。
现在,如果这是常规列类型(例如 Rep[String]
),我可以通过 ?
运算符(即 record.?
)将其转换为可选类型并得到 Rep[Option[String]]
但在 table(即帐户 table)上使用它会导致:
Error:(62, 85) value ? is not a member of com.test.Account
我该如何解决这个问题并正确地进行合并?
好的,看起来这是什么'?'投影是为了但我没有意识到它,因为我在 Codegen 中禁用了 optionEnabled
选项。这是您的 codegen 扩展应该是这样的:
class MyCodegen extends SourceCodeGenerator(inputModel) {
override def TableClass = new TableClassDef {
override def optionEnabled = true
}
}
或者,您可以使用隐式 类 将此内容添加到您自己生成的 TableClass 中。这是它的样子:
implicit class AccountExtensions(account:Account) {
def ? = (Rep.Some(account.id), account.name).shaped.<>({r=>r._1.map(_=> Account.tupled((r._2, r._1.get)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported."))
}
NOTE: be sure to check the field ordering, depending on how this
projection is done, the union query might put the ID field in the wrong
place in the output, use
println(query.result.statements.headOption)
to debug the output
SQL to be sure.
完成后,您就可以使用帐户了。?在 yield 语句中:
def specialAccountRecords = for {
(customer, account) <- customers join accounts on (_.accountId === _.accountId)
} yield (customer, account.?)
...然后您将能够正确合并表
regularAccountRecords ++ specialAccountRecords
我真希望 Slick 的人能在 '?' 上写个注释除了模糊声明 'useful for outer joins'.
之外,投影在文档中很有用
我有两个查询 select 记录了需要进行并集的位置,其中一个是左连接,另一个是常规(即内部)连接。
这是左连接案例:
def regularAccountRecords = for {
(customer, account) <- customers joinLeft accounts on (_.accountId === _.accountId) // + some other special conditions
} yield (customer, account)
这是常规的连接案例:
def specialAccountRecords = for {
(customer, account) <- customers join accounts on (_.accountId === _.accountId) // + some other special conditions
} yield (customer, account)
现在我想合并两个记录集:
regularAccountRecords ++ specialAccountRecords
显然这不起作用,因为在常规连接情况下它 returns Query[(Customer, Account),...]
而在左连接情况下它 returns Query[(Customer, Rep[Option[Account]]),...]
这导致类型不匹配错误。
现在,如果这是常规列类型(例如 Rep[String]
),我可以通过 ?
运算符(即 record.?
)将其转换为可选类型并得到 Rep[Option[String]]
但在 table(即帐户 table)上使用它会导致:
Error:(62, 85) value ? is not a member of com.test.Account
我该如何解决这个问题并正确地进行合并?
好的,看起来这是什么'?'投影是为了但我没有意识到它,因为我在 Codegen 中禁用了 optionEnabled
选项。这是您的 codegen 扩展应该是这样的:
class MyCodegen extends SourceCodeGenerator(inputModel) {
override def TableClass = new TableClassDef {
override def optionEnabled = true
}
}
或者,您可以使用隐式 类 将此内容添加到您自己生成的 TableClass 中。这是它的样子:
implicit class AccountExtensions(account:Account) {
def ? = (Rep.Some(account.id), account.name).shaped.<>({r=>r._1.map(_=> Account.tupled((r._2, r._1.get)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported."))
}
NOTE: be sure to check the field ordering, depending on how this projection is done, the union query might put the ID field in the wrong place in the output, use
println(query.result.statements.headOption)
to debug the output SQL to be sure.
完成后,您就可以使用帐户了。?在 yield 语句中:
def specialAccountRecords = for {
(customer, account) <- customers join accounts on (_.accountId === _.accountId)
} yield (customer, account.?)
...然后您将能够正确合并表
regularAccountRecords ++ specialAccountRecords
我真希望 Slick 的人能在 '?' 上写个注释除了模糊声明 'useful for outer joins'.
之外,投影在文档中很有用