使用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
相关产品推荐
相关产品推荐

