random recording 随心记录
What seems to us as bitter trials are often blessings in disguise.
看起来对我们痛苦的试炼,常常是伪装起来的好运。
此系列是一个前后端整合项目,跟往期关联,链接传送到达:
1.vite+ts-1-前期准备(尽量详细)
2.vite+ts-2-通过图片名动态加载图片路径
3.vite+ts-3-ts+koa+mysql后端(慢慢更新)
4.vite+ts-4-ORM框架sequelize搭建后端
Sequelize框架优化改进
目录变化
新建src/modules目录
封装模块,合并define和装饰器模型,提高可扩展性和维护性
目录结构如下
Userinfo.ts
import { Column,Model,Table } from "sequelize-typescript";
import { DataTypes } from "sequelize";
// 装饰器
@Table({
tableName:'userinfo'
})
export default class UserinfoModel extends Model<UserinfoModel>{
@Column({
type:DataTypes.INTEGER,
primaryKey:true,
autoIncrement:true
})
userid!:number
@Column({
type:DataTypes.STRING(30),
field:'username',
allowNull:false
})
public username!:string
@Column({
type:DataTypes.STRING(30),
field:'psw',
allowNull:false
})
psw!:string
@Column({
type:DataTypes.STRING(50),
field:'address'
})
public address!:string
@Column({
type:DataTypes.TINYINT,
field:'valid',
})
valid!:number
@Column({
type:DataTypes.DATE,
field:'birth'
})
@Column({
type:DataTypes.TINYINT,
field:'age'
})
age!:number
}
UserDao.ts
import { Op, Sequelize } from 'sequelize'
import { model } from '../defmodel/index'
// import model from '../../decormodel/Userinfo'
class UserDao {
static userDao = new UserDao()
// 添加用户
addUser(userinfo: UserInfo) {
return model.create(userinfo)
}
// 查询所有用户
findAllUser() {
return model.findAll({
raw: true // 屏蔽其他属性,只要记录
})
}
// 投影查询
findByProps() {
return model.findAll({
raw: true,
attributes:['username','psw'] // 想要查询的字段
})
}
// or and 查询
findByUserAndPassword(username:string,psw:string){
return model.findOne({
raw:true,
// where 条件
where:{
// Op是一种条件类型 or and in like
[Op.or]:[
{username},
{psw}
]
}
})
}
// 模糊查询
findByLike(key:string){
const matchKey = `%${key}%`
return model.findAll({
raw:true,
where:{
username:{
[Op.like]:matchKey // % _
}
}
})
}
// and查询
findByUserAndAddr(){
return model.findAll({
raw:true,
where:{
[Op.and]:[
{
username:{
[Op.like]:'%s%'
}
},
{address:'cq'}
]
}
})
}
// 聚合查询 sql:select address,count(valid) from userinfo where valid=1 group by address;
countUserinfo(){
return model.findAll({
raw:true,
group:'address',
attributes:['address',[Sequelize.fn('count',Sequelize.col('valid')),'totalcount']],
where:{
valid:1
}
})
}
// 分页查询 sql:select * from userinfo limit offset,pageSize
findUserWithPager(offset:number,pageSize:number){
return model.findAll({
raw:true,
limit:pageSize,
offset
})
}
}
export type UserInfo = {
userid: string,
username: string,
psw: string,
address: string,
valid: number,
age: number
}
// export const { addUser, findAllUser,findByProps,findByUserAndPassword,findByLike,findByUserAndAddr } = UserDaoDefine
export default UserDao.userDao
definemodel/index.ts
import { DataTypes } from "sequelize";
import { sequelize } from "../../BaseDao";
class UserInfo{
static createMode(){ //表名
const model = sequelize.define('userinfo',{
// 属性
userid:{
type:DataTypes.INTEGER, // 必须属性,类型
field:'userid',
primaryKey:true,
autoIncrement:true
},
username:{
type:DataTypes.STRING(30),
field:'username',
allowNull:false
},
psw:{
type:DataTypes.STRING(30),
field:'psw',
allowNull:false
},
address:{
type:DataTypes.STRING(50),
field:'address'
},
valid:{
type:DataTypes.TINYINT,
field:'valid',
},
birth:{
type:DataTypes.DATE,
field:'birth'
},
age:{
type:DataTypes.TINYINT,
field:'age'
}
},
// 可选参数
{
freezeTableName:true, // true表示使用给定表名,false表示模型名后加s作为表名
timestamps:false // true表示给模型加时间戳(createAt,updateAt),false不加
}
)
model.sync({force:false}) // 同步数据库,true,表存在先删除后创建,false不存在才创建
return model
}
}
export const model = UserInfo.createMode()
BaseDao.ts
import dbConfig from "../conf/DbConfig";
import { Dialect } from "sequelize";
import { Sequelize } from "sequelize-typescript";
import path from 'path'
class BaseDao{
static baseDao:BaseDao = new BaseDao()
sequelize!:Sequelize
constructor(){
this.initSeqConf('mysql')
}
initSeqConf(dialect:Dialect){
let {host,user,password,port,database} = dbConfig.getConf()
this.sequelize = new Sequelize(database,user,password,{
host,
port,
dialect,
define:{timestamps:false,freezeTableName:false}
})
// this.addModels()
}
addModels(){
const modelPath = path.join(process.cwd(),'/src/modules/decormodel')
this.sequelize.addModels([modelPath])
}
}
// 合并第一和第三种模型
const baseDao = BaseDao.baseDao
baseDao.addModels()
export const {sequelize} = baseDao
修改router/user.ts
import userDao,{ UserInfo } from "../modules/userinfo/dao/UserDao"; // define模型
// import userDao from "../modules/userinfo/dao/UserDao"; // 装饰器模型
// 使用 define模型
// post请求 http://localhost:6789/book/usermodule/addUser
router.post('/addUser',async (ctx)=>{
const user:UserInfo = ctx.request.body
ctx.body = `你好,${user.username}`
const userinfo:UserInfo = ctx.request.body
const dbUserinfo = await userDao.addUser(userinfo)
ctx.body = success(dbUserinfo)
})
// 查询所有用户 http://localhost:6789/book/usermodule/findAllUser
router.get('/findAllUser',async (ctx:Context)=>{
const dbUser = await userDao.findAllUser()
console.log(dbUser)
ctx.body = success(dbUser)
})
Koa高性能访问数据库 || sequelize数据库连接池
连接池
数据库连接池是负责创建,分配,释放数据库连接对象,在项目启动时会创建一定数量数据库连接放入连接池对象,并允许应用重复使用现有数据库连接,而不是重新创建新的连接。
Sequelize底层,连接池是由ConnectionManager类管理的pool对象,通过pool类对象来管理和共享多个连接对象。
工作原理
连接池技术的核心思想是连接复用,通过建立一个数据库连接池以及一套连接使用、分配和管理策略,使得该连接池中的连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销。
连接池配置
new Sequelize(database,user,password,{
host,
port,
dialect,
define:{timestamps:false,freezeTableName:false},
pool:{
// 数据库连接池
max:500, // 最大连接池对象个数
min:50, // 最小连接数
idle:10000, // 空闲连接最长等待时间 毫秒ms
acquire:10000 // 一条sql语句查询在获取链接资源之前最长等待时间 ms
}
})
service层
service层应用场景
- 当一个业务功能需要执行一个dao类中的多个方法才能完成时
- 当一个业务功能需要执行多个dao中方法才能完成时
- 当一个业务功能需要对dao类取出来的数据进行处理时