2013-10-09 117 views
24

枚舉值我有後續枚舉:如何堅持光滑

object LoginStatus extends Enumeration() with BitmaskedEnumeration { 
    type LoginStatus = Value 
    val Active = Value("A") 
    val Inactive = Value("I") 
} 

我需要堅持枚舉的「A」的值,但生成的SQL時,結果爲0。 這是表映射:

object LoginTable extends Table[Login]("login") { 
    def idLogin = column[Int]("idlogin", O.PrimaryKey, O.AutoInc) 
    def cdLogin = column[String]("cdlogin", O.NotNull) 
    def cdPass = column[String]("cdPass", O.NotNull) 
    def stLogin = column[LoginStatus]("stlogin", O.NotNull, O.DBType("character(1)")) 
} 

如何持久枚舉值?

我實現

implicit val charMapper = MappedTypeMapper.base[Char, String](
    b => b.toString(), 
    i => i.charAt(0)) 

    implicit def enum2StringMapper(enum: Enumeration) = MappedTypeMapper.base[enum.Value, Char](
    b => b.toString.charAt(0), 
    i => enum.withName(i.toString)) 

    implicit val LoginStatusMapper = enum2StringMapper(LoginStatus) 

,反而會導致:

implicit val LoginStatusTypeMapper = MappedTypeMapper.base[LoginStatus.Value, Int]( 
    // conversion from LoginStatus to int 
    { 
    status => status.id 
    }, 
    // conversion back from int to enum 
    { 
    id => LoginStatus(id) 
    } 
) 

,那麼你需要引用您的列:

[error] c.Login - Invalid value for type int : A 
+0

這是有點相關http://stackoverflow.com/questions/19030875/how-can-i-create-a-custom-column-type-with-typesafe-slick-in-scala/19040124#19040124 – cvogt

+0

這個也在Slick郵件列表上討論https://groups.google.com/d/msg/scalaquery/Cd5iG-tJchM/fEIhq8IPVJQJ – cvogt

+0

也與http://stackoverflow.com/questions/18752929/how-to-use相關-sens-in-scala-slick – cvogt

回答

18

我個人建議從Scala的枚舉類製作自己的類繼承,因爲你不必爲你最終使用的每一個枚舉創建映射器:

這裏是我目前使用的光滑2.0代碼:

abstract class DBEnum extends Enumeration { 

    import slick.jdbc.MappedJdbcType 
    import slick.driver.JdbcDriver.simple._ 

    implicit val enumMapper = MappedJdbcType.base[Value, Int](_.id, this.apply) 
} 

這也應光滑1.0工作(我沒有測試過):

abstract class DBEnum extends Enumeration { 
    implicit val enumMapper = MappedTypeMapper.base[Value, Int](_.id, this.apply) 
} 

現在,所有你需要爲你的枚舉只是從DBEnum繼承,它應該減少很多鍋爐板。

如果要使用字符串值而不是Ints,請相應地編輯代碼。

+0

tks @prakhunov,我編輯了你的答案,添加了我改爲使用字符串的代碼。 – Longo

+5

請注意,由於https://github.com/slick/slick/issues/540的原因,此代碼似乎與當前版本無關。你會得到錯誤'JdbcProfile has typeInfo for type scala.slick.driver.JdbcTypesComponent $ MappedJdbcType ...'爲了解決這個問題,把導入改爲你特定的db驅動,而不是'jdbc'。例如'import scala.slick.driver.HsqldbDriver.simple._'和'import scala.slick.driver.HsqldbDriver。MappedJdbcType' – Luciano

+0

你是對的我注意到當我將我的項目更新到最終的slick 2.0版本時。我們最初有計劃支持多個數據庫,現在可能不可能。 – prakhunov

4

也許你可以爲你的枚舉類型創建一個TypeMapper :

​​

這樣,當您從數據庫加載數據時,這種方式將轉換回您的枚舉。如果你堅持存儲你的價值觀作爲數據庫的字符,你只需要創建一個映射到一個字符映射器和定義

+0

我實現了一個映射器,但是導致了錯誤: – Longo

2

一些幫助我找到了解決辦法之後,枚舉:

object LoginStatus extends Enumeration { 

    def enum2StringMapper(enum: Enumeration) = MappedTypeMapper.base[enum.Value, String](
    b => b.toString, 
    i => enum.withName(i)) 

    implicit val LoginStatusMapper = enum2StringMapper(LoginStatus) 

    type LoginStatus = Value 
    val Active = Value("A") 
    val Inactive = Value("I") 
} 

和表映射:

import constants.LoginStatus._ 
... 
    def stLogin = column[LoginStatus]("stlogin", O.NotNull, O.DBType("character(1)"))