Play2的anorm不能在postgresql上工作

前端之家收集整理的这篇文章主要介绍了Play2的anorm不能在postgresql上工作前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我发现play2的动画的行解析器取决于jdbc驱动程序返回的元数据。

所以在播放中提供的内置示例“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)
    }
  }
}

请注意,这些字段都有一个项目。字首。

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

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

我问过this in play’s google group,而纪尧姆博特说:

@H_404_13@

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驱动程序真的有这个问题,我认为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.创建anorm模型

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,a_id) 
          values (
          {id},{name},{aId}
          )
          """).on('id -> id,'name -> b.name,'aId -> b.aId).executeUpdate()
      b.copy(id = Id(id))
    }
  }
}

3.测试用例

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,它不起作用,因为类的名称将是“com.p6spy ….”,而不是“org.postgresql ….”。

猜你在找的Postgre SQL相关文章