前提假設本地的mysql環境安裝完成
1、 安裝typeorm和mysql
$ npm install --save @nestjs/typeorm typeorm mysql2 nestjs-config
2、導入到AppModule中
采用的是cofing的模式導入配置資訊
異步配置參考位址
在src目錄下建立config檔案
database.config.ts
export default {
type: process.env.DB_TYPE,
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
database: process.env.DB_DATABASE,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
logging: true,
};
.env
PREFIX=api/v1
PORT=XXXX
DB_TYPE=mysql
DB_HOST=localhost
DB_USERNAME=root
DB_PASSWORD=123456
DB_DATABASE=backstage
DB_PORT=3306
DB_LOGGING=true
SECRET=secret
import { ConfigModule, ConfigService } from 'nestjs-config';
@Module({
imports: [
// 配置加載配置檔案
ConfigModule.load(path.resolve(__dirname, 'config', '**/!(*.d).{ts,js}'), {
modifyConfigName: (name) => name.replace('.config', ''),
}),
// mysql的連接配接
TypeOrmModule.forRootAsync({
useFactory: async (config: ConfigService) => ({
type: config.get('database.type'),
host: config.get('database.host'),
port: config.get('database.port'),
username: config.get('database.username'),
password: config.get('database.password'),
database: config.get('database.database'),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
subscribers: [__dirname + './../subscribers/*.subscriber{.ts,.js}'],
logging: config.get('database.logging'),
synchronize: false,
timezone: '+08:00', // 東八區
}),
inject: [ConfigService],
}),
UserModule,
],
controllers: [AppController],
providers: [
AppService,
],
})
ormconfig.js
{
"type": process.env.DB_TYPE, // 選用的資料庫
"host": process.env.DB_HOST, // 資料庫位址
"port": Number(process.env.DB_PORT), // 資料庫端口
"username": process.env.DB_USERNAME, // 資料庫使用者名
"password": process.env.DB_PASSWORD, // 資料庫密碼
"database": process.env.DB_DATABASE, // 資料庫
"synchronize": true, // 是否同步true表示會自動将src/entity裡面定義的資料子產品同步到資料庫生成資料表(已經存在的表的時候再運作會報錯) 生産環境應改為false 通過指令行操作更新資料庫
"dropSchema": true, // 删除資料庫中的表
"logging": false, // 是否列印日志,執行sql語句時候輸出原生sql,也可以配置成一個數組["query", "error", "schema"]指定sql的執行類型
"charset": "utf8mb4", // 編碼
"timezone": "local", // 時區,預設本地,也可以寫"+8"
"entityPrefix": "", // 給此資料庫連接配接上的所有表(或集合)加的字首。
"entities": [ // 定義TypeORM需要查找的資料模型的,可以定義多個
"src/modules/**/*.entity.{ts,js}"
],
"migrations": [ // 資料遷移檔案生成的地方
"src/migration/**/*.ts"
],
"subscribers": [ // 訂閱(用的少)
"src/subscribers/**/*.ts"
],
"cli": { // 資料遷移工具使用的
"entitiesDir": "src/modules",
"migrationsDir": "src/migration",
"subscribersDir": "src/subscriber"
}
}
實作mysql typeorm 資料遷移的重點 個人學習
entities
和
migrations
的路徑要對應上 否則找不到檔案 mysql不會生成對應的
migration
表
"entities": [
"src/modules/**/*.entity.{ts,js}"
],
"migrations": [
"src/migration/**/*.ts"
],
"cli": {
"entitiesDir": "src/modules",
"migrationsDir": "src/migration"
}
配置
package.json
"scripts": {
"generate": "ts-node ./node_modules/typeorm/cli.js migration:generate -n Test",
"db": "ts-node ./node_modules/typeorm/cli.js migration:run"
}
通過
npm run generate
會在設定的migrations路徑下生成對應的檔案
1646202649266-Test.ts
函數
up
為将要改變的資料庫的内容
函數
down
為恢複之前的資料庫的内容
import {MigrationInterface, QueryRunner} from "typeorm";
export class Test1646202649266 implements MigrationInterface {
name = 'Test1646202649266'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE \`user\` DROP COLUMN \`grade\``);
await queryRunner.query(`ALTER TABLE \`user\` CHANGE \`gender\` \`gender\` int NOT NULL COMMENT '性别' DEFAULT 0`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE \`user\` CHANGE \`gender\` \`gender\` int NOT NULL COMMENT '性别' DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE \`user\` ADD \`grade\` int NULL COMMENT '分數'`);
}
}
通過
npm run db
執行生成的
migration
檔案 資料庫就會變更為新的對應
entity
字段格式
至此 資料遷移完成
mysql資料庫在service中使用
方式一: 通過
Entity
将資料庫注入到
Service
中 在方法中通過this.xxx 調用服務
import {
BadRequestException,
HttpStatus,
Injectable,
Logger,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { UserDto } from './user.dto';
import { UserEntity } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
) {}
async createUser(userDto: UserDto) {
const oldUser = await this.userRepository.find({
name: userDto.name,
});
if (oldUser.length) {
throw new BadRequestException('使用者已存在~');
}
userDto['hobby'] = userDto.hobby.toString();
const createUser = await this.userRepository.create(userDto);
const user = await this.userRepository.save(createUser);
Logger.log('建立成功', `${user.name} 使用者建立成功`);
return user;
}
}
方式二:connection 參考connection 增删改查
async getPowerRoles(powerRolesDto): Promise<{ids: number[], keys: string[]}> {
const list = await getConnection()
.createQueryBuilder(PowerRolesEntity, 'powerRoles')
.where("powerRoles.isDel = 0")
.andWhere("(powerRoles.roleId = :roleId)", { roleId: powerRolesDto.roleId })
.getMany();
const powerKeys = []
for (const item of list) {
const { powerId } = item
const res = await this.powerRepository.findOne(powerId)
if (res.isDel === 0) {
// 未删除的才放入清單
powerKeys.push(res.key)
}
}