【问题标题】:"ConnectionNotFoundError: Connection "default" was not found" - class attribute“ConnectionNotFoundError:未找到连接“默认”” - 类属性
【发布时间】:2022-03-17 01:06:54
【问题描述】:

我正在学习 NodeJS,任务是构建一个简单的消息传递服务。老师使用的是 SQLite3,但我决定使用 Postgres,因为它是我们公司项目中使用的数据库。

错误:“ConnectionNotFoundError:未找到连接“默认””

// server.ts

import 'reflect-metadata';
import express from 'express';
import { createConnection } from 'typeorm';

import router from './router';

(async () => {
  const PORT = 3333;

  console.log('before');
  await createConnection();
  console.log('after');

  const app = express();

  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));

  app.use(router);

  app.listen(PORT, () => {
    console.log(`App is running on port ${PORT}`);
  });
})();

我有以下MessagesService

// this works just fine
class MessagesService {
  async create({ user_id, text, admin_id }: MessagesCreateInterface): Promise<Message> {
    const repository = getCustomRepository(MessagesRepository);

    const message = repository.create({
      admin_id,
      text,
      user_id,
    });

    await repository.save(message);

    return message;
  }


  async listByUser(user_id: string): Promise<Array<Message>> {
    const repository = getCustomRepository(MessagesRepository);
    const messages = await repository.find({ user_id });
    return messages;
  }
}

由于getCustomRepository在两个函数中都被调用,并尝试将其转换为类属性:

class MessagesService {
  repository: MessagesRepository;

  constructor() {
    console.log('constructor');
    this.repository = getCustomRepository(MessagesRepository);
  }
  ...
}

然后我得到ConnectionNotFoundError: Connection "default" was not found.。

实验

  1. 在constructor 内使用setTimeout:访问连接。

  2. Consoles.log:我得到“之前”和“构造函数”打印,但没有“之后”。

有人可以帮助我了解发生了什么吗?由于我使用的是 async/await,所以在建立连接之前不应调用 MessageService。我在这里打破了一些模式吗?

【问题讨论】:

    标签: node.js typescript typeorm


    【解决方案1】:

    问题是router.js 是在createConnection 被server.ts 调用之前被导入的。

    由于控制器是在 router.js 内部实例化的,除了服务和存储库之外,它们确实在创建数据库连接之前尝试访问它。

    我找到的解决方案是在建立连接后延迟导入router.js,但我不确定这是否是反模式。

    // server.ts
    
    import 'reflect-metadata';
    import express from 'express';
    import { createConnection } from 'typeorm';
    
    (async () => {
      await createConnection();
      // Importing routes after connection has been established
      const router = (await import('./router').default);
      const PORT = 3333;
    
      const app = express();
    
      app.use(express.json());
      app.use(express.urlencoded({ extended: true }));
    
      app.use(router);
    
      app.listen(PORT, () => {
        console.log(`App is running on port ${PORT}`);
      });
    })();
    

    讲座中建议的方法是在每条路由中创建一个控制器实例,但对我来说似乎不合适。

    router.js
    
    // suggested way
    router.post('/messages', (request, response) => {
      const messagesController = new MessagesController();
      return messagesController.create(request, response); 
    });
    
    router.get('/messages/:id', (request, response) => {
      const messagesController = new MessagesController();
      return messagesController.showByUser(request, response); 
    });
    

    由于我还在学习 NodeJS,请随时纠正我并指出正确的方法。

    【讨论】:

      【解决方案2】:

      您没有将连接选项传递给 TypeORM,因此它不知道如何连接和设置连接(这是 默认的)。

      不带参数调用await createConnection() 将从文件中加载连接选项,并且(据我所知)您没有任何ormconfig.X 文件。

      要将连接选项传递给 TypeORM,您有三个选项:

      1. 连接选项对象
        见https://typeorm.io/#/connection。
        调用 createConnection({ ... }) 时直接传递连接选项(对象)。
        示例:
      const connection = await createConnection({
          type: "postgres",
          host: "localhost",
          port: 5432,
          username: "test",
          password: "test",
          database: "test"
      });
      
      1. ormconfig.X 文件
        见https://typeorm.io/#/using-ormconfig。
        在项目根目录中加载 ormconfig.[extension] 文件。
        支持的 ormconfig 文件扩展名有:.json、.js、.ts、.env、.yml 和 .xml。
        示例(ormconfig.json):
      {
         "type": "postgres",
         "host": "localhost",
         "port": 5432,
         "username": "test",
         "password": "test",
         "database": "test"
      }
      
      1. 环境变量
        见https://typeorm.io/#/using-ormconfig/using-environment-variables。
        TypeORM 自动在环境变量或项目根目录中的 .env 或 ormconfig.env 中搜索连接选项(靠近 package.json)。
        示例:
      TYPEORM_CONNECTION = postgres
      TYPEORM_HOST = localhost
      TYPEORM_PORT = 5432
      TYPEORM_USERNAME = test
      TYPEORM_PASSWORD = test
      TYPEORM_DATABASE = test
      

      【讨论】:

      • 你好卡洛,谢谢你的回答。我有一个 ormconfig.json 并且连接工作正常。我只在尝试在类构造函数中访问它时收到此错误。
      • 我建议typeorm-typedi-extensions。只需在您的班级中使用@InjectRepository。很简单:)
      • 好的,我去看看!
      【解决方案3】:

      我知道该问题已被标记为已回答,但我最近遇到了类似的问题(与使用 mocha 进行单元测试有关)。就我而言,解决方案是存根 typeorm getCustomRepository:

      import sinon from 'sinon';
      import * as typeorm from 'typeorm';
      import {Connection, ConnectionManager} from 'typeorm';
      
      describe('groupService', () => {
      
          let getCustomRepositoryStub;
      
          beforeEach(() => {
              getCustomRepositoryStub = sinon.stub(typeorm, 'getCustomRepository');
              sinon.stub(ConnectionManager.prototype, 'get').returns({getCustomRepository: getCustomRepositoryStub} as  Connection);
          });
      
          afterEach(() => {
              sinon.restore();
          });
      
          it('findById returns empty result', async() => {
              const groupId: string = 'mock-group-id';
              getCustomRepositoryStub.withArgs(GroupRepository)
                  .returns({
                      findById: () => Promise.resolve([])
                  });
              const groups = await groupService.getGroup(groupId);
              expect(groups.length).equal(0);
          });
      
          ...
      
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-19
        • 2020-02-13
        • 2020-12-03
        • 2018-09-22
        • 2013-10-17
        • 2019-09-08
        • 1970-01-01
        • 2010-11-19
        相关资源
        最近更新 更多