Slick 3中LocalDateTime自定义解析器适配MySQL问题求助
解决Slick 3与MySQL 8中LocalDateTime映射的格式解析问题
核心问题分析
- Slick默认的
LocalDateTime映射会将其序列化为VARCHAR类型,与MySQL的TIMESTAMP/DATETIME返回的yyyy-MM-dd HH:mm:ss格式不兼容,导致LocalDateTime.parse因格式不符抛出解析异常。 - 自定义映射仅处理非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
相关产品推荐
相关产品推荐

