当前位置: 首页 > news >正文

Next.js、Prisma 和 MySQL 实践示例

1. 环境设置

a. 创建 Next.js 项目

首先,使用下面的命令创建一个新的 Next.js 应用:

npx create-next-app@latest my-next-prisma-app  cd my-next-prisma-app  

b. 安装依赖

安装 Prisma 和 MySQL 驱动程序:

npm install @prisma/client prisma mysql  

c. 初始化 Prisma

初始化 Prisma,并创建一个 Prisma 配置文件:

npx prisma init  

这将创建一个 prisma 文件夹,其中包含 schema.prisma 文件。

d. 环境变量

在 .env 文件中配置数据库连接字符串:

DATABASE_URL="mysql://user:password@localhost:3306/mydb?connection_limit=10"  

2. 设置 Prisma 模型

在 prisma/schema.prisma 文件中定义数据模型。例如,一个简单的用户模型:

generator client {  provider = "prisma-client-js"  
}  datasource db {  provider = "mysql"  url      = env("DATABASE_URL")  
}  model User {  id        Int      @id @default(autoincrement())  name      String  email     String   @unique  createdAt DateTime @default(now())  updatedAt DateTime @updatedAt  
}  

运行以下命令生成数据库迁移并更新数据库结构:

npx prisma migrate dev --name init  npx prisma generate

查看数据库状态(可选):

可以使用以下命令查看数据库的当前状态:

npx prisma studio  

3. 使用中间件处理连接

为了避免连接泄漏,使用 Prisma 中间件来处理连接。可以创建一个 db/prisma.ts 文件:

// data/prisma.ts  
import { PrismaClient } from '@prisma/client';class PrismaInstance {private static instance: PrismaClient | undefined;private constructor() { }public static getInstance(): PrismaClient {if (!PrismaInstance.instance) {PrismaInstance.instance = new PrismaClient();}return PrismaInstance.instance;}
}// 导出 Prisma 实例获取方法
export const prisma = PrismaInstance.getInstance();

在上面的代码中,确保多个请求不会重复创建 Prisma 实例。

4. 创建 API 路由

在 pages/api 文件夹中创建 API 路由。例如,创建 users/route.ts 文件处理用户的 CRUD 操作:

// pages/api/users/route.ts  
import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/db/prisma';export async function GET(request: NextRequest) {const { searchParams } = new URL(request.url);const id = searchParams.get('id');if (id) {// 获取特定用户const user = await prisma.user.findUnique({where: { id: Number(id) },});if (!user) {return NextResponse.json({ error: 'User not found' }, { status: 404 });}return NextResponse.json(user);} else {// 获取所有用户const users = await prisma.user.findMany();return NextResponse.json(users);}
}export async function POST(request: NextRequest) {const { name, email } = await request.json();const newUser = await prisma.user.create({data: { name, email },});return NextResponse.json(newUser, { status: 201 });
}export async function PUT(request: NextRequest) {const { searchParams } = new URL(request.url);const id = searchParams.get('id');if (!id) {return NextResponse.json({ error: 'User ID is required' }, { status: 400 });}const { name, email } = await request.json();const updatedUser = await prisma.user.update({where: { id: Number(id) },data: { name, email },});return NextResponse.json(updatedUser);
}export async function DELETE(request: NextRequest) {const { searchParams } = new URL(request.url);const id = searchParams.get('id');if (!id) {return NextResponse.json({ error: 'User ID is required' }, { status: 400 });}await prisma.user.delete({where: { id: Number(id) },});return new NextResponse(null, { status: 204 });
}

5. 创建前端页面

可以在 app/page.tsx 中创建一个简单的用户列表和表单来添加用户:

// app/page.tsx  
'use client';import { useEffect, useState } from 'react';interface User {id: string;name: string;email: string;
}const Home = () => {const [users, setUsers] = useState<User[]>([]);const [name, setName] = useState('');const [email, setEmail] = useState('');const fetchUsers = async () => {try {const response = await fetch('/api/users');if (!response.ok) {throw new Error('Failed to fetch users');}const data = await response.json();setUsers(data);} catch (error) {console.error('Error fetching users:', error);}};const addUser = async (e: React.FormEvent<HTMLFormElement>) => {e.preventDefault();try {const response = await fetch('/api/users', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ name, email }),});if (!response.ok) {throw new Error('Failed to add user');}setName('');setEmail('');fetchUsers();} catch (error) {console.error('Error adding user:', error);}};useEffect(() => {fetchUsers();}, []);return (<div className="p-4 max-w-2xl mx-auto"><h1 className="text-3xl font-bold mb-6 text-center">User List</h1><form onSubmit={addUser} className="mb-8 flex flex-col sm:flex-row gap-4"><inputtype="text"value={name}onChange={(e) => setName(e.target.value)}placeholder="Name"requiredclassName="flex-grow p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500"/><inputtype="email"value={email}onChange={(e) => setEmail(e.target.value)}placeholder="Email"requiredclassName="flex-grow p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500"/><buttontype="submit"className="p-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-700">Add User</button></form>{users.length > 0 ? (<ul className="space-y-2">{users.map((user) => (<li key={user.id} className="p-3 bg-gray-100 rounded shadow"><span className="font-semibold">{user.name}</span> - {user.email}</li>))}</ul>) : (<p className="text-center text-gray-500">No users found. Add a user to get started!</p>)}</div>);
};export default Home;

http://www.mrgr.cn/news/59719.html

相关文章:

  • 深度解析百度搜索引擎点击结果:如何提高网站曝光率和用户满意度
  • TypeScript(中)+算法(二)
  • 2024 Blue Water CTF - The Great Escape
  • 整和 Wechaty机器人(Windows)
  • 【完整版】opencv-python-headless、opencv-python和opencv-contrib-python区别和联系
  • 香港海洋投资启动创新海洋牧场,领航全球海洋经济
  • 面向对象进阶(下)(JAVA笔记第二十五期)
  • 重构代码之状态与策略模式
  • 破解API加密逆向接口分析,看这篇就够了
  • 录屏软件推荐,4个工具助你高效录屏。
  • 自适应阻抗控制基本概念
  • redis 查找key使用正在表达式与java的区别
  • 《C++中局部变量与全局变量在内存中的奥秘》
  • vue 项目情景应用+深度理解+面试高频题
  • 海洋生物图像分割系统:算法改进策略
  • 习题2.40
  • 群控系统服务端开发模式-应用开发-业务架构逻辑开发API准备工作
  • D. Skipping 【 Codeforces Round 980 (Div. 2)】
  • 用Pycharm 运行深度学习,在测试(推理)运行测试文件会自动进入pytest模式,如何关闭默认测试框架
  • LVGL _基础控件_Label 文本