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

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">
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Name"
          required
          className="flex-grow p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
        />
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="Email"
          required
          className="flex-grow p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
        />
        <button
          type="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.kler.cn/a/372288.html

相关文章:

  • gitlab不同账号间·仓库转移
  • magic-api简单使用二:自定义返回结果
  • sql进阶篇
  • 合并排序算法(C语言版)
  • 采用STM32CubeMX和HAL库的定时器应用实例
  • rtp协议:rtcp包格式和传输间隔
  • js获取浏览器指纹
  • rabbitmq高级特性(1):消息确认,持久性,发送方确认和重试机制
  • 在软件工程开发中,瀑布式开发和螺旋式开发的优缺点比较
  • 【数据结构】树-二叉树-堆(上)
  • 堆Heap
  • 医院信息化与智能化系统(13)
  • React Query已过时?新一代请求工具横空出世
  • 日本也有九九乘法表?你会读吗?柯桥零基础学日语到蓝天广场
  • openharmony北向开发入门教程汇总
  • 【非关系型分布式数据库】HBase从入门到面试学习总结
  • Python实现随机分布式延迟PSO优化算法(RODDPSO)优化DBSCAN膨胀聚类模型项目实战
  • IDEA 安装热部署 JRebel -新版-亲测有效
  • Android13预置应用及授权开发
  • Thread类及线程的核心操作
  • Java集合常见面试题总结(5)
  • 常见的开发工具及其作用
  • [论文阅读] GPT-4 Technical Report
  • Kotlin-协程基础
  • 【面试经典150】day 9
  • PostgreSQL 清理 WAL 文件