我正在使用 MySQL 开发 Nodejs。我需要在将数据插入多个表时实现事务管理。这样,如果发生任何错误,我可以“回滚”所有插入。 所有与DB相关的操作都在DB层每个实体的不同类中声明。在单个操作的业务逻辑层中,我们可能需要处理来自不同实体的多个数据库层调用。在JAVA Spring中我们可以简单地在服务层进行
annotate@Transaction。 nodejs中有类似的东西吗?
创建数据库连接
connect
beginTransaction
开始交易
执行事务查询rollback
commit
end
const mysql = require('mysql');
const connection = mysql.createConnection(
{
host : 'YOUR_HOST',
user : 'YOUR_USERNAME',
password : 'YOUR_PASSWORD',
database : 'YOUR_DB_NAME'
}
);
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
/* Begin transaction */
connection.beginTransaction(function(err) {
if (err) { throw err; }
connection.query('YOUR QUERY', "PLACE HOLDER VALUES", function(err, result) {
if (err) {
connection.rollback(function() {
throw err;
});
}
const log = result.insertId;
connection.query('ANOTHER QUERY PART OF TRANSACTION', log, function(err, result) {
if (err) {
connection.rollback(function() {
throw err;
});
}
connection.commit(function(err) {
if (err) {
connection.rollback(function() {
throw err;
});
}
console.log('Transaction Completed Successfully.');
connection.end();
});
});
});
});
/* End transaction */
如果你想让它更有活力,这只是一个想法。我在代码中添加了一些注释。您可能需要更改代码以满足您的要求。 基本上,您传递一组查询以及查询值,然后所有这些查询都在事务中运行。 -
function executeTransaction(queries) {
try {
const connection = yield getConnectionObj({/* your db params to get connection */)
let results = []
return new Promise(function(resolve, reject) {
connection.beginTransaction(function (err) {
if (err) throw err
console.log("Starting transaction")
queries
.reduce(function (sequence, queryToRun) {
return sequence.then(function () {
/* pass your query and connection to a helper function and execute query there */
return queryConnection(
connection,
query,
queryParams,
).then(function (res) {
/* Accumulate resposes of all queries */
results = results.concat(res)
})
}).catch(function (error) {
reject(error)
})
}, Promise.resolve())
.then(function () {
connection.commit(function (err) {
if (err) {
connection.rollback(function () {
throw err
})
}
console.log('Transactions were completed!')
/* release connection */
connection.release()
/* resolve promise with all results */
resolve({ results })
})
})
.catch(function (err) {
console.log('Transaction failed!')
connection.rollback(function () {
console.log('Abort Transaction !!!')
throw err
})
})
})
})
/* End Transaction */
} catch (error) {
return Promise.reject(error)
}
}
我希望这有帮助。
sequelize
和
zb-sequelize
。
Sequelize 是一个充当驱动程序的层,用于连接到许多不同的基于 SQL 的数据库。@Transactional
装饰器。
import { Transactional, Tx } from 'zb-sequelize';
@Transactional
function fooBar(@Tx transaction) {
foo(transaction);
bar(transaction);
}
如果您以前使用过 Spring,那么这肯定看起来很熟悉。
// Class object injection
@Component()
export class A {
}
@Component()
export class B {
@Autowired()
protected a: A;
}
// Configuration property injection
@Component()
export class C {
@Value('foo') // Support EL expression syntax, such as @Value('obj.xxx'), @Value('arr[1]') etc.
protected foo: string;
}
数据库操作
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 remove(@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);
}
}