gpt4 book ai didi

postgresql - Play 2's anorm can' t 在 postgresql 上工作

转载 作者:行者123 更新时间:2023-11-29 11:11:20 26 4
gpt4 key购买 nike

我发现play2的异常的行解析器依赖于jdbc驱动返回的元数据。

所以在play提供的内置示例“zentasks”中,我可以找到这样的代码:

object Project {
val simple = {
get[Pk[Long]]("project.id") ~
get[String]("project.folder") ~
get[String]("project.name") map {
case id~folder~name => Project(id, folder, name)
}
}
}

请注意,所有字段都有一个 project. 前缀。

它在 h2 数据库上运行良好,但在 postgresql 上运行不佳。如果我使用 portgresql,我应该这样写:

object Project {
val simple = {
get[Pk[Long]]("id") ~
get[String]("folder") ~
get[String]("name") map {
case id~folder~name => Project(id, folder, name)
}
}
}

我问过this in play's google group , Guillaume Bort 说:

Yes if you are using postgres it's probably the cause. The postgresql jdbc driver is broken and doesn't return table names.

如果postgresql的jdbc driver真的有这个问题,我觉得anorm会有问题:如果两个表有同名的字段,我用join查询它们,anorm不会得到正确的值,因为它找不到属于哪个名字到哪个表。

所以我写了一个测试。

1。在 postgresql 上创建表

create table a (
id text not null primary key,
name text not null
);

create table b (
id text not null primary key,
name text not null,
a_id text,
foreign key(a_id) references a(id) on delete cascade
);

2。创建异常模型

case class A(id: Pk[String] = NotAssigned, name: String)
case class B(id: Pk[String] = NotAssigned, name: String, aId: String)

object A {
val simple = {
get[Pk[String]]("id") ~
get[String]("name") map {
case id ~ name =>
A(id, name)
}
}

def create(a: A): A = {
DB.withConnection { implicit connection =>
val id = newId()
SQL("""
insert into a (id, name)
values (
{id}, {name}
)
""").on('id -> id, 'name -> a.name).executeUpdate()
a.copy(id = Id(id))
}
}

def findAll(): Seq[(A, B)] = {
DB.withConnection { implicit conn =>
SQL("""
select a.*, b.* from a as a left join b as b on a.id=b.a_id
""").as(A.simple ~ B.simple map {
case a ~ b => a -> b
} *)
}
}
}

object B {
val simple = {
get[Pk[String]]("id") ~
get[String]("name") ~
get[String]("a_id") map {
case id ~ name ~ aId =>
B(id, name, aId)
}
}

def create(b: B): B = {
DB.withConnection { implicit conneciton =>
val id = UUID.randomUUID().toString
SQL("""
insert into b (id, name, a_id)
values (
{id}, {name}, {aId}
)
""").on('id -> id, 'name -> b.name, 'aId -> b.aId).executeUpdate()
b.copy(id = Id(id))
}
}
}

3。 scalatest 测试用例

class ABTest extends DbSuite {

"AB" should "get one-to-many" in {
running(fakeApp) {
val a = A.create(A(name = "AAA"))
val b1 = B.create(B(name = "BBB1", aId = a.id.get))
val b2 = B.create(B(name = "BBB2", aId = a.id.get))

val ab = A.findAll()
ab foreach {
case (a, b) => {
println("a: " + a)
println("b: " + b)
}
}
}
}
}

4。输出

a: A(dbc52793-0f6f-4910-a954-940e508aab26,BBB1)
b: B(dbc52793-0f6f-4910-a954-940e508aab26,BBB1,4a66ebe7-536e-4bd5-b1bd-08f022650f1f)
a: A(d1bc8520-b4d1-40f1-af92-52b3bfe50e9f,BBB2)
b: B(d1bc8520-b4d1-40f1-af92-52b3bfe50e9f,BBB2,4a66ebe7-536e-4bd5-b1bd-08f022650f1f)

您可以看到“a”的名称为“BBB1/BBB2”,而不是“AAA”。

我尝试将带有前缀的解析器重新定义为:

 val simple = {
get[Pk[String]]("a.id") ~
get[String]("a.name") map {
case id ~ name =>
A(id, name)
}
}

但是会报找不到指定字段的错误。

是异常的大问题吗?还是我错过了什么?

最佳答案

最新的play2(RC3)通过检查元对象的类名解决了这个问题:

// HACK FOR POSTGRES
if (meta.getClass.getName.startsWith("org.postgresql.")) {
meta.asInstanceOf[{ def getBaseTableName(i: Int): String }].getBaseTableName(i)
} else {
meta.getTableName(i)
}

但是如果你想将它与 p6spy 一起使用时要小心,它不起作用,因为 meta 的类名将是“com.p6spy ....”,而不是“org.postgresql” ……”。

关于postgresql - Play 2's anorm can' t 在 postgresql 上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9247064/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com