【问题标题】:Scala Option[java.util.Date] cannot be cast to Option[java.sql.Date]Scala Option[java.util.Date] 不能转换为 Option[java.sql.Date]
【发布时间】:2013-06-21 17:58:21
【问题描述】:

我有一个如下所示的 Play 表单:

val form = Form( tuple( 
        /* 5 more fields */ 
        "dueDate" -> optional(date) 
)  )

我正在尝试将"dueDate" 插入到 Slick 中的对象中。

newAuditForm.bindFromRequest.fold(
    errors => BadRequest(views.html.error(form)),
    success => {
        Database.forDataSource(DB.getDataSource()) withSession {
            Things.forInsert.insert Thing(
                (success._6).asInstanceOf[Option[java.sql.Date]] 
            )
        }
    }
)

其中 Slick 仅处理 java.sql.Date,而 Play 仅处理 Form 对象中的 java.util.Date (?)。

使用asInstanceOf 返回:

     ClassCastException: java.util.Date cannot be cast to java.sql.Date

必须有一种方法让我为这个演员阵容编写规则...... 我需要写一个new pattern matching rule吗?

【问题讨论】:

    标签: scala casting playframework slick


    【解决方案1】:

    您不能将java.util.Date 转换为java.sql.Date,因为java.sql.Date 是一个子类。您可以做的是创建java.sql.Date 的新实例:

    val x = new java.util.Date()
    val y = new java.sql.Date(x.getTime())
    

    如果你认为它有用,你可以定义一个隐式转换:

    implicit def date2sqlDate(d: java.util.Date) = new java.sql.Date(d.getTime())
    

    但是,这不会在选项内部进行转换(转换也不会起作用,因为它不是转换而是转换)。

    您可以:

    val x: Option[java.util.Date]
    x.map(_: java.sql.Date) // using implicit conversion
    

    或者直接写出来:

    x.map(d => new java.sql.Date(d.getTime()))
    

    如果您经常需要转换,您可以考虑编写从Option[java.util.Date]Option[java.sql.Date] 的隐式转换。

    【讨论】:

    • 如果您已经在使用类型归属进行显式映射,我认为不值得引入隐式转换。
    • 感谢您的快速回复。我很欣赏你如何花额外的时间来解释发生了什么。我是否正确理解显式转换更像是一次性的事情,而隐式转换相当于编写新的类型转换规则?
    • @MeredithLeu 欢迎。隐式转换是用于转换的特殊函数,而不是类型转换:如果你有一个值 x: A 并且你需要一个 B 并且你在范围内有一个隐式函数 f: A => B,编译器会将 x 替换为 @987654336 @。所以在字节码级别上,它们只不过是函数调用。显式转换是自己编写完全相同的函数调用。见:stackoverflow.com/questions/2861501/…
    • @om-nom-nom 是的,我同意。我添加了更多以显示一般机制(并防止与盒装类型混淆)。如果其他地方也需要转换,它可能会很有用。
    【解决方案2】:

    尝试将Option[java.util.Date] 映射到Option[java.sql.Date],如下所示:

    (success._6).map(d => new java.sql.Date(d.getTime))
    

    还有一点建议,您可能希望将其实际映射到java.sql.Timestamp,这样在将其写入数据库时​​就不会丢失任何时间精度,我相信java.sql.Date 就是这种情况。所以代码是:

    (success._6).map(d => new java.sql.Timestamp(d.getTime))
    

    【讨论】:

    • 谢谢!我知道使用 java.sql.Timestamp 而不是 Date。我在架构的其他地方使用了 Option[Timestamp],但是对于这个特定的对象,一天的粒度很好 ^.^
    猜你喜欢
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 2011-08-29
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多