

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
12345# 数据库(db)67数据库使用的是`typeorm`库89中文文档:](httpsom)1011官方文档:[https://typeorm.io](mdc:https:/据库文档:[https:/www.midwayjs.org/docs/extensions/orm](https:/www.midwayjs.org/docs/extensions/orm)1213## 数据库配置1415支持`Mysql`、`PostgreSQL`、`Sqlite`三种数据库1617#### Mysql1819`src/config/config.local.ts`2021```ts22import { CoolConfig } from "@cool-midway/core";23import { MidwayConfig } from "@midwayjs/core";2425export default {26 typeorm: {27 dataSource: {28 default: {29 type: "mysql",30 host: "127.0.0.1",31 port: 3306,32 username: "root",33 password: "123456",34 database: "cool",35 // 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失36 synchronize: true,37 // 打印日志38 logging: false,39 // 字符集40 charset: "utf8mb4",41 // 是否开启缓存42 cache: true,43 // 实体路径44 entities: ["**/modules/*/entity"],45 },46 },47 },48} as MidwayConfig;49```5051#### PostgreSQL5253需要先安装驱动5455```shell56npm install pg --save57```5859`src/config/config.local.ts`6061```ts62import { CoolConfig } from "@cool-midway/core";63import { MidwayConfig } from "@midwayjs/core";6465export default {66 typeorm: {67 dataSource: {68 default: {69 type: "postgres",70 host: "127.0.0.1",71 port: 5432,72 username: "postgres",73 password: "123456",74 database: "cool",75 // 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失76 synchronize: true,77 // 打印日志78 logging: false,79 // 字符集80 charset: "utf8mb4",81 // 是否开启缓存82 cache: true,83 // 实体路径84 entities: ["**/modules/*/entity"],85 },86 },87 },88} as MidwayConfig;89```9091#### Sqlite9293需要先安装驱动9495```shell96npm install sqlite3 --save97```9899`src/config/config.local.ts`100101```ts102import { CoolConfig } from "@cool-midway/core";103import { MidwayConfig } from "@midwayjs/core";104import * as path from "path";105106export default {107 typeorm: {108 dataSource: {109 default: {110 type: "sqlite",111 // 数据库文件地址112 database: path.join(__dirname, "../../cool.sqlite"),113 // 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失114 synchronize: true,115 // 打印日志116 logging: false,117 // 实体路径118 entities: ["**/modules/*/entity"],119 },120 },121 },122} as MidwayConfig;123```124125## 事务示例126127`cool-admin`封装了自己事务,让代码更简洁128129#### 示例130131```ts132import { Inject, Provide } from "@midwayjs/core";133import { BaseService, CoolTransaction } from "@cool-midway/core";134import { InjectEntityModel } from "@midwayjs/orm";135import { Repository, QueryRunner } from "typeorm";136import { DemoAppGoodsEntity } from "../entity/goods";137138/**139 * 商品140 */141@Provide()142export class DemoGoodsService extends BaseService {143 @InjectEntityModel(DemoAppGoodsEntity)144 demoAppGoodsEntity: Repository<DemoAppGoodsEntity>;145146 /**147 * 事务148 * @param params149 * @param queryRunner 无需调用者传参, 自动注入,最后一个参数150 */151 @CoolTransaction({ isolation: "SERIALIZABLE" })152 async testTransaction(params: any, queryRunner?: QueryRunner) {153 await queryRunner.manager.insert<DemoAppGoodsEntity>(DemoAppGoodsEntity, {154 title: "这是个商品",155 pic: "商品图",156 price: 99.0,157 type: 1,158 });159 }160}161```162163::: tip164`CoolTransaction`中已经做了异常捕获,所以方法内部无需捕获异常,必须使用`queryRunner`做数据库操作,165而且不能是异步的,否则事务无效,166`queryRunner`会注入到被注解的方法最后一个参数中, 无需调用者传参167:::168169## 字段170171BaseEntity 是实体基类,所有实体类都需要继承它。172173- v8.x 之前位于`@cool-midway/core`包中174- v8.x 之后位于`src/modules/base/entity/base.ts`175176```typescript177import { Index, PrimaryGeneratedColumn, Column } from "typeorm";178import * as moment from "moment";179import { CoolBaseEntity } from "@cool-midway/core";180181const transformer = {182 to(value) {183 return value184 ? moment(value).format("YYYY-MM-DD HH:mm:ss")185 : moment().format("YYYY-MM-DD HH:mm:ss");186 },187 from(value) {188 return value;189 },190};191192/**193 * 实体基类194 */195export abstract class BaseEntity extends CoolBaseEntity {196 // 默认自增197 @PrimaryGeneratedColumn("increment", {198 comment: "ID",199 })200 id: number;201202 @Index()203 @Column({204 comment: "创建时间",205 type: "varchar",206 transformer,207 })208 createTime: Date;209210 @Index()211 @Column({212 comment: "更新时间",213 type: "varchar",214 transformer,215 })216 updateTime: Date;217218 @Index()219 @Column({ comment: "租户ID", nullable: true })220 tenantId: number;221}222```223224```typescript225// v8.x 之前226import { BaseEntity } from "@cool-midway/core";227// v8.x 之后228import { BaseEntity } from "../../base/entity/base";229import { Column, Entity, Index } from "typeorm";230231/**232 * demo模块-用户信息233 */234// 表名必须包含模块固定格式:模块_,235@Entity("demo_user_info")236// DemoUserInfoEntity是模块+表名+Entity237export class DemoUserInfoEntity extends BaseEntity {238 @Index()239 @Column({ comment: "手机号", length: 11 })240 phone: string;241242 @Index({ unique: true })243 @Column({ comment: "身份证", length: 50 })244 idCard: string;245246 // 生日只需要精确到哪一天,所以type:'date',如果需要精确到时分秒,应为'datetime'247 @Column({ comment: "生日", type: "date" })248 birthday: Date;249250 @Column({ comment: "状态 0-禁用 1-启用", default: 1 })251 status: number;252253 @Column({254 comment: "分类 0-普通 1-会员 2-超级会员",255 default: 0,256 type: "tinyint",257 })258 type: number;259260 // 由于labels的类型是一个数组,所以Column中的type类型必须得是'json'261 @Column({ comment: "标签", nullable: true, type: "json" })262 labels: string[];263264 @Column({265 comment: "余额",266 type: "decimal",267 precision: 5,268 scale: 2,269 })270 balance: number;271272 @Column({ comment: "备注", nullable: true })273 remark: string;274275 @Column({ comment: "简介", type: "text", nullable: true })276 summary: string;277}278```279280## 虚拟字段281282虚拟字段是指数据库中没有实际存储的字段,而是通过其他字段计算得到的字段,这种字段在查询时可以直接使用,但是不能进行更新操作283284```ts285import { BaseEntity } from "@cool-midway/core";286import { Column, Entity, Index } from "typeorm";287288/**289 * 数据实体290 */291@Entity("xxx_xxx")292export class XxxEntity extends BaseEntity {293 @Index()294 @Column({295 type: "varchar",296 length: 7,297 asExpression: "DATE_FORMAT(createTime, '%Y-%m')",298 generatedType: "VIRTUAL",299 comment: "月份",300 })301 month: string;302303 @Index()304 @Column({305 type: "varchar",306 length: 4,307 asExpression: "DATE_FORMAT(createTime, '%Y')",308 generatedType: "VIRTUAL",309 comment: "年份",310 })311 year: string;312313 @Index()314 @Column({315 type: "varchar",316 length: 10,317 asExpression: "DATE_FORMAT(createTime, '%Y-%m-%d')",318 generatedType: "VIRTUAL",319 comment: "日期",320 })321 date: string;322323 @Column({ comment: "退款", type: "json", nullable: true })324 refund: {325 // 退款单号326 orderNum: string;327 // 金额328 amount: number;329 // 实际退款金额330 realAmount: number;331 // 状态 0-申请中 1-已退款 2-拒绝332 status: number;333 // 申请时间334 applyTime: Date;335 // 退款时间336 time: Date;337 // 退款原因338 reason: string;339 // 拒绝原因340 refuseReason: string;341 };342343 // 将退款状态提取出来,方便查询344 @Index()345 @Column({346 asExpression: "JSON_EXTRACT(refund, '$.status')",347 generatedType: "VIRTUAL",348 comment: "退款状态",349 nullable: true,350 })351 refundStatus: number;352}353```354355## 不使用外键356357typeorm 有很多 OneToMany, ManyToOne, ManyToMany 等关联关系,这种都会生成外键,但是在实际生产开发中,不推荐使用外键:358359- 性能影响:外键会在插入、更新或删除操作时增加额外的开销。数据库需要检查外键约束是否满足,这可能会降低数据库的性能,特别是在大规模数据操作时更为明显。360361- 复杂性增加:随着系统的发展,数据库结构可能会变得越来越复杂。外键约束增加了数据库结构的复杂性,使得数据库的维护和理解变得更加困难。362363- 可扩展性问题:在分布式数据库系统中,数据可能分布在不同的服务器上。外键约束会影响数据的分片和分布,限制了数据库的可扩展性。364365- 迁移和备份困难:带有外键约束的数据库迁移或备份可能会变得更加复杂。迁移时需要保证数据的完整性和约束的一致性,这可能会增加迁移的难度和时间。366367- 业务逻辑耦合:过多依赖数据库的外键约束可能会导致业务逻辑过度耦合于数据库层。这可能会限制应用程序的灵活性和后期的业务逻辑调整。368369- 并发操作问题:在高并发的场景下,外键约束可能会导致锁的竞争,增加死锁的风险,影响系统的稳定性和响应速度。370371尽管外键提供了数据完整性保障,但在某些场景下,特别是在高性能和高可扩展性要求的系统中,可能会选择在应用层实现相应的完整性检查和约束逻辑,以避免上述问题。这需要在设计系统时根据实际需求和环境来权衡利弊,做出合适的决策。372373## 多表关联查询374375cool-admin 有三种方式的联表查询:3763771、controller 上配置378379特别注意要配置 select, 不然会报重复字段错误380381```ts382@CoolController({383 // 添加通用CRUD接口384 api: ['add', 'delete', 'update', 'info', 'list', 'page'],385 // 设置表实体386 entity: DemoAppGoodsEntity,387 // 分页查询配置388 pageQueryOp: {389 // 指定返回字段,注意多表查询这个是必要的,否则会出现重复字段的问题390 select: ['a.*', 'b.name', 'a.name AS userName'],391 // 联表查询392 join: [393 {394 entity: BaseSysUserEntity,395 alias: 'b',396 condition: 'a.userId = b.id'397 },398 ]399})400```4014022、service 中403404通过`this.nativeQuery`或者`this.sqlRenderPage`两种方法执行自定义 sql405406- nativeQuery:执行原生 sql,返回数组407- sqlRenderPage:执行原生 sql,返回分页对象408409模板 sql 示例,方便动态传入参数,千万不要直接拼接 sql,有 sql 注入风险,以下方法 cool-admin 内部已经做了防注入处理410411- setSql:第一个参数是条件,第二个参数是 sql,第三个参数是参数数组412413```ts414this.nativeQuery(415 `SELECT416 a.*,417 b.nickName418 FROM419 demo_goods a420 LEFT JOIN user_info b ON a.userId = b.id421 ${this.setSql(true, 'and b.userId = ?', [userId])}`422```4234243、通过 typeorm 原生的写法425426示例427428```ts429const find = this.demoGoodsEntity430 .createQueryBuilder("a")431 .select(["a.*", "b.nickName as userName"])432 .leftJoin(UserInfoEntity, "b", "a.id = b.id")433 .getRawMany();434```435436## 配置字典和可选项(8.x 新增)437438为了让前端可能自动识别某个字段的可选项或者属于哪个字典,我们可以在@Column 注解上配置`options`和`dict`属性,439440旧的写法441442```ts443// 无法指定字典444445// 可选项只能按照一定规则编写,否则前端无法识别446@Column({ comment: '状态 0-禁用 1-启用', default: 1 })447status: number;448```449450新的写法451452```ts453// 指定字典为goodsType,这样前端生成的时候就会默认指定这个字典454@Column({ comment: '分类', dict: 'goodsType' })455type: number;456457// 状态的可选项有禁用和启用,默认是启用,值是数组的下标,0-禁用,1-启用458@Column({ comment: '状态', dict: ['禁用', '启用'], default: 1 })459status: number;460```461
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| cool-team-official/cool-admin-midway.cursor/rules/authority.mdc · 3.3k | Cursor rules | security | 54/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/cache.mdc · 3.3k | Cursor rules | no sections | 58/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/controller.mdc · 3.3k | Cursor rules | api | 46/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/event.mdc · 3.3k | Cursor rules | no sections | 45/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/module.mdc · 3.3k | Cursor rules | no sections | 50/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/service.mdc · 3.3k | Cursor rules | database | 54/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/socket.mdc · 3.3k | Cursor rules | no sections | 58/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/task.mdc · 3.3k | Cursor rules | style | 58/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/tenant.mdc · 3.3k | Cursor rules | no sections | 50/100 | today | |
| cool-team-official/cool-admin-midway.cursorrules · 3.3k | .cursorrules | no sections | 39/100 | today |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 46 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/cool-team-official-cool-admin-midway-cursor-rules-db)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.