Slick 3.2 Schema投影含日期字段时编译错误求助
解决Slick 3.2 Oracle Schema编译错误及日期查询问题
嗨,我来帮你搞定这个Slick的编译问题,顺便把日期查询的细节也捋清楚~
编译错误的核心原因
你遇到的「Expression of type Rep[Long] doesn't conform to expected type Long」错误,根源是表的投影方法def *的返回类型声明错了。在Slick里,表的投影需要返回ProvenShape[T]类型(这是Slick用来映射数据库行和Scala类型的特殊类型),而不是直接写普通的Scala元组(Long, String, Date)。当你声明了错误的返回类型后,编译器会尝试把Rep[Long]这类数据库字段引用转换成普通的Scala值,自然就不匹配了。
修正后的Schema代码
import slick.jdbc.OracleProfile.api._ import java.sql.Date class User(tag: Tag) extends Table[(Long, String, Date)](tag, "USR") { def usr_id: Rep[Long] = column[Long]("USR_ID", O.PrimaryKey) def usr_subj_txt: Rep[String] = column[String]("USR_SUBJ_TXT") def usr_arch_dt: Rep[Date] = column[Date]("USR_ARCH_DT") // 要么去掉返回类型让编译器自动推断,要么显式声明为ProvenShape[(Long, String, Date)] def * = (usr_id, usr_subj_txt, usr_arch_dt) }
这里我做了两个小调整:
- 移除了
def *的返回类型声明,让Slick的编译器自动推断出正确的ProvenShape类型,这是最常用的写法 - 调整了字段的顺序,让投影的顺序和表类的泛型
(Long, String, Date)对应(虽然顺序不影响编译,但保持一致更清晰易读)
日期范围查询的注意事项
你的查询代码里还有个小坑:Calendar.getInstance().getTime返回的是java.util.Date,而你的列类型是java.sql.Date,两者不能直接比较。这里有两种解决方案:
方案1:把java.util.Date转换成java.sql.Date
如果坚持用java.sql.Date,可以手动转换后再查询:
import java.util.Calendar import java.sql.Date // 获取当前时间并转换成java.sql.Date val currentSqlDate = new Date(Calendar.getInstance().getTime.getTime) // 注意要先创建TableQuery实例,你代码里的ntfns应该是TableQuery[User] val filterQuery: Query[User, (Long, String, Date), Seq] = TableQuery[User].filter(_.usr_arch_dt > currentSqlDate)
方案2:改用Java 8+的LocalDate(更推荐)
java.sql.Date和java.util.Date的设计都比较老旧,Slick对Java 8的日期API(java.time.LocalDate)支持更好,代码也更简洁:
首先修改表的字段类型:
import slick.jdbc.OracleProfile.api._ import java.time.LocalDate class User(tag: Tag) extends Table[(Long, String, LocalDate)](tag, "USR") { def usr_id: Rep[Long] = column[Long]("USR_ID", O.PrimaryKey) def usr_subj_txt: Rep[String] = column[String]("USR_SUBJ_TXT") def usr_arch_dt: Rep[LocalDate] = column[LocalDate]("USR_ARCH_DT") def * = (usr_id, usr_subj_txt, usr_arch_dt) }
然后查询的时候直接用LocalDate.now():
import java.time.LocalDate val filterQuery: Query[User, (Long, String, LocalDate), Seq] = TableQuery[User].filter(_.usr_arch_dt > LocalDate.now())
这样既避免了日期类型转换的麻烦,代码也更易维护。
内容的提问来源于stack exchange,提问作者algae514
相关产品推荐
相关产品推荐

