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

使用Crystal与Jennifer搭建API遇SQLite抽象方法未实现错误

问题:Crystal + Jennifer + SQLite3 编译错误:未实现抽象方法current_column_name

运行crystal run时出现以下编译错误:

In lib/sqlite3/src/sqlite3/result_set.cr:1:1

1 | class SQLite3::ResultSet < DB::ResultSet
^
Error: abstract `def DB::ResultSet#current_column_name()` must be implemented by SQLite3::ResultSet

尝试过调整sqlite3和Jennifer的版本,但问题未解决。以下是相关配置和代码:

一、shard.yml 配置

name: travel_api
version: 0.1.0

description: "API for travel."

dependencies:
  kemal:
    github: kemalcr/kemal
  jennifer:
    github: imdrasil/jennifer.cr
    version: "0.12.0"
  sqlite3:
    github: crystal-lang/crystal-sqlite3
  jennifer_sqlite3_adapter:
    github: imdrasil/jennifer_sqlite3_adapter

targets:
  travel-api:
    main: src/main.cr

license: MIT

二、模型文件 model.cr

# model.cr
require "jennifer"

class TravelPlan < Jennifer::Model::Base
  mapping(
    id: {type: Int32, primary: true},
    travel_stops: Array(Int32),
    created_at: {type: Time, null: true},
    updated_at: {type: Time, null: true}
  )

  def initialize(@travel_stops : Array(Int32))
  end
end

三、控制器文件 controller.cr

# controller.cr
require "./model"

module TravelApiController
  extend self

  def create_travel_plan(ctx : HTTP::Server::Context)
    travel_stops = JSON.parse(ctx.request.body.to_s, to: Array(Int32))
    travel_plan = TravelPlan.new(travel_stops: travel_stops)
    
    handle_response(ctx, travel_plan.save) do
      ctx.response.status = 201
      ctx.response.write(travel_plan.to_json)
    end
  end

  def get_all_travel_plans(ctx : HTTP::Server::Context)
    travel_plans = TravelPlan.all
    handle_response(ctx, true) do
      ctx.response.write(travel_plans.to_json)
    end
  end

  def get_travel_plan(ctx : HTTP::Server::Context)
    id = ctx.params.url["id"].to_i
    travel_plan = TravelPlan.find(id)

    handle_not_found(ctx, travel_plan) do
      ctx.response.status = 200
      ctx.response.write(travel_plan.to_json)
    end
  end

  def update_travel_plan(ctx : HTTP::Server::Context)
    id = ctx.params.url["id"].to_i
    travel_stops = JSON.parse(ctx.request.body.to_s, to: Array(Int32))
    travel_plan = TravelPlan.find(id)

    handle_not_found(ctx, travel_plan) do
      travel_plan.travel_stops = travel_stops

      handle_response(ctx, travel_plan.save) do
        ctx.response.status = 200
        ctx.response.write(travel_plan.to_json)
      end
    end
  end

  def delete_travel_plan(ctx : HTTP::Server::Context)
    id = ctx.params.url["id"].to_i
    travel_plan = TravelPlan.find(id)

    handle_not_found(ctx, travel_plan) do
      travel_plan.delete
      ctx.response.status = 204
    end
  end

  private def handle_response(ctx : HTTP::Server::Context, success : Bool)
    if success
      yield
    else
      ctx.response.status = 500
      ctx.response.write("Erro ao salvar o plano de viagem.")
    end
  end

  private def handle_not_found(ctx : HTTP::Server::Context, entity)
    if entity
      yield
    else
      ctx.response.status = 404
      ctx.response.write("Plano de viagem não encontrado.")
    end
  end
end

四、主文件 main.cr

# main.cr
require "kemal"
require "sqlite3"
require "./model"
require "./controller"

# Configurar conexão com o banco de dados
DB.open "sqlite3://./db/travel_api.db" do |db|
  # Configurar Jennifer para usar a conexão SQLite3
  Jennifer::DB.connection = db
end

# Configurar Kemal
Kemal.config do |config|
  config.host = "0.0.0.0"
  config.port = 3000
end

Kemal.run do
  # Configuração do Kemal

  post "/travel_plans", TravelApiController.create_travel_plan
  get "/travel_plans", TravelApiController.get_all_travel_plans
  get "/travel_plans/:id", TravelApiController.get_travel_plan
  put "/travel_plans/:id", TravelApiController.update_travel_plan
  delete "/travel_plans/:id", TravelApiController.delete_travel_plan
end

解决方案

这个错误源于crystal-sqlite3 版本与 Jennifer 版本不兼容:Jennifer 0.12.0 依赖的 DB 接口定义了current_column_name抽象方法,但部分版本的 crystal-sqlite3 未实现该方法,或版本迭代后接口不匹配。

步骤1:锁定兼容的依赖版本

修改shard.yml,指定与 Jennifer 0.12.0 匹配的依赖版本:

dependencies:
  kemal:
    github: kemalcr/kemal
  jennifer:
    github: imdrasil/jennifer.cr
    version: "0.12.0"
  sqlite3:
    github: crystal-lang/crystal-sqlite3
    version: "~> 0.18.0"  # 与 Jennifer 0.12.0 兼容的稳定版本
  jennifer_sqlite3_adapter:
    github: imdrasil/jennifer_sqlite3_adapter
    version: "~> 0.12.0"  # 与 Jennifer 主版本保持一致

步骤2:更新依赖并重新构建

执行以下命令更新依赖:

shards update
shards install

重新运行项目:

crystal run src/main.cr

额外优化提示

原代码中DB.open块执行完毕后会关闭数据库连接,而 Kemal 运行在块外部会导致后续操作无可用连接。建议修改连接初始化方式,确保连接持久化:

# 修改 main.cr 中的数据库连接部分
Jennifer::DB.configure do |conf|
  conf.adapter = "sqlite3"
  conf.database = "./db/travel_api.db"
end

Kemal.run do
  # 路由配置...
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:34:52