从零开始实现一个简单的 rest 风格服务器 (4) —— 连接 postgresql 数据库

从零开始实现一个简单的rest风格服务器 (1) —— typescript 开发环境配置
从零开始实现一个简单的rest风格服务器 (2) —— 集成 koa
从零开始实现一个简单的rest风格服务器 (3) —— 自动编译

终于写到要连接数据库啦,有些读者可能等得有点不耐烦了。以前的几篇写的都是些花架子,只有连上数据库,才是能算是一个完整的 rest 风格服务器嘛。

这里选用 sequelize 这个 ORM 框架来连接 postgresql 数据库,当然你也可以直接用 sql 来操作数据库。为什么会选择 ORM 框架呢,还是为了获得 IDE 的更多提示嘛。文章有点长,我为每一个步骤标上序号,大家耐心点。

1、安装 sequelize,数据库驱动 pg 以及与 typescript 相关的包

yarn add sequelize sequelize-typescript pg reflect-metadata

2、新建数据库配置文件夹 conf 及 配置文件 db.conf.ts

/**
 * @name: 数据库配置
 * @param : undefined
 * @return : undefined
 */ 
export const dbConfig = {
  host: 'localhost',
  database: 'demo',
  dialect: 'postgres',
  username: 'postgres',
  password: '123456'
}

3、连接数据库,新建文件夹 db 及 配置文件 db.ts

/*
 * @Description: 数据库连接类
 */
import * as path from 'path'
import { Sequelize } from 'sequelize-typescript'
import { dbConfig } from '../conf/db.conf'

class DbContext {
  private sequelize: Sequelize
  constructor() {
    const { host, database, dialect, username, password } = dbConfig
    this.sequelize = new Sequelize({
      host: host,
      database: database,
      dialect: dialect,
      username: username,
      password: password,
      define: {
        timestamps: true,  //开启时间戳 create_at delete_at update_at
        paranoid: true,    //开启假删除
        underscored: true, //下划线
        charset: 'utf8',
        freezeTableName: true //固定表名为单数  默认表名是xxxs
      },
      pool: {
        max: 10,
        min: 0,
        acquire: 30000,
        idle: 10000
      },
      timezone: '+08:00',
      modelPaths: [path.resolve(__dirname, `./models`)]
    })
    this.sequelize.sync()
  }
  init(): Boolean {
    return !!this.sequelize
  }
  getInstance(): Sequelize {
    return this.sequelize
  }
  isInit(): Boolean {
    return !!this.sequelize
  }
}
export const dbContext = new DbContext()

4、数据库实体类,新建文件夹 models 及文件 user.ts

/*
 * @Description: 数据库实体类
 */

import { Table, Column, Model } from 'sequelize-typescript'

@Table({
  tableName: 'user'
})
export default class User extends Model<User> {
  @Column({
    comment: '自增ID',
    primaryKey: true,
    autoIncrement: true,
  })
  id: number

  @Column
  username: string

  @Column
  password: string
}

5、编写业务逻辑接口,在 src 目录下新建文件夹 dao、service,在 dao 目录下新建 UserDao.ts 及子目录 impl,在 service 目录下新建 UserService.ts 及子目录 impl

/*
 * @Description: 数据库表操作基础接口 UserDao.ts 
 */
export interface UserDao {
  /**
   * @name: 查询
   * @param : 
   * @return : Array<User>
   */
  findAll();
  /**
   * @name: 查询
   * @param : 
   * @return : Array<User>
   */
  findByName(username:string);
  /**
   * @name: 新增
   * @param : undefined
   * @return : undefined
   */
  create(entity:UserInfo);

  /**
   * @name: 删除
   * @param : undefined
   * @return : undefined
   */
  delete(id:number);
}
export interface UserInfo {
  username:string;
  password:string;
}

==================================================

/*
 * @Description: service接口  UserService.ts
 * @version: 
 */

export interface UserService{
  /**
   * @name: 查询
   * @param : undefined
   * @return : undefined
   */
  findAll();
  
  /**
   * @name: 查询
   * @param : undefined
   * @return : undefined
   */
  findByName(username:string);

  /**
   * @name: 新增
   * @param : undefined
   * @return : undefined
   */
  create(username:string,password:string);

  /**
   * @name: 删除
   * @param : undefined
   * @return : undefined
   */
  delete(id:String);
}

6、编写业务逻辑实现类 UserDaoImpl.ts、UserServiceImpl.ts

/*
 * @Description: 数据库表操作基础实现类 UserDaoImpl.ts
 */
 
import { dbContext } from '../../db/db'
import { UserDao, UserInfo } from '../UserDao';
import User from '../../db/models/user';

export class UserDaoImpl implements UserDao{
  constructor(){
    dbContext.init();
  }
  /**
   * @name: 查询
   * @param : undefined
   * @return : undefined
   */
  public async findAll(){
    const results = await User.findAll({
      raw: true
    })
    return results;
  } 
  
   /**
   * @name: 查询
   * @param : undefined
   * @return : undefined
   */
  public async findByName(username:string){
    const results = await User.findOne({
      where:{
        username:username
      }
    })
    return results;
  } 

  /**
   * @name: 新增
   * @param : entity
   * @return : undefined
   */
  public async create(entity:UserInfo) {
    const results = await User.create(entity)
    return results;
  }
  
   /**
   * @name: 删除
   * @param : undefined
   * @return : undefined
   */
  public async delete(id: number) {
    const results = await User.destroy({
      where:{
          id:{
            $eq:id
          }
      }
    });
    return results;
  }
}

========================================================

/*
 * @Description: service实现类 UserServiceImpl.ts
 */
import { UserService } from "../UserService";
import { UserDao } from "../../dao/UserDao";
import { UserDaoImpl } from "../../dao/impl/UserDaoImpl";

export class UserServiceImpl implements UserService{
  private userDao:UserDao;

  constructor(){
    this.userDao = new UserDaoImpl();
  }

  /**
   * @name: 查询
   * @param : undefined
   * @return : undefined
   */
  public findAll() {
    return this.userDao.findAll();
  } 
  /**
   * @name: 查询
   * @param : undefined
   * @return : undefined
   */
  public findByName(username:string) {
    return this.userDao.findByName(username);
  } 
  /**
   * @name: 新增
   * @param : entity
   * @return : undefined
   */
  public create(username: string, password: string) {
    return this.userDao.create({username,password});
  }

  /**
   * @name: 删除
   * @param : undefined
   * @return : undefined
   */
  public delete(id: String) {
    return this.userDao.delete(~~id);
  }  
}

7、查看成果,修改 router/index.ts

/*
 * @Description: 后台路由组件
 * @version: 0.1.0
 */
import * as Router from 'koa-router';
import { UserInfo } from '../dao/UserDao';
import { UserService } from '../service/UserService';
import { UserServiceImpl } from '../service/impl/UserServiceImpl';

const router = new Router();
const userService:UserService =new UserServiceImpl();

router.get('/*', async (ctx) => {
  ctx.body = await userService.findAll();
})

export { router }

8、浏览器输入 http://localhost:8080
在这里插入图片描述

数据库连接成功!!!

目录结构:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值