腾讯云云函数使用教程 - Malagu Framework 访问数据库
文档简介:
Malagu 框架可以方便地集成第三方数据库操作相关的框架,例如 Sequelize、Typeorm 等。基于 Malagu 的组件机制,第三库扩展性更强,且支持属性配置,开箱即用。
Malagu 框架可以方便地集成第三方数据库操作相关的框架,例如 Sequelize、Typeorm 等。基于 Malagu 的组件机制,第三库扩展性更强,且支持属性配置,开箱即用。
目前,框架提供了对 Typeorm 库的集成,可以通过框架配置文件,配置数据库链接相关信息。另外,Malagu 框架是 Serverless First,框架在集成 Typeorm 时,对 Serverless 场景进行了最佳实践适配。同时借鉴了 Spring 事务管理机制,提供了无侵入式的事务管理,并支持事务的传播行为。
使用方法
1. 安装 malagu 软件,详细安装步骤请参见 使用 Malagu。
2. 框架提供了一个内置模板 database-app ,执行以下命令可以快速初始化一个有关数据库操作的模板应用。
malagu init demo database-app
3. 初始化完成后,只需将数据库链接配置改成当前实际环境的配置。通过执行以下命令也可以在项目里直接安装 @malagu/typeorm 组件。
yarn add @malagu/typeorm# 或者执行 npm i @malagu/typeorm
配置数据源链接
在 Malagu 中,数据源链接配置与 Typeorm 类似,只是配置形式和位置稍微不同。框架为使第三库的配置方式与框架组件的配置方式保持统一,框架在集成 Typeorm 时,将 Typeorm 的原有配置方式适配成了框架组件的配置方式。更多 Typeorm 数据源链接配置说明,请参见 Typeorm 官方文档。
数据源链接名称如果未设置,则默认是 default。
# malagu.ymlbackend:malagu:typeorm:ormConfig:- type: mysqlhost: localhostport: 3306synchronize: trueusername: rootpassword: rootdatabase: test
为区分不同的数据源链接,需要为数据源链接设置名称,有且只有一个可以不设置名称,且该链接默认名称为 default。在使用 OrmContext 相关的 API 时,将会使用数据源链接名称。
# malagu.ymlbackend:malagu:typeorm:ormConfig:- type: mysqlhost: localhostport: 3306synchronize: trueusername: rootpassword: rootdatabase: test- type: mysqlname: 'datasource2'host: xxxxport: 3306synchronize: trueusername: rootpassword: rootdatabase: test
数据库操作
以下示例使用 rest 风格来实现 API。
说明
您也可以使用 RPC 风格来实现,这两种风格类似。
import { Controller, Get, Param, Delete, Put, Post, Body } from '@malagu/mvc/lib/node';import { Transactional, OrmContext } from '@malagu/typeorm/lib/node';import { User } from './entity';@Controller('users')export class UserController {@Get()@Transactional({ readOnly: true })list(): Promise<User[]> {const repo = OrmContext.getRepository(User);return repo.find();}@Get(':id')@Transactional({ readOnly: true })get(@Param('id') id: number): Promise<User | undefined> {const repo = OrmContext.getRepository(User);return repo.findOne(id);}@Delete(':id')@Transactional()async reomve(@Param('id') id: number): Promise<void> {const repo = OrmContext.getRepository(User);await repo.delete(id);}@Put()@Transactional()async modify(@Body() user: User): Promise<void> {const repo = OrmContext.getRepository(User);await repo.update(user.id, user);}@Post()@Transactional()create(@Body() user: User): Promise<User> {const repo = OrmContext.getRepository(User);return repo.save(user);}}
数据库上下文
在 Malagu 框架中,Typeorm 的事务托管至框架管理。框架提供了一个装饰器 @Transactional ,用于框架在执行方法前后如何开启、传播、提交和回滚事务。同时框架会将托管的 Entitymanager 对象放到数据库上下文中,方便在业务代码中使用。另外您也可以手动管理数据库事务和创建 EntityManager 对象。
数据库上下文基于请求上下文实现,因此数据库上下文也是请求级别。在数据库上下文中主要提供了获取 EntityManager 和 Repository 对象相关的方法:
export namespace OrmContext {export function getEntityManager(name = DEFAULT_CONNECTION_NAME): EntityManager {...}export function getRepository<Entity>(target: ObjectType<Entity>|EntitySchema<Entity>|string, name?: string): Repository<Entity> {...}export function getTreeRepository<Entity>(target: ObjectType<Entity>|EntitySchema<Entity>|string, name?: string): TreeRepository<Entity> {...}export function getMongoRepository<Entity>(target: ObjectType<Entity>|EntitySchema<Entity>|string, name?: string): MongoRepository<Entity> {...}export function getCustomRepository<T>(customRepository: ObjectType<T>, name?: string): T {...}export function pushEntityManager(name: string, entityManager: EntityManager): void {...}export function popEntityManager(name: string): EntityManager | undefined {...}}
事务管理
Malagu 框架提供了一个装饰器 @Transactional ,以声明的方式定义事务的行为,Malagu 框架根据装饰器声明决定事务的开启、传播、提交和回滚行为。
@Transactional
@Transactional 装饰器可以加在类和方法上,如果类和方法同时加上,最终的配置是使用方法的配置去合并类,且方法的配置优先级高于类上。装饰器配置选项如下:
export interface TransactionalOption {name?: string; // 多数据源链接情况下,指定数据源链接名称,默认为 defaultisolation?: IsolationLevel; // 数据库隔离级别propagation?: Propagation; // 事务的传播行为,支持 Required 和 RequiresNew,默认为 RequiredreadOnly?: boolean; // 只读,不开启事务,默认为开启事务}
示例如下:
@Put()@Transactional()async modify(@Body() user: User): Promise<void> {const repo = OrmContext.getRepository(User);await repo.update(user.id, user);}
@Transactional 与 OrmContext
Malagu 框架根据装饰器的配置,在方法调用前开启事务(也可能不开启),并将 EntityManager 托管在 OrmContext 上下文中,通过 OrmContext 取到框架帮助开启过事务的 EntityManager,其中 Repository 是通过托管的 EntityManager 创建。为正确获取到 EntityManager,请确保装饰器配置的名称与通过 OrmContext 要获取的 EntityManager 名称保持一致,不指定名称,则默认为 default。
方法执行后,框架根据方法的执行情况,自动决定事务是提交还是回滚,方法执行出现异常则回滚事务,否则提交事务。
当方法存在嵌套调用带 @Transactional 装饰器的方法,由事务传播行为的配置决定是复用上层方法的事务,还是重新开启新的事务。
数据库查询
数据库查询大部分情况无需开启事务,但建议最好在方式加上 @Transactional 装饰器,并将 readonly 配置为 true,让框架创建一个不开启事务的 EntityManager,保持代码风格统一。示例如下:
@Get()@Transactional({ readOnly: true })list(): Promise<User[]> {const repo = OrmContext.getRepository(User);return repo.find();}
事务传播行为
事务传播行为决定事务在需要事务的不同方法之间如何传播,目前支持两种事务传播行为:
export enum Propagation {Required, RequiresNew}
Required:需要开启一个事务,如果上一层方法已经开启过事务,则复用上一个事务,否则开启一个新事务。
RequiresNew:无论上一层方法是否开启过事务,都将开启一个新事物。
注意
事务在不同的方法传播的时候,请保证方法之间是同步调用的。示例如下:
...@Transactional()async foo(): Promise<void> {...await bar(); // 必须加上 await}.......@Transactional()async bar(): Promise<void> {...}
绑定实体类
框架提供了一个方法 autoBindEntities 用于绑定实体类,该方法一般在模块入口文件里调用。方法包含以下两个参数:
entities:您定义的实体类。
name:您希望实体类与哪个数据源连接绑定,默认与 default 绑定。
export function autoBindEntities(entities: any, name = DEFAULT_CONNECTION_NAME) {}
示例如下:
import { autoBindEntities } from '@malagu/typeorm';import * as entities from './entity';import { autoBind } from '@malagu/core';autoBindEntities(entities);export default autoBind();
工具类
工具
|
描述
|
DEFAULT_CONNECTION_NAME
|
默认数据库连接名称 default。
|
autoBindEntities
|
绑定实体类。
|