smartprix / xorm

NodeJS ORM based on ObjectionJS with some extra utilities
18 stars 4 forks source link

transactions | question #2

Open seeden opened 7 years ago

seeden commented 7 years ago

Hi I am thinking about your library because I want to switch from bookshelfjs to objectionsjs. Currently I am using transactions and DataLoader as well. Can you describe how are you using your library with transactions? Are you extending all models for each request?

Thank you for response.

seeden commented 6 years ago

thanks with unstar

rohit-gohri commented 6 years ago

Hi @seeden Sorry for closing your issue without answering your query. We haven't extended transaction like we have the Model class. It's exported as is.

We are using transactions just like in objection, by passing the Model Class to the transaction function and using the extended Model. The main problems we faced using it was in using any functions from the extended Model, when the function starts a query by importing any other model then that query will not be a part of the transaction. Example:

A.js:

import {Model} from 'xorm';

class A extends Model {
.
.
.
}

B.js

import {Model} from 'xorm';
import A from './A'

class B extends Model {
.
.
.
  async getRelatedAs() {
    return A.query().where('bType', this.type);
  }
}

transaction.js

import {transaction} from 'xorm';
import B from './B';

async function doTransaction() {
  return transaction(B, async (transactionB, trx) => {
    const b = await transactionB.where(id, 'xyz'); // will be part of transaction
    const a = await b.getRelatedAs(); // will not be part of transaction as doesn't use transaction object
    return a;
  }
}

To counter this use this.query() in static functions instead of ModelClass.query(). Because that will also be out of the transaction, even if using the same model.

And when querying other models, either pass the trx variable to them and use that. Or in static functions you can use some thing like :

in B.js:

static async getRelatedAs(type) {
  return this.query().from('A').where('bType', id);
}

Another problem was that an instance of the extended transaction class when returned from the transaction will no longer be an instance but a simple object, so you'll have to do ModelClass.fromJson(returnedItem);

We are still figuring out how best to use transactions, if you have any other use cases or suggestions we'd be glad to discuss them.