Giter Site home page Giter Site logo

Comments (7)

silent-tan avatar silent-tan commented on May 23, 2024

实现是可以实现,但是觉得这种写法很挫。不用 @Transaction 修饰器是因为 typeorm0.4.0 版本好像是要删掉这些修饰器的

from nestjs-learning.

silent-tan avatar silent-tan commented on May 23, 2024

而且通过查看typeorm日志发现好像这种写法的话,没执行到最后就已经 commit

query: START TRANSACTION
query: INSERT INTO `post`(`id`, `created_at`, `update_at`, `deleted_at`, `type`, `title`, `sub_title`, `description`, `uid`, `content`, `status`, `cover`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?) -- PARAMETERS: [0,"搭建 git 服务器","","",11,"1. 安装git:\n\n```cmd\n$ sudo apt-get install git\n```\n\n> [CentOS安装最新版git](https://my.oschina.net/antsky/blog/514586)\n\n2. 创建一个git用户,用来运行git服务:\n\n```cmd\n$ sudo adduser git\n```\n3. 创建证书登录:\n\n  收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。\n\n4. 初始化Git仓库:\n\n  先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:\n\n```cmd\n$ sudo git init --bare sample.git\n```\n  Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:\n\n```cmd\n$ sudo chown -R git:git sample.git\n```\n5. 禁用shell登录:\n\n  出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:\n\n```\ngit:x:1001:1001:,,,:/home/git:/bin/bash\n```\n\n  改为:\n```\ngit:x:1001:1001:,,,:/home/git:/usr/bin/git-shell\n```\n\n  这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。\n\n6. 克隆远程仓库:\n\n  现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:\n\n```cmd\n$ git clone git@server:/srv/sample.git\nCloning into 'sample'...\nwarning: You appear to have cloned an empty repository.\n```\n\n### 管理公钥\n如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里就是可行的。\n\n### 来源\n- [廖雪峰的官方网站](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137583770360579bc4b458f044ce7afed3df579123eca000)\n",1,"https://images.unsplash.com/photo-1547981607-6ea66fe762b4?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=900&h=600&fit=crop&ixid=eyJhcHBfaWQiOjF9"]
query: SELECT `PostEntity`.`id` AS `PostEntity_id`, `PostEntity`.`created_at` AS `PostEntity_created_at`, `PostEntity`.`update_at` AS `PostEntity_update_at`, `PostEntity`.`type` AS `PostEntity_type` FROM `post` `PostEntity` WHERE `PostEntity`.`id` = ? -- PARAMETERS: [18]
query: SELECT `CateEntity`.`id` AS `CateEntity_id`, `CateEntity`.`created_at` AS `CateEntity_created_at`, `CateEntity`.`update_at` AS `CateEntity_update_at`, `CateEntity`.`deleted_at` AS `CateEntity_deleted_at`, `CateEntity`.`name` AS `CateEntity_name`, `CateEntity`.`pid` AS `CateEntity_pid`, `CateEntity`.`cover` AS `CateEntity_cover`, `CateEntity`.`description` AS `CateEntity_description` FROM `cate` `CateEntity` WHERE `CateEntity`.`id` IN (?) LIMIT 1 -- PARAMETERS: [2]
query: SELECT `CateEntity`.`id` AS `CateEntity_id`, `CateEntity`.`created_at` AS `CateEntity_created_at`, `CateEntity`.`update_at` AS `CateEntity_update_at`, `CateEntity`.`deleted_at` AS `CateEntity_deleted_at`, `CateEntity`.`name` AS `CateEntity_name`, `CateEntity`.`pid` AS `CateEntity_pid`, `CateEntity`.`cover` AS `CateEntity_cover`, `CateEntity`.`description` AS `CateEntity_description` FROM `cate` `CateEntity` WHERE `CateEntity`.`id` IN (?) LIMIT 1 -- PARAMETERS: [3]
query: START TRANSACTION
query: START TRANSACTION
query: INSERT INTO `cate_relation`(`id`, `created_at`, `update_at`, `deleted_at`, `cid`, `compose_id`, `compose_type`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?) -- PARAMETERS: [2,18,1]
query: INSERT INTO `cate_relation`(`id`, `created_at`, `update_at`, `deleted_at`, `cid`, `compose_id`, `compose_type`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?) -- PARAMETERS: [3,18,1]
query: SELECT `CateRelationEntity`.`id` AS `CateRelationEntity_id`, `CateRelationEntity`.`created_at` AS `CateRelationEntity_created_at`, `CateRelationEntity`.`update_at` AS `CateRelationEntity_update_at` FROM `cate_relation` `CateRelationEntity` WHERE `CateRelationEntity`.`id` = ? -- PARAMETERS: [20]
query: SELECT `CateRelationEntity`.`id` AS `CateRelationEntity_id`, `CateRelationEntity`.`created_at` AS `CateRelationEntity_created_at`, `CateRelationEntity`.`update_at` AS `CateRelationEntity_update_at` FROM `cate_relation` `CateRelationEntity` WHERE `CateRelationEntity`.`id` = ? -- PARAMETERS: [21]
query: COMMIT
query: COMMIT
query: SELECT `TagEntity`.`id` AS `TagEntity_id`, `TagEntity`.`created_at` AS `TagEntity_created_at`, `TagEntity`.`update_at` AS `TagEntity_update_at`, `TagEntity`.`deleted_at` AS `TagEntity_deleted_at`, `TagEntity`.`name` AS `TagEntity_name`, `TagEntity`.`pid` AS `TagEntity_pid`, `TagEntity`.`color` AS `TagEntity_color`, `TagEntity`.`description` AS `TagEntity_description` FROM `tag` `TagEntity` WHERE `TagEntity`.`name` = ? LIMIT 1 -- PARAMETERS: ["git"]
query: START TRANSACTION
query: INSERT INTO `tag_relation`(`id`, `created_at`, `update_at`, `deleted_at`, `tag_id`, `compose_id`, `compose_type`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?) -- PARAMETERS: [7,18,1]
query: SELECT `TagRelationEntity`.`id` AS `TagRelationEntity_id`, `TagRelationEntity`.`created_at` AS `TagRelationEntity_created_at`, `TagRelationEntity`.`update_at` AS `TagRelationEntity_update_at` FROM `tag_relation` `TagRelationEntity` WHERE `TagRelationEntity`.`id` = ? -- PARAMETERS: [5]
query: COMMIT
query: COMMIT

是不是我哪个地方的理解有问题?

from nestjs-learning.

silent-tan avatar silent-tan commented on May 23, 2024

哦,我可能知道为什么提前commit了,是不是只能通过调用manager方法去进行事务的原因....

from nestjs-learning.

silent-tan avatar silent-tan commented on May 23, 2024

更改后就正常了

query: START TRANSACTION
query: INSERT INTO `post`(`id`, `created_at`, `update_at`, `deleted_at`, `type`, `title`, `sub_title`, `description`, `uid`, `content`, `status`, `cover`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?) -- PARAMETERS: [0,"搭建 git 服务器2","","",11,"1. 安装git:\n\n```cmd\n$ sudo apt-get install git\n```\n\n> [CentOS安装最新版git](https://my.oschina.net/antsky/blog/514586)\n\n2. 创建一个git用户,用来运行git服务:\n\n```cmd\n$ sudo adduser git\n```\n3. 创建证书登录:\n\n  收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。\n\n4. 初始化Git仓库:\n\n  先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:\n\n```cmd\n$ sudo git init --bare sample.git\n```\n  Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:\n\n```cmd\n$ sudo chown -R git:git sample.git\n```\n5. 禁用shell登录:\n\n  出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:\n\n```\ngit:x:1001:1001:,,,:/home/git:/bin/bash\n```\n\n  改为:\n```\ngit:x:1001:1001:,,,:/home/git:/usr/bin/git-shell\n```\n\n  这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。\n\n6. 克隆远程仓库:\n\n  现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:\n\n```cmd\n$ git clone git@server:/srv/sample.git\nCloning into 'sample'...\nwarning: You appear to have cloned an empty repository.\n```\n\n### 管理公钥\n如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里就是可行的。\n\n### 来源\n- [廖雪峰的官方网站](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137583770360579bc4b458f044ce7afed3df579123eca000)\n",1,"https://images.unsplash.com/photo-1547981607-6ea66fe762b4?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=900&h=600&fit=crop&ixid=eyJhcHBfaWQiOjF9"]
query: SELECT `PostEntity`.`id` AS `PostEntity_id`, `PostEntity`.`created_at` AS `PostEntity_created_at`, `PostEntity`.`update_at` AS `PostEntity_update_at`, `PostEntity`.`type` AS `PostEntity_type` FROM `post` `PostEntity` WHERE `PostEntity`.`id` = ? -- PARAMETERS: [19]
query: SELECT `CateEntity`.`id` AS `CateEntity_id`, `CateEntity`.`created_at` AS `CateEntity_created_at`, `CateEntity`.`update_at` AS `CateEntity_update_at`, `CateEntity`.`deleted_at` AS `CateEntity_deleted_at`, `CateEntity`.`name` AS `CateEntity_name`, `CateEntity`.`pid` AS `CateEntity_pid`, `CateEntity`.`cover` AS `CateEntity_cover`, `CateEntity`.`description` AS `CateEntity_description` FROM `cate` `CateEntity` WHERE `CateEntity`.`id` IN (?) LIMIT 1 -- PARAMETERS: [2]
query: SELECT `CateEntity`.`id` AS `CateEntity_id`, `CateEntity`.`created_at` AS `CateEntity_created_at`, `CateEntity`.`update_at` AS `CateEntity_update_at`, `CateEntity`.`deleted_at` AS `CateEntity_deleted_at`, `CateEntity`.`name` AS `CateEntity_name`, `CateEntity`.`pid` AS `CateEntity_pid`, `CateEntity`.`cover` AS `CateEntity_cover`, `CateEntity`.`description` AS `CateEntity_description` FROM `cate` `CateEntity` WHERE `CateEntity`.`id` IN (?) LIMIT 1 -- PARAMETERS: [3]
query: INSERT INTO `cate_relation`(`id`, `created_at`, `update_at`, `deleted_at`, `cid`, `compose_id`, `compose_type`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?) -- PARAMETERS: [2,19,1]
query: INSERT INTO `cate_relation`(`id`, `created_at`, `update_at`, `deleted_at`, `cid`, `compose_id`, `compose_type`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?) -- PARAMETERS: [3,19,1]
query: SELECT `CateRelationEntity`.`id` AS `CateRelationEntity_id`, `CateRelationEntity`.`created_at` AS `CateRelationEntity_created_at`, `CateRelationEntity`.`update_at` AS `CateRelationEntity_update_at` FROM `cate_relation` `CateRelationEntity` WHERE `CateRelationEntity`.`id` = ? -- PARAMETERS: [22]
query: SELECT `CateRelationEntity`.`id` AS `CateRelationEntity_id`, `CateRelationEntity`.`created_at` AS `CateRelationEntity_created_at`, `CateRelationEntity`.`update_at` AS `CateRelationEntity_update_at` FROM `cate_relation` `CateRelationEntity` WHERE `CateRelationEntity`.`id` = ? -- PARAMETERS: [23]
query: SELECT `TagEntity`.`id` AS `TagEntity_id`, `TagEntity`.`created_at` AS `TagEntity_created_at`, `TagEntity`.`update_at` AS `TagEntity_update_at`, `TagEntity`.`deleted_at` AS `TagEntity_deleted_at`, `TagEntity`.`name` AS `TagEntity_name`, `TagEntity`.`pid` AS `TagEntity_pid`, `TagEntity`.`color` AS `TagEntity_color`, `TagEntity`.`description` AS `TagEntity_description` FROM `tag` `TagEntity` WHERE `TagEntity`.`name` = ? LIMIT 1 -- PARAMETERS: ["git"]
query: INSERT INTO `tag_relation`(`id`, `created_at`, `update_at`, `deleted_at`, `tag_id`, `compose_id`, `compose_type`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, ?, ?, ?) -- PARAMETERS: [7,19,1]
query: SELECT `TagRelationEntity`.`id` AS `TagRelationEntity_id`, `TagRelationEntity`.`created_at` AS `TagRelationEntity_created_at`, `TagRelationEntity`.`update_at` AS `TagRelationEntity_update_at` FROM `tag_relation` `TagRelationEntity` WHERE `TagRelationEntity`.`id` = ? -- PARAMETERS: [6]
query: COMMIT

from nestjs-learning.

silent-tan avatar silent-tan commented on May 23, 2024

更改后的函数:

async create(createPostDto: CreatePostDto): Promise<PostEntity> {
    return await getManager().transaction(async manager => {
      const defaultCover = `https://images.unsplash.com/
      photo-1546623235-23f145a669ef?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=900&h=600&fit=crop&ixid=eyJhcHBfaWQiOjF9`;
      const postDto: PostDto = {
        title: createPostDto.title,
        uid: createPostDto.uid,
        content: createPostDto.content,
        type: createPostDto.type,
        status: createPostDto.status,
        cover: createPostDto.cover || defaultCover,
        subTitle: createPostDto.subTitle || '',
        description: createPostDto.description || '',
      };
      // 保存文章
      const post = await manager.save<PostEntity>(
        manager.create<PostEntity>(PostEntity, postDto),
      );
      const postId = post.id;

      // ------ 文章分类表
      const cids = createPostDto.cids || [];
      if (cids.length === 0) {
        // 默认未分类
        await manager.save<CateRelationEntity>(
          manager.create<CateRelationEntity>(
            CateRelationEntity,
            {
              cid: 14, // 未分类,
              composeId: postId,
              composeType: SourceType.POST,
            },
          ),
        );
      } else {
        const cates = await Promise.all(
          _map(cids, cid => {
            return this.cateService.findOne(cid);
          }),
        );
        // 过滤不存在的分类
        const existCates = _filter(cates, item => !_isUndefined(item));
        // 批量插入分类文章映射
        // TODO 待优化
        const cateRaltions = await Promise.all(
          _map(existCates, cate => {
            return manager.save<CateRelationEntity>(
              manager.create<CateRelationEntity>(CateRelationEntity, {
                cid: cate.id,
                composeId: postId,
                composeType: SourceType.POST,
              }),
            );
          }),
        );
      }

      // -------- 文章标签表
      const tagsName = createPostDto.tags || [];
      if (tagsName.length) {
        // 检测tag是否存在
        const tags = await Promise.all(
          _map(tagsName, t => {
            return this.tagService.findByName(t);
          }),
        );
        // 需要新增的tag
        const newTags = [];
        const newTagIndex = [];
        const existTags: TagEntity[] = [...tags];
        _forEach(tags, (tag, index) => {
          if (_isUndefined(tag)) { // 为空即是不存在
            newTags.push(tagsName[index]);
            newTagIndex.push(index);
          }
        });
        // 新增加的tag
        const createTags = await Promise.all(
          _map(newTags, t => {
            return manager.save<TagEntity>(
              manager.create<TagEntity>(TagEntity, {
                name: t,
              }),
            );
          }),
        );

        // 组合获取文章的标签详情数组
        _forEach(createTags, (value, index) => {
          const existIndex = newTagIndex[index];
          existTags[existIndex] = value;
        });

        // 批量插入标签文章映射
        // TODO 待优化
        await Promise.all(
          _map(existTags, et => {
            return manager.save<TagRelationEntity>(
              manager.create<TagRelationEntity>(TagRelationEntity, {
                tagId: et.id,
                composeId: postId,
                composeType: SourceType.POST,
              }),
            );
          }),
        );
      }
      return post;
    });
}

from nestjs-learning.

dzzzzzy avatar dzzzzzy commented on May 23, 2024

getManager().transaction() 此方法会自动回滚

要自己控制事物可以用如下方式:

// 获取连接生成 query runner
const queryRunner = getConnection().createQueryRunner();
// 开启事务
await queryRunner.startTransaction();
try {
    const user = await queryRunner.manager.findOne(User, { id: userId });
    user.nickname = 'new_nickname';

    const article = await queryRunner.manager.findOne(Article, { id: articleId });
    article.title = 'new_title';

    // 保存 user 数据
    await queryRunner.manager.save(user);

    // 保存 article 数据
    await queryRunner.manager.save(article);

    // 提交事物
    await queryRunner.commitTransaction();
} catch (error) {
    // 回滚
    await queryRunner.rollbackTransaction();
} finally {
    // 释放连接
    await queryRunner.release();
}

from nestjs-learning.

silent-tan avatar silent-tan commented on May 23, 2024

OK

from nestjs-learning.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.