Slick 3.3.3无法解析MySQL Datetime类型问题求助
解决Slick 3.3.3解析MySQL datetime格式报错问题
问题根源
Slick 3.3.3对Java 8时间类型(LocalDateTime/OffsetDateTime)的默认映射,采用JDK原生的ISO8601格式解析(如2023-09-20T21:20:21),但MySQL的datetime类型默认存储格式是yyyy-MM-dd HH:mm:ss(空格分隔),两者格式不匹配导致解析报错:Text '2023-09-20 21:20:21' could not be parsed at index 10。
正确解决方案
1. 定义适配MySQL的日期时间格式化器
先创建对应格式的DateTimeFormatter:
import java.time.format.DateTimeFormatter import java.time.{LocalDateTime, OffsetDateTime, ZoneOffset} // 匹配MySQL datetime默认格式的解析/格式化工具 private val mysqlDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
2. 编写自定义列类型映射器
无需单独为Option[T]编写映射,Slick会自动基于非可选类型的映射生成可选版本的隐式转换。只需先定义基础类型的映射:
import slick.jdbc.MySQLProfile.api._ // LocalDateTime 与数据库String的双向映射 implicit val localDateTimeMapping: BaseColumnType[LocalDateTime] = MappedColumnType.base[LocalDateTime, String]( dt => dt.format(mysqlDateTimeFormatter), str => LocalDateTime.parse(str, mysqlDateTimeFormatter) ) // 若使用OffsetDateTime,需补充时区处理(MySQL datetime不带时区,建议统一转成UTC或服务器时区) implicit val offsetDateTimeMapping: BaseColumnType[OffsetDateTime] = MappedColumnType.base[OffsetDateTime, String]( dt => dt.format(mysqlDateTimeFormatter), str => LocalDateTime.parse(str, mysqlDateTimeFormatter).atOffset(ZoneOffset.UTC) // 根据实际场景调整时区 )
3. 配置表列定义
确保上述隐式映射在表定义的作用域内(同包、全局导入或伴生对象均可),直接定义列即可:
class YourTable(tag: Tag) extends Table[YourRow](tag, "your_table") { // 隐式映射已在作用域,无需手动传入 def startDate = column[Option[LocalDateTime]]("start_date", O.SqlType("datetime")) // 其他列定义... override def * = (startDate, ...) <> (YourRow.tupled, YourRow.unapply) }
常见坑点排查
- 类型不匹配:你之前尝试用
OffsetDateTime的映射处理LocalDateTime类型,导致映射未生效,必须保证映射泛型与列类型严格一致。 - 隐式作用域:如果隐式映射不在表定义的作用域内,Slick会 fallback 到默认映射,需确保映射能被编译器找到(比如放在伴生对象或全局隐式对象中)。
- 时区处理:MySQL的
datetime不带时区信息,使用OffsetDateTime时必须明确指定时区,避免解析时出现偏移错误。
内容的提问来源于stack exchange,提问作者Mr. MonoChrome
相关产品推荐
相关产品推荐

