【问题标题】:Sequelize: Create two referenced Rows in same TransactionSequelize:在同一个事务中创建两个引用的行
【发布时间】:2022-02-04 05:41:56
【问题描述】:

我想创建两行。

首先我想创建一个tenant,然后我想创建一个引用tenantuser

我想在一个事务中完成此操作(注册)。

tenant 将被创建,但是当 sequelize 尝试创建用户时,我得到一个错误:

Failing row contains

例程:ExecConstraints

我的数据库映射:

const TenantMapping = sequelize.define('tenant', {
    id: { type: DataTypes.NUMBER, primaryKey: true, autoIncrement: true },
    label: { type: DataTypes.STRING, allowNull: false },
    name: { type: DataTypes.STRING },
    postOfficeBox: { type: DataTypes.STRING },
    street: { type: DataTypes.STRING },
    houseNo: { type: DataTypes.STRING },
    zipCode: { type: DataTypes.STRING, validate: { max: 10 } },
    city: { type: DataTypes.STRING },
    phone: { type: DataTypes.STRING },
    mobilePhone: { type: DataTypes.STRING },
    email: { type: DataTypes.STRING, allowNull: false },
    website: { type: DataTypes.STRING },
    birth: { type: DataTypes.DATE, allowNull: false },
    death: { type: DataTypes.DATE }
}, {
    ...getSequelizeTableSettings({ schema: 'auth' })
});

const UserMapping = sequelize.define('user', {
    id: { type: DataTypes.NUMBER, primaryKey: true, autoIncrement: true },
    tenantId: { type: DataTypes.NUMBER, allowNull: false },
    email: { type: DataTypes.STRING, allowNull: false },
    password: { type: DataTypes.STRING, allowNull: false },
    role: { type: DataTypes.STRING, allowNull: false },
    isActivated: { type: DataTypes.BOOLEAN, allowNull: false },
    birth: { type: DataTypes.DATE, allowNull: false },
    death: { type: DataTypes.DATE }
}, {
    ...getSequelizeTableSettings({ schema: 'auth' })
});

我的控制器


const response = await sequelize.transaction(async (transaction) => {
            try {
                const { tenantLabel, email, password } = req.body;
                const tenant = await this.tenantRepository.create({
                    tenantLabel,
                    email
                }, {
                    transaction
                });

                const user = await this.userRepository.create({
                    email,
                    password,
                    tenantId: tenant.id,
                    role: UserRole.ADMIN
                }, {
                    transaction
                });

                await transaction.commit();
                res.status(200).json({
                    tenant,
                    user
                });
            } catch (exception) {
                res.status(400).send({
                    ...exception
                });
            }
        });

如果我在两个不同的transactions 中创建tenantuser - 它工作正常。

怎么了?

【问题讨论】:

  • 如果你使用像sequelize.transaction(async (transaction) => {这样的回调打开一个事务,那么你不需要显式调用commit
  • 你使用什么数据库?您能否添加有关该错误的更多信息?
  • 我在线程中添加了更多细节。有什么想法吗?
  • 你能显示tenantRepositoryuserRepository的代码吗?
  • 我发布了tenantRepositoryuserRepository 和父Repository

标签: node.js sequelize.js


【解决方案1】:

我用的是 PostgreSQL

{
    "name": "SequelizeDatabaseError",
    "parent": {
        "length": 257,
        "name": "error",
        "severity": "ERROR",
        "code": "23502",
        "detail": "Failing row contains (22, null, email@mail.com, null, null, f, 2022-01-22 12:07:33.899, null).",
        "schema": "auth",
        "table": "user",
        "column": "tenant_id",
        "file": "execMain.c",
        "line": "1965",
        "routine": "ExecConstraints",
        "sql": "INSERT INTO \"auth\".\"user\" (\"id\",\"email\",\"birth\") VALUES (DEFAULT,$1,$2) RETURNING \"id\",\"tenant_id\",\"email\",\"password\",\"role\",\"is_activated\",\"birth\",\"death\";",
        "parameters": [
            "email@mail.com",
            "2022-01-22 12:07:33.899 +00:00"
        ]
    },
    "original": {
        "length": 257,
        "name": "error",
        "severity": "ERROR",
        "code": "23502",
        "detail": "Failing row contains (22, null, email@mail.com, null, null, f, 2022-01-22 12:07:33.899, null).",
        "schema": "auth",
        "table": "user",
        "column": "tenant_id",
        "file": "execMain.c",
        "line": "1965",
        "routine": "ExecConstraints",
        "sql": "INSERT INTO \"auth\".\"user\" (\"id\",\"email\",\"birth\") VALUES (DEFAULT,$1,$2) RETURNING \"id\",\"tenant_id\",\"email\",\"password\",\"role\",\"is_activated\",\"birth\",\"death\";",
        "parameters": [
            "email@mail.com",
            "2022-01-22 12:07:33.899 +00:00"
        ]
    },
    "sql": "INSERT INTO \"auth\".\"user\" (\"id\",\"email\",\"birth\") VALUES (DEFAULT,$1,$2) RETURNING \"id\",\"tenant_id\",\"email\",\"password\",\"role\",\"is_activated\",\"birth\",\"death\";",
    "parameters": [
        "email@mail.com",
        "2022-01-22 12:07:33.899 +00:00"
    ]
}

我记录了我的object 我想创建一个新行,然后再尝试使用 sequelize 创建。

console.log('create new something', JSON.stringify(object));
const response = await this.sequelize.create(object, transaction);

在控制台我有这个:

create new something {"email":"email@mail.com","password":"$2b$04$2vDzrLah9FjhxG.nlIJjluByE28O6bjyIr4s7LXqoFgGwyjHODJMG","role":"ADMIN","tenantId":22,"isActivated":false}

没错。但是请查看错误消息。 Sequelize 尝试仅使用电子邮件创建新用户 - 没有密码、没有角色、没有tenantId、没有 isActivated...

【讨论】:

    【解决方案2】:

    租户存储库:

    export class TenantRepository extends Repository<TenantResource> {
    
        constructor() {
            super(DB_MAPPINGS.TenantMapping, { identifier: 'id' });
        }
    
        public async create(
            { tenantLabel, email }: { tenantLabel: string; email: string; },
            { transaction }: { transaction: Transaction }
        ): Promise<TenantResource> {
            return await this.CREATE({
                    label: tenantLabel,
                    email
                },
                {
                    transaction
                }
            );
        }
    }
    

    用户存储库:

    export class UserRepository extends Repository<UserResource> {
    
        constructor() {
            super(DB_MAPPINGS.UserMapping, { identifier: 'id' });
        }
    
        public async create(
            { email, password, role, tenantId }: { email: string; password: string; role: UserRole; tenantId: number; },
            { transaction }: { transaction: Transaction }
        ): Promise<UserResource> {
            return await this.CREATE({
                    email,
                    password: await this.encryptPassword({ password }),
                    role,
                    tenantId,
                    isActivated: false
                },
                {
                    transaction
                }
            );
        }
    }
    
    

    存储库:

    export class Repository<T> extends RepositoryHelper<T> {
    
        public async CREATE(
            object: Partial<T>,
            { transaction }: { transaction: Transaction }
        ): Promise<T> {
            const response = await this.sequelize.create(object, transaction);
            return response.toJSON();
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      我发现了我的问题。我必须通过transaction

      export class Repository<T> extends RepositoryHelper<T> {
      
          public async CREATE(
              object: Partial<T>,
              { transaction }: { transaction: Transaction }
          ): Promise<T> {
              const response = await this.sequelize.create(object, { transaction });
              return response.toJSON();
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2011-06-19
        • 2022-12-23
        • 1970-01-01
        • 1970-01-01
        • 2020-10-12
        • 1970-01-01
        • 2020-09-19
        • 1970-01-01
        • 2019-12-04
        相关资源
        最近更新 更多