Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

scala - Customer Type Mapper for Slick SQL

I've found this example from slick testing:
https://github.com/slick/slick/blob/master/slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/MapperTest.scala

sealed trait Bool
case object True extends Bool
case object False extends Bool

implicit val boolTypeMapper = MappedColumnType.base[Bool, String](
  { b =>
    assertNotNull(b)
    if(b == True) "y" else "n"
  }, { i =>
    assertNotNull(i)
    if(i == "y") True else False
  }
)

But I'm trying to create a TypeMapper for org.joda.time.DateTime to/from java.sql.Timestamp - but without much success. The Bool example is very particular and I'm having trouble adapting it. Joda Time is super common - so any help would be much appreciated.

To be clear, I'm using interpolated sql"""select colA,colB from tableA where id = ${id}""" and such. When doing a select the system works well by using jodaDate types in the implicit GetResult converter.

However, for inserts there doesn't seem to be a way to do an implicit conversion or it is ignoring the code provided below in Answer #1 - same error as before: could not find implicit value for parameter pconv: scala.slick.jdbc.SetParameter[(Option[Int], String, String, Option[org.joda.time.DateTime])]

I'm not using the Lifted style Slick configuration with the annotated Table objects perhaps that is why it is not finding/using the TypeMapper

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I use the following in my code, which might also work for you:

import java.sql.Timestamp
import org.joda.time.DateTime
import org.joda.time.DateTimeZone.UTC
import scala.slick.lifted.MappedTypeMapper.base
import scala.slick.lifted.TypeMapper

implicit val DateTimeMapper: TypeMapper[DateTime] = 
  base[DateTime, Timestamp](
    d => new Timestamp(d millis), 
    t => new DateTime(t getTime, UTC))

Edit (after your edit =^.~= ): (a bit late but I hope it still helps)

Ah, OK, since you're not using lifted embedding, you'll have to define different implicit values (as indicated by the error message from the compiler). Something like the following should work (though I haven't tried myself):

implicit val SetDateTime: SetParameter[DateTime] = new SetParameter { 
  def apply(d: DateTime, p: PositionedParameters): Unit =
    p setTimestamp (new Timestamp(d millis))
}

For the other way round (retrieving the results of the SELECT), it looks like you'd need to define a GetResult:

implicit val GetDateTime: GetResult[DateTime] = new GetResult {
  def apply(r: PositionedResult) = new DateTime(r.nextTimestamp getTime, UTC))
}

So, basically this is just the same as with the lifted embedding, just encoded with different types.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...