tencent cloud

文档反馈

访问数据库

最后更新时间:2024-04-22 17:54:01
    Malagu 框架可以方便地集成第三方数据库操作相关的框架,例如 Sequelize、Typeorm 等。基于 Malagu 的组件机制,第三库扩展性更强,且支持属性配置,开箱即用。
    目前,框架提供了对 Typeorm 库的集成,可以通过框架配置文件,配置数据库链接相关信息。另外,Malagu 框架是 Serverless First,框架在集成 Typeorm 时,对 Serverless 场景进行了最佳实践适配。同时借鉴了 Spring 事务管理机制,提供了无侵入式的事务管理,并支持事务的传播行为。

    使用方法

    1. 框架提供了一个内置模板 database-app ,执行以下命令可以快速初始化一个有关数据库操作的模板应用。
    malagu init demo database-app
    2. 初始化完成后,只需将数据库链接配置改成当前实际环境的配置。通过执行以下命令也可以在项目里直接安装 @malagu/typeorm 组件。
    yarn add @malagu/typeorm
    # 或者执行 npm i @malagu/typeorm

    配置数据源链接

    在 Malagu 中,数据源链接配置与 Typeorm 类似,只是配置形式和位置稍微不同。框架为使第三库的配置方式与框架组件的配置方式保持统一,框架在集成 Typeorm 时,将 Typeorm 的原有配置方式适配成了框架组件的配置方式。更多 Typeorm 数据源链接配置说明,请参见 Typeorm 官方文档
    单数据源
    多数据源
    数据源链接名称如果未设置,则默认是 default。
    # malagu.yml
    backend:
    malagu:
    typeorm:
    ormConfig:
    - type: mysql
    host: localhost
    port: 3306
    synchronize: true
    username: root
    password: root
    database: test
    为区分不同的数据源链接,需要为数据源链接设置名称,有且只有一个可以不设置名称,且该链接默认名称为 default。在使用 OrmContext 相关的 API 时,将会使用数据源链接名称。
    # malagu.yml
    backend:
    malagu:
    typeorm:
    ormConfig:
    - type: mysql
    host: localhost
    port: 3306
    synchronize: true
    username: root
    password: root
    database: test
    - type: mysql
    name: 'datasource2'
    host: xxxx
    port: 3306
    synchronize: true
    username: root
    password: root
    database: 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; // 多数据源链接情况下,指定数据源链接名称,默认为 default
    isolation?: IsolationLevel; // 数据库隔离级别
    propagation?: Propagation; // 事务的传播行为,支持 Required 和 RequiresNew,默认为 Required
    readOnly?: 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 要获取的 EntityMananger 名称保持一致,不指定名称,则默认为 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
    绑定实体类。
    联系我们

    联系我们,为您的业务提供专属服务。

    技术支持

    如果你想寻求进一步的帮助,通过工单与我们进行联络。我们提供7x24的工单服务。

    7x24 电话支持