You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让ScalikeJDBC自动生成的仓库使用外部自定义数据类型?

解决方案:让ScalikeJDBC Repository使用独立的Model Case类

我来帮你解决这个问题——其实核心就是让ScalikeJDBC的Repository代码依赖你独立定义的Model类,而不是用生成工具默认在Repository文件里创建的内部类。下面是一步步的实现方案:

1. 先定义独立的Model Case类

models包下创建你的数据类型定义,这是整个应用都会复用的核心模型:

// models/Profile.scala
package models

case class Profile(profileId: Int, name: String)

2. 调整ScalikeJDBC生成的Repository代码

默认情况下scalikejdbcGen会在Repository文件里同时生成Case类和伴生对象,我们需要修改生成的代码,让它导入外部的models.Profile,而不是使用内部定义的版本。

修改后的repositories/ProfileRepository.scala应该是这样的:

package repositories

import scalikejdbc._
import models.Profile // 关键:导入外部的Profile模型

object ProfileRepository extends SQLSyntaxSupport[Profile] {
  override val autoSession = AutoSession
  override val tableName = "profile"
  override val columns = Seq("profile_id", "name")

  // 定义语法别名,用于SQL查询
  val p = syntax("p")

  // 从ResultSet映射到外部的Profile实例
  def apply(p: SyntaxProvider[Profile])(rs: WrappedResultSet): Profile = apply(p.resultName)(rs)
  def apply(p: ResultName[Profile])(rs: WrappedResultSet): Profile = Profile(
    profileId = rs.get(p.profileId),
    name = rs.get(p.name)
  )

  // 示例查询方法,返回外部Profile类型的集合/单个实例
  def count(): Long = DB readOnly { implicit session =>
    withSQL(select(sqls.count).from(ProfileRepository as p))
      .map(rs => rs.long(1))
      .single()
      .apply()
      .get
  }

  // 新增一个查询所有Profile的方法,返回Seq[Profile]
  def findAll(): Seq[Profile] = DB readOnly { implicit session =>
    withSQL(select.from(ProfileRepository as p))
      .map(apply(p))
      .list()
      .apply()
  }
}

关键修改点:

  • 导入外部Model:添加import models.Profile,确保Repository使用的是你独立定义的Case类
  • 移除内部Model定义:删掉生成工具自动在Repository里创建的case class Profile(...)
  • 调整映射逻辑apply方法直接实例化models.Profile,而不是内部类
  • 语法别名的正确引用val p = syntax("p")是基于SQLSyntaxSupport[Profile]的泛型自动生成的,只要泛型是外部的Profile,就不会有别名语法错误

3. 让scalikejdbcGen直接生成符合要求的代码(可选)

如果你不想每次生成后手动修改,可以通过scalikejdbcGen的参数指定Model的包名,这样工具会直接生成依赖外部Model的Repository代码。

比如使用以下SBT命令:

sbt "scalikejdbcGen profile models.Profile"

这个命令会告诉生成工具:

  • 数据库表是profile
  • 对应的Model类是models.Profile
  • 生成的Repository会自动导入这个外部Model,不会在内部重复定义

4. 分层架构的适配

现在你的Repository只负责数据库交互,所有返回类型都是models.Profile或其集合(比如Seq[Profile])。Service层可以直接调用Repository的方法获取Model实例,再进行业务逻辑处理;Controller层则接收Service返回的Model,转换成API响应数据。这样整个分层清晰,Model类型可以在应用的各个层复用,完全符合你期望的controller->service->repository架构。

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

火山引擎 最新活动