9

我有一个表,其中一个列具有 ltree 类型,以下代码从中获取数据:

SQL("""select * from "queue"""")()
.map(
    row =>
        {
            val queue =
                Queue(
                    row[String]("path"),
                    row[String]("email_recipients"),
                    new DateTime(row[java.util.Date]("created_at")),
                    row[Boolean]("template_required")
                )
            queue
        }
).toList

这会导致以下错误:

RuntimeException: TypeDoesNotMatch(Cannot convert notification.en.incident_happened:class org.postgresql.util.PGobject to String for column ColumnName(queue.path,Some(path)))

队列表模式如下:

CREATE TABLE queue
(
  id serial NOT NULL,
  template_id integer,
  template_version integer,
  path ltree NOT NULL,
  json_params text,
  email_recipients character varying(1024) NOT NULL,
  email_from character varying(128),
  email_subject character varying(512),
  created_at timestamp with time zone NOT NULL,
  sent_at timestamp with time zone,
  failed_recipients character varying(1024),
  template_required boolean NOT NULL DEFAULT true,
  attachments hstore,
  CONSTRAINT pk_queue PRIMARY KEY (id ),
  CONSTRAINT fk_queue__email_template FOREIGN KEY (template_id)
      REFERENCES email_template (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE RESTRICT
)
WITH (
  OIDS=FALSE
);
ALTER TABLE queue
  OWNER TO postgres;
GRANT ALL ON TABLE queue TO postgres;
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE queue TO writer;
GRANT SELECT ON TABLE queue TO reader;

这是为什么?不notification.en.incident_happened就是一个普通的字符串吗?还是我错过了什么?

更新

这个问题仍然适用,但这里有一个解决方法:

SQL("""select id, path::varchar, email_recipients, created_at, template_required from "queue"""")()
4

1 回答 1

4

这看起来是一个有趣的项目,所以我实现了 ltree 列映射器。

我捎带了anorm-postgresql,因为该项目已经在 anorm 中实现了一些 postgres 类型。它看起来不错,如果它实现了所有的 postgres 类型,它会很有用。我的代码已合并,因此您可以使用该库。或者,只需使用以下代码:

import org.postgresql.util.PGobject
import anorm._
object LTree {
  implicit def rowToStringSeq: Column[Seq[String]] = Column.nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
      value match {
        case pgo:PGobject => {
          val seq = pgo.getValue().split('.')
          Right(seq.toSeq)
        }
        case x => Left(TypeDoesNotMatch(x.getClass.toString))
      }
    }
    implicit def stringSeqToStatement = new ToStatement[Seq[String]] {
      def set(s: java.sql.PreparedStatement, index: Int, aValue: Seq[String]) {
      val stringRepresentation = aValue.mkString(".")
      val pgo:org.postgresql.util.PGobject = new org.postgresql.util.PGobject()
      pgo.setType("ltree");
      pgo.setValue( stringRepresentation );
      s.setObject(index, pgo)
    }
  }
}

然后您可以将 a 映射ltree到 a Seq[String]。请注意,它是一系列路径元素顺序很重要,因此它是 a Seq[String],而不是Stringor Set[String]。如果您想要一个字符串,只需说path.mkString("."). 下面的用法:

import LTree._

SQL("""select * from "queue"""")()
.map(
    row =>
        {
            val queue =
                Queue(
                    row[Seq[String]]("path"),
                    row[String]("email_recipients"),
                    new DateTime(row[java.util.Date]("created_at")),
                    row[Boolean]("template_required")
                )
            queue
        }
).toList
于 2014-08-13T06:04:08.873 回答