【发布时间】:2015-11-10 19:02:38
【问题描述】:
更新 为此问题创建了一个可运行的演示。
https://github.com/narayanjr/anorm_test
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
我无法访问别名表上的字段。我不断收到错误消息,说该字段不是一个选项,可用字段是基本字段名称或“table_name”.field_name。但不是别名字段名称。这使得不可能两次加入同一个表并访问所有字段。
var vendor_client_parser_1 = SqlParser.long("vid") ~ SqlParser.str("vname") ~ SqlParser.long("cid") ~ SqlParser.str("cname") map
{
case vid ~ vn ~ cid ~ cn => println(vid + "," + vn + "," + cid + "," + cn + ",")
}
var vendor_client_parser_2 = SqlParser.long("v.business_id") ~ SqlParser.str("v.name") ~ SqlParser.long("c.business_id") ~ SqlParser.str("c.name") map
{
case vid ~ vn ~ cid ~ cn => println(vid + "," + vn + "," + cid + "," + cn + ",")
}
var vendor_client_parser_3 = SqlParser.long(1) ~ SqlParser.str(2) ~ SqlParser.long(3) ~ SqlParser.str(4) map
{
case vid ~ vn ~ cid ~ cn => println(vid + "," + vn + "," + cid + "," + cn + ",")
}
DB.withConnection
{
implicit c =>
var results =
SQL"""
SELECT v.business_id AS vid, v.name AS vname, c.business_id AS cid, c.name AS cname
FROM #$BUSINESS_CONNECTION_TABLE
JOIN #$BUSINESS_TABLE AS v ON (vendor_id = v.business_id)
JOIN #$BUSINESS_TABLE AS c ON (client_id = c.business_id)
LIMIT 20
""".as(vendor_client_parser.*)
}
预期结果:
1, Vendor A, 10, Vendor K
2, Vendor B, 11, Vendor L
2, Vendor B, 1, Vendor A
12, Vendor M, 3, Vendor C
来自 vendor_client_parser_1 的结果:
10, Vendor K, 10, Vendor K
11, Vendor L, 11, Vendor L
1, Vendor A, 1, Vendor A
3, Vendor C, 3, Vendor C
来自 vendor_client_parser_2 的结果:
Execution exception[[AnormException: 'v.business_id' not found, available columns: business.business_id, business_id, business.name, name, business.business_id, business_id, business.name, name]]
来自 vendor_client_parser_3 的结果:(与预期相同)
1, Vendor A, 10, Vendor K
2, Vendor B, 11, Vendor L
2, Vendor B, 1, Vendor A
12, Vendor M, 3, Vendor C
vendor_client_parser_3 有效,但它依赖于使用索引而不是名称。我不喜欢使用索引,因为如果我弄乱了索引,我可能仍然会得到有效的响应而不会注意到。如果我弄乱了名称,该列将不存在,我会知道有问题。
我有什么遗漏吗?有什么方法可以在不依赖索引的情况下达到我需要的结果?
- 播放 Scala 2.4.1
- 异常 2.5.0
更新:
如果我不对列使用别名并使用vendor_client_parser_2,我会得到与列别名时相同的结果。
修改后的查询:
SQL"""
SELECT v.business_id, v.name, c.business_id, c.name
FROM #$BUSINESS_CONNECTION_TABLE
JOIN #$BUSINESS_TABLE AS v ON (vendor_id = v.business_id)
JOIN #$BUSINESS_TABLE AS c ON (client_id = c.business_id)
LIMIT 20
""".as(vendor_client_parser_2.*)
vendor_client_parser_2.* 的结果:
Execution exception[[AnormException: 'v.business_id' not found, available columns: business.business_id, business_id, business.name, name, business.business_id, business_id, business.name, name]]
我还用一个别名表对其进行了测试,它拒绝查看别名表名
单表测试:
SQL"""
SELECT v.business_id, v.name, business_id, name
FROM #$BUSINESS_TABLE AS v
LIMIT 20
""".as(test_parser.*)
test_parser:
var test_parser = SqlParser.long("v.business_id") ~ SqlParser.str("v.name") ~ SqlParser.long("business_id") ~ SqlParser.str("name") map
{
case vid ~ vn ~ cid ~ cn => println(vid + "," + vn + "," + cid + "," + cn + ",")
}
结果:
[AnormException: 'v.business_id' not found, available columns: business.business_id, business_id, business.name, name, business.business_id, business_id, business.name, name]
然后我测试了别名列是否可以通过其原始名称和别名名称访问。
测试别名列:
SQL"""
SELECT business_id AS vid, name AS vname
FROM #$BUSINESS_TABLE
LIMIT 20
""".as(test_parser_2.*)
test_parser_2:
var test_parser_2 = SqlParser.long("business_id") ~ SqlParser.str("name") ~ SqlParser.long("vid") ~ SqlParser.str("vname") map
{
case vid ~ vn ~ cid ~ cn => println(vid + "," + vn + "," + cid + "," + cn + ",")
}
此测试没有出错,它正确地提取了 business_id 和 vid 值。以及 name 和 vname。
我强迫它出错,所以它会给我一个列名列表。看起来 Anorm 并没有提供非别名名称作为建议,但它们在这种情况下确实有效。
[AnormException: 'forceError' not found, available columns: business.business_id, vid, business.name, vname]
我也试过不使用 SqlParser。
var businesses = SQL"""
SELECT v.business_id AS vid, v.name AS vname, c.business_id AS cid, c.name AS cname
FROM #$BUSINESS_CONNECTION_TABLE
JOIN #$BUSINESS_TABLE AS v ON (vendor_id = v.business_id)
JOIN #$BUSINESS_TABLE AS c ON (client_id = c.business_id)
LIMIT 20
""".fold(List[(Long, String, Long, String)]())
{
(list, row) =>
list :+ (row[Long]("v.business_id"), row[String]("v.name"), row[Long]("c.business_id"), row[String]("c.name")) //attempt_1
//list :+ (row[Long]("vid"), row[String]("vname"), row[Long]("cid"), row[String]("cname")) //attempt_2
}
如果我使用尝试_1,我会收到这个错误,正如你所建议的那样,它不应该起作用。
Left('v.business_id' not found, available columns: business.business_id, vid, business.name, vname, business.business_id, cid, business.name, cname)))
如果我使用尝试_2,我会得到与 vendor_client_parser_1 相同的结果
10, Vendor K, 10, Vendor K
11, Vendor L, 11, Vendor L
1, Vendor A, 1, Vendor A
3, Vendor C, 3, Vendor C
如果我不对列设置别名并使用相同的方法
SQL"""
SELECT v.business_id, v.name, c.business_id, c.name
FROM #$BUSINESS_CONNECTION_TABLE
JOIN #$BUSINESS_TABLE AS v ON (vendor_id = v.business_id)
JOIN #$BUSINESS_TABLE AS c ON (client_id = c.business_id)
LIMIT 20
""".fold(List[(Long, String, Long, String)]())
{
(list, row) =>
list :+ (row[Long]("v.business_id"), row[String]("v.name"), row[Long]("c.business_id"), row[String]("c.name")) //Attempt_3
}
使用此查询而不给列添加别名会导致此错误,
Left('v.business_id' not found, available columns: business.business_id, business_id, business.name, name, business.business_id, business_id, business.name, name)))
然后我使用这种方法测试了一个简单的别名表
SQL"""
SELECT v.business_id, v.name
FROM #$BUSINESS_TABLE AS v
LIMIT 20
""".fold(List[(Long, String)]())
{
(list, row) =>
list :+ (row[Long]("v.business_id"), row[String]("v.name")) //simple_attempt_1
}
我遇到同样的错误
Left(List(java.lang.RuntimeException: Left('v.business_id' not found, available columns: business.business_id, business_id, business.name, name)))
据我所知,如果使用字段名称而不是索引两次使用同一个表,则无法访问作为别名表一部分的字段。
更新 2:
我尝试颠倒 SQL 中字段的顺序,使其为 c.business_id AS cid, c.name AS cname, v.business_id AS vid, v.name AS vname 并重新运行 vendor_client_parser_1。它给了我相反的结果
vendor_client_parser_1 的结果,mysql 字段已切换:
1, Vendor A, 1, Vendor A
2, Vendor B, 2, Vendor B
2, Vendor B, 2, Vendor B
12, Vendor M, 12, Vendor M
当我强制出错并显示我得到这些可能的字段时,
按原顺序排列的字段:
Left('forceError' not found, available columns: business.business_id, vid, business.name, vname, business.business_id, cid, business.name, cname)
切换顺序的字段:
Left('forceError' not found, available columns: business.business_id, cid, business.name, cname, business.business_id, vid, business.name, vname)
这让我觉得这种情况正在发生。
如果在查询结果中发现多个具有相同名称的列,例如 Country 和 CountryLanguage 表中名为 code 的列,则可能存在歧义。默认情况下,如下映射将使用最后一列:
https://www.playframework.com/documentation/2.4.1/ScalaAnorm
如果您查看建议的字段 business.business_id 和 business.name 出现两次,因为该表被引用了两次。似乎 Anorm 将最后一次出现的 business.business_id 和 business.name 与两个别名相关联。
更新 为此问题创建了一个可运行的演示。 https://github.com/narayanjr/anorm_test
【问题讨论】:
-
一旦为列设置别名,就无法使用原始名称访问它。如果你想使用它,不要给它加上别名,或者有两次列(带 & 不带别名)。
-
@cchantep 我尝试按照您的建议进行更改。结果已添加到问题中。
-
如果你查看错误的详细信息,你会发现列的FQDN不是用表的别名计算的,有
v,而只是用原始表名。越简单越好:确保您的 SELECT 使用唯一的列或别名来投影值,并且只使用这些简单的唯一名称,这里只是"business_id"和"name"。 -
@cchantep 我已经尝试过了,但它似乎无法正常工作。看看
vendor_client_parser_1和我从中得到的结果。那是使用唯一的别名,但结果是错误的。cid和cname的值同时用于vid和 `vname。这有什么关系吗? "如果在查询结果中发现多个具有相同名称的列,例如 Country 和 CountryLanguage 表中名为 code 的列,则可能存在歧义。默认情况下,如下所示的映射将使用最后一列 " playframework.com/documentation/2.4.1/ScalaAnorm -
在 Anorm 中测试了对列别名的支持。确保所有名称都是唯一的,并按照提示检查哪些名称可用(在错误详细信息中)。
标签: scala anorm playframework-2.4