2015-06-19 63 views
2

鑑於以下Person SQL和型號代碼:JDBC插入與Postgres的枚舉

SQL

CREATE TYPE sex AS ENUM ('male', 'female'); 

CREATE TABLE person (
    id bigserial primary key, 
    name varchar(100) NOT NULL, 
    age integer NOT NULL, 
    gender sex NOT NULL); 

代碼

object Person { 

    sealed trait Gender 
    case object Male extends Gender 
    case object Female extends Gender 

    // credit to Travis Brown: http://stackoverflow.com/a/30946172/409976 
    implicit val GenderShows: Show[Gender] = Show.shows { 
     case Male => "male" 
     case Female => "female" 
    } 

} 

case class Person private(id: Option[Long], name: String, age: Int, gender: Person.Gender) 

我寫了下面的對象創建Person

object PostgresRepository { 

    val xa = DriverManagerTransactor[IO](
     "org.postgresql.Driver", "jdbc:postgresql:person", "postgres", "postgres" 
    ) 

    def insert1(name: String, age: Int, gender: Gender) = 
     sql"insert into person (name, age, gender) values 
      ($name, $age, 
     ${implicitly[Show[Gender]].shows(gender)})".update.run.transact(xa) 
} 

然後,我跑sbt console,並試圖插入:

scala> PostgresRepository.insert1("foo", 3, net.phone.model.Person.Male) 
res0: scalaz.effect.IO[Int] = [email protected] 

scala> res0.unsafePerformIO 
org.postgresql.util.PSQLException: ERROR: column "gender" is of type sex but expression is of type character varying 
    Hint: You will need to rewrite or cast the expression. 
    Position: 56 

回答

3

由於異常已經建議,你需要轉換枚舉值表達式。

def insert1(name: String, age: Int, gender: Gender) = { 
    val sgender = implicitly[Show[Gender]].shows(gender) 
    sql"insert into person (name, age, gender) 
      values ($name, $age, CAST($sgender AS sex)) 
     ".update.run.transact(xa) 
} 
+1

謝謝,馬丁。當然'casting'強烈反對函數式編程 - 因爲它可以在運行時失敗,導致異常。澆鑄-ING一個可以接受的做法,即有沒有替代方案,在數據庫級別? –