You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Slick 3中LocalDateTime自定义解析器适配MySQL问题求助

解决Slick 3与MySQL 8中LocalDateTime映射的格式解析问题

核心问题分析

  1. Slick默认的LocalDateTime映射会将其序列化为VARCHAR类型,与MySQL的TIMESTAMP/DATETIME返回的yyyy-MM-dd HH:mm:ss格式不兼容,导致LocalDateTime.parse因格式不符抛出解析异常。
  2. 自定义映射仅处理非Option类型时,显式传递映射器给Option[LocalDateTime]列会出现类型不匹配错误,因为Slick需要的是TypedType[Option[LocalDateTime]]而非BaseColumnType[LocalDateTime]。

最优解决方案:直接映射JDBC Timestamp(推荐)

绕开字符串解析环节,直接在LocalDateTime与JDBC原生Timestamp之间转换,利用MySQL驱动自动处理数据库类型与JDBC类型的适配,彻底避免格式问题。

代码实现

import java.sql.Timestamp
import java.time.LocalDateTime
import slick.jdbc.MySQLProfile.api._

// 定义作用域内的隐式映射
implicit val localDateTimeColumnType: BaseColumnType[LocalDateTime] = MappedJdbcType.base[LocalDateTime, Timestamp](
  // LocalDateTime 转 JDBC Timestamp
  localDateTime => Timestamp.valueOf(localDateTime),
  // JDBC Timestamp 转 LocalDateTime
  timestamp => timestamp.toLocalDateTime
)

模型使用方式

无需显式传递映射器,Slick会自动推导Option[LocalDateTime]的类型适配:

class Users(tag: Tag) extends Table[User](tag, "users") {
  def uuid           = column[UUID]("uuid", O.PrimaryKey)
  def name           = column[String]("name")
  def email          = column[String]("email")
  def lastSignedInAt = column[Option[LocalDateTime]]("last_signed_in_at")
  def createdAt      = column[LocalDateTime]("created_at")

  override def * = (uuid, name, email, lastSignedInAt, createdAt) <> (User.tupled, User.unapply)
}

备选方案:修复字符串格式映射(不推荐)

若因特殊需求必须使用字符串中间类型,需确保隐式映射作用域优先于Slick默认映射,且无需显式传递给Option列:

代码实现

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import slick.jdbc.MySQLProfile.api._

// 定义MySQL日期格式化器与隐式映射
private val mysqlDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
implicit val localDateTimeMapper: BaseColumnType[LocalDateTime] = MappedJdbcType.base[LocalDateTime, String](
  ldt => ldt.format(mysqlDateTimeFormatter),
  str => LocalDateTime.parse(str, mysqlDateTimeFormatter)
)

模型使用方式

移除Option列后的显式映射器参数:

class Users(tag: Tag) extends Table[User](tag, "users") {
  def uuid           = column[UUID]("uuid", O.PrimaryKey)
  def name           = column[String]("name")
  def email          = column[String]("email")
  def lastSignedInAt = column[Option[LocalDateTime]]("last_signed_in_at")
  def createdAt      = column[LocalDateTime]("created_at")

  override def * = (uuid, name, email, lastSignedInAt, createdAt) <> (User.tupled, User.unapply)
}

关键注意事项

  • 确保自定义隐式映射的作用域优先于Slick默认的LocalDateTime映射(例如将映射定义在模型伴生对象或DAO类中),避免全局冲突。
  • 优先使用JDBC Timestamp映射方案,既避免格式解析错误,又提升数据读写效率。

内容的提问来源于stack exchange,提问作者Christoffer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 21:15:33