2013-02-06 20 views
9

我有一個表與具有ltree類型的列中的一個,並將下面的代碼從它讀取數據:ANORM串從postgres的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只是一個普通的字符串?或者我錯過了什麼?

UPD

的問題仍然適用,但這裏是一個解決辦法:

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

表'queue'的模式是什麼? –

+0

@JasonWebb更新了問題。 – zapadlo

+1

此鏈接可能會有所幫助: http://stackoverflow.com/questions/20024357/how-to-get-char-values-from-postgres-with-anorm –

回答

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) 
    } 
    } 
} 

然後你可以一個ltree映射到Seq[String]。請注意,它是一系列路徑元素順序問題,因此它是Seq[String],而不是StringSet[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