如何用Prisma ORM建立一个Golang API

1,101 阅读12分钟

用Prisma ORM设置Golang API

Object-Relational Mapper(ORM)是一种在面向对象的程序中存储、检索、更新和删除数据库的技术。ORM简化了我们在面向对象范式中查询和修改数据的方式。

ORM对数据进行建模,而不需要编写和数据库查询。它利用模型类和数据库之间的数据层来管理两者之间的转换。这使得与数据库打交道变得更加容易。与其使用复杂的SQL语句,我们不如通过Prisma这样的ORM来使用面向对象。

Prisma是一个现代的ORM,允许程序员编写类型安全的数据库模式。当然,一切都需要很好的设置,以定义该数据库的样子。在这种情况下,Prisma将开发人员从编写数据库查询中抽象出来,从而确保我们编写安全的数据库访问模式。

Prisma ORM提供Prisma-客户端来设置和编写数据库、数据模型、数据验证以及描述不同数据字段之间的关系。然后,该客户端能够生成查询并连接到所选择的数据库。

为什么Prisma是首选

  • Prisma允许帮助编写类型安全的数据库模型。它为.prisma 文件增加了语法高亮、格式化、自动完成、跳到定义和提示。这有助于你通过提供可靠和完全类型安全的API来避免错误,这些API专门为你的Prisma代码而建。

  • Prisma提供数据库模式迁移。与GitLab等工具一样,Prisma在引入新的变化时都会生成新的版本。这样,每当你当前的模式不能工作时,你总是可以回滚到以前的稳定版本。

  • Prisma提供自省功能。如果你有一个已经存在的数据库,你不必从头开始创建Prisma模型。它还允许你将数据反省到Prisma模式中。例如,如果你在数据库表内已经有一个预定义的模式,你可以反省它,并把它放到Prisma模式中。

  • Prisma允许你将你写在.prisma 文件中的数据模型可视化。它为你提供了一个叫做Prisma studio的GUI,使你能够通过GUI来实现数据的可视化,就像典型的datasets GUI一样。然后,你可以继续插入、创建或更新你的数据。

前提条件

  • 安装有最新版本的Node.js。
  • 在你的电脑上安装Golang。
  • 在你的电脑上安装Postman以测试API端点。
  • 有一些Golang的工作知识。
  • 对Prisma和Prisma的工作原理有基本了解。
  • 在你的电脑上安装Visual Studio Code
  • Prisma扩展应该安装在你的Visual Studio Code中。

设置Go

首先,我们需要设置一个Go程序,并安装库,以使Prisma随时可用。因此,继续创建一个项目文件夹。将其称为prisma-and-go 。然后通过运行以下命令在这个文件夹中初始化你的Go应用程序。

go mod init go-prisma

这个命令将初始化Go应用程序,并创建一个go.mod 文件,用来存储我们将使用的任何包和模块。它还将创建一个本地模块,go-prisma ,我们将用它来导入我们将要创建的任何本地模块。

现在安装软件包,用Prisma设置Go Rest API。我们将使用以下包。

  1. Prisma Client Go- 一个Prisma生态系统库,提供声明式数据建模、数据访问、可视化数据管理数据库工具和模式迁移。Prisma Client Go是一个查询生成器,可以自动生成查询,允许类型安全的数据库访问和减少模板代码。

要安装这个软件包,请运行。

go get github.com/prisma/prisma-client-go
  1. Echo- 一个高性能和简约的Go框架,用于创建强大和可扩展的Go RESTful APIs。它是一个高效的HTTP路由器,具有最小的动态内存分配和智能路由优先级。此外,它还提高了速度,以获得更好的用户体验。

要安装这个包,请运行。

go get github.com/labstack/echo/v4    

添加v4 ,将安装Echo第4版。

我们还将使用Echo中间件作为一个日志中间件。通过运行以下命令来安装它。

go get github.com/labstack/echo/v4/middleware

设置Prisma

为了将Prisma与Go设置在一起,我们将使用Node.js NPX命令来帮助我们创建Prima模型,将其推送到数据库表示,并设置Go客户端生成。

首先,运行npx prisma init ,利用Prisma客户端来生成Prisma所需的文件。它将创建一个prisma 文件夹,里面有schema.prisma,.env 文件。schema.prisma 文件有以下几个块。

  • generator 指定要生成的资产,同时产生产生实际查询的数据库类型。

  • datasource 包含两个主要参数: 和 。 指定了要使用的数据库。, , , , 和 是例子。provider url provider sqlserver sqlite mysql postgresql mongodb

参数url 指定了数据库服务器的连接字符串。此外,你的DATABASE URL 可以在.env 文件中指定。DATABASE URL 是与托管你所选择的数据库的服务器的连接字符串。

这些块是为JavaScript生成的。由于我们使用的是Go将对它们进行如下修改。我们将使用SQLite(基于文件的SQL数据库)。这就是你如何设置你的datasourcegenerator

datasource db {
  provider = "sqlite"
  url = "file:dev.db"
}

generator db {
  provider = "go run github.com/prisma/prisma-client-go"
}

创建一个Prisma模型

模型代表你的应用程序字段的实体。一个模型对应于一个数据库表。让我们开始在SQLite数据库中建模和表示实体。在generator 块下面,添加以下to-dos模型。

model Todos {
  id String @id @default(uuid())
  complete Boolean @default(false)
  name String
  updatedAt DateTime @updatedAt
  createdAt DateTime @default(now())
}

这个模型将创建一个有五个字段的Todos 数据库表。使用Prisma,每个字段都用名称、数据类型和你想添加到每个字段的值来表示。因此,举例来说,你总是要在SQL表中设置一个唯一的字段。

在这种情况下,我们有一个id,它将使用uuid() ,自动生成。而由于id将总是被添加到每个待办事项中,我们设置@default ,表示这个值将总是以默认的id值创建。

complete 取一个布尔值,要么是真,要么是假。默认情况下,当创建一个新的待办事项时,将创建一个假值。每个字段都有一个数据类型,指定需要的数据。 ,添加一个默认的数据值,即当前时间。createdAt

我们需要执行上述模型以反映SQLite数据库中的Prisma模式。要做到这一点,请运行。

npx Prisma db push

这个命令将在schema 目录内创建一个db 文件夹,以设置配置来加载数据到SQLite数据库。因此,将创建一个dev.db ,以反映数据库表中的设定模式,如下图所示。

sqlite-table

这个创建的db ,将是这个数据库的本地模块配置。因此,我们需要运行以下命令来设置go.sum 条目内的模块。

go get go-prisma/prisma/db

现在改变datasource url ,以反映prisma 的模块。

datasource db {
  provider = "sqlite"
  url = "file:/prisma/dev.db"
}

使用命令npx prisma generate 。这个命令将执行generatorprovider 来设置prisma-client-go

用Go和Echo建立RESTful API

我们设置了一个to-dos模式,并将其导出到一个典型的数据库。然后,让我们创建一个简单的Restful API,演示如何将加载的Prisma与Go应用程序一起使用。

使用Echo设置处理程序

你需要使用不同的HTTP方法进行不同的操作来设置API。最常见的HTTP方法是GETPOSTPUTDELETE

这些HTTP方法有特定的含义。通常情况下,你使用正确的方法进行适当的操作,如获取、添加、更新和删除数据。所以,让我们编写这些编写方法,并创建一个REST。

在你的项目目录下,创建一个handler 文件夹,在该文件夹内,创建一个to-dos.go 文件,并按照以下步骤操作。

第1步:创建一个包并导入模块

package handler
import (
  "context"
  "go-prisma/prisma/db"
  "net/http"
  "github.com/labstack/echo/v4"
)

这个代码块将创建一个包handler ,我们将在本地模块系统中使用。我们也会导入我们需要设置处理程序的库。

这个导入包括Go的核心模块,如contextnet/http 。同时,导入生成的Prism模块以访问Prisma模式结构。此外,为了创建不同的HTTP方法,导入已安装的Echo包。

第2步:添加结构

type TodosHandler struct {
  client *db.PrismaClient
}

// TODO structure
type TodosResponse struct {
  db.TodosModel
}

TodosHandler 将建立一个 引擎,创建引擎盖下发生的事情的抽象。这样查询引擎可以生成并发送请求到 。PrismaClient PrismaClient

TodosResponse 创建一个代表 模型的 ,以及一个用于访问字段和方法的包装器。json:"Todos" TodosModel

第3步:创建一个函数来执行 "TodosHandler"。

func NewTodoHandler(client *db.PrismaClient) *TodosHandler {
  return &TodosHandler{client}
}

相对于模型方法,Prisma提供了Prisma相关的方法。所以现在我们可以开始实现这些Prisma相关的方法,以获得相关的响应。

第4步:创建一个获取函数

func (h *TodosHandler) ShowAll(c echo.Context) error {
  todos, err := h.client.Todos.FindMany().Exec(context.Background())
  if err != nil {
    return c.String(http.StatusInternalServerError, "error getting Todos")
  }

  return c.JSON(http.StatusOK, todos)
}

正如我们所说,Prisma提供了Prisma相关的方法。我们将使用FindMany() Prisma方法来获取这些to-dos。PrismaClient 引擎将创建一个抽象的引擎下发生的事情,然后返回可用的to-dos列表,如果这个执行环境失败,则返回一个错误信息。

第5步:创建获取单个待办事项的函数

func (h *TodosHandler) Show(c echo.Context) error {
  todo, err := h.client.Todos.FindUnique(db.Todos.ID.Equals(c.Param("id"))).Exec(context.Background())
  if err != nil {
    return c.String(http.StatusInternalServerError, err.Error())
  }
  return c.JSON(http.StatusOK, todo)
}

要获得一个单一的待办事项,使用FindUnique() ,它将执行待办事项的id字段参数,并返回与提供的id参数相等的待办事项值。

第6步:创建一个添加新待办事项的函数

func (h *TodosHandler) Create(c echo.Context) error {
  var todo db.TodosModel
  if err := c.Bind(&todo); err != nil {
    return c.String(http.StatusInternalServerError, err.Error())
  }

  created, err := h.client.Todos.CreateOne(
    db.Todos.Name.Set(todo.Name),
  ).Exec(context.Background())
  if err != nil {
    return c.String(http.StatusInternalServerError, err.Error())
  }

  return c.JSON(http.StatusOK, created)
}

要使用PrismaClient 创建一个新条目,请使用CreateOne() 函数。PrismaClient 引擎将插入一个新条目,然后返回新添加的待办事项的值。

尝试创建其他处理程序来执行UPDATE和DELETE等方法。

使用Echo设置路由

为了执行上述所有的处理函数,我们需要用相应的HTTP方法设置路由。例如,为了获取一个待办事项,我们需要设置一个路由,执行一个GET请求,返回可用的待办事项的列表。

在你的项目目录下创建一个router 文件夹,在该文件夹内,创建一个to-dos.go 文件,并按照以下步骤操作。

第1步:创建一个包并导入模块

package router
import (
  "github.com/labstack/echo/v4"
  "go-prisma/handler"
  "go-prisma/prisma/db"
)

这个代码块将创建一个包router ,我们将在本地模块系统中使用。我们还导入库来设置一个router 。这个导入包括生成的Prisma模块来访问Prisma模式结构,以及handler 模块来访问处理函数。我们还需要Echo包来创建不同的HTTP方法。

第2步:创建一个路由器函数

func TodoRouter(e *echo.Echo, dbClient *db.PrismaClient) {
  todoHandler := handler.NewTodoHandler(dbClient)
  g := e.Group("/todos/")
  g.GET("", todoHandler.ShowAll)
  g.GET(":id", todoHandler.Show)
  g.POST("", todoHandler.Create)
}

在这里,我们只是设置一个基本的路由,它将根据被执行的方法来使用。同时,指定一个需要参数的端点,如id值。

设置服务器

为了设置我们到目前为止所建立的一切,我们需要设置一个本地服务器,我们将用它来访问API。我们使用Gomain() 函数,在Go应用程序运行时执行。下面是我们要做的事情。

第3步:创建一个包并导入模块

package main

import (
  "github.com/labstack/echo/v4"
  "github.com/labstack/echo/v4/middleware"
  "go-prisma/prisma/db"
  "go-prisma/router"
  "log"
)

上面的代码片断将创建Gomain 模块。我们还导入我们所创建的本地模块,包括routerprisma/db 模块。我们还需要Echo包来访问不同的HTTP方法和Echo中间件以及log来实现HTTP日志。

第4步:创建Go的主函数

func main() {
  e := echo.New()
  e.Use(middleware.Logger())

  client := db.NewClient()
  if err := client.Prisma.Connect(); err != nil {
    log.Fatal(err)
  }

  defer func() {
    if err := client.Prisma.Disconnect(); err != nil {
      panic(err)
    }
  }()

  router.TodoRouter(e, client)

  log.Print(e.Routes())
  e.Logger.Fatal(e.Start(":8000"))
}

在这里,我们使用一个echo 实例来设置一个记录器。每当一个HTTP方法被执行时,它就会记录并打印出一个HTTP状态。

为了访问PrismaClient ,我们使用与Prisma相关的方法,如Connect() ,建立与Prisma引擎的连接,以及Disconnect() ,从运行中的Prisma实例中释放资源。

一旦与Prisma的连接可用,就执行我们先前设置的路由,并将服务器映射到一个端口号。

测试应用程序

服务器已经准备好了,我们可以运行它来测试Go和Prisma是否设置好了执行to-dos。使用命令go run main.go 来运行Go应用程序。这个命令将使用Echo启动Go服务器。

go-server-with-echo

一旦服务器启动并运行,打开Postman并测试不同的HTTP方法。

我们将从创建一个新的待办事项开始。但是,首先,前往Postman,使用URLhttp://localhost:8080/todos/ 创建一个POST方法,如下图所示。

post-method

点击发送来执行上述方法,添加的待办事项将被添加到SQLite数据库中,并由Postman打印出来,如下图所示。

post-todo

你可以继续尝试添加几个新的待办事项。另外,请注意,每次你执行一个方法时,都会在你的命令行控制台注册一个日志。

http-logs

一旦你添加了一个待办事项列表,你可以发送一个GET请求来获取这些待办事项。

get-todos

你也可以用它的id作为请求参数来获取单个待办事项,即http://localhost:8080/todos/:id ,其中:id 是你想获取的待办事项的id值。

总结

Prisma的美妙之处在于,它使数据库的工作感觉非常直观和直接,从数据建模、运行、迁移、编写查询,以及与API的集成。