--安装模块
npm install mssql --连接数据库模块 ,基本封装看这里:http://blog.csdn.net/zzwwjjdj1/article/details/51911270
npm install async --异步流程控制模块 ,async模块介绍:http://blog.csdn.net/zzwwjjdj1/article/details/51857959
--创建测试数据库和表
数据库 : nodetest,表 : test
--封装代码
dbTransaction.js:
/*
nodejs连接sqlserver数据库支持事物封装
2016年7月22日15:46:22
QQ : 452076103 意外金喜
*/
var dbTransaction = {};
var sql = require('mssql');
var config = {
user: 'sa',
password: '123456',
server: '10.81.36.167',
database: 'nodetest',
port:1433,
options: {
encrypt: true // Use this if you're on Windows Azure
},
pool: {
min: 0,
max: 10,
idleTimeoutMillis: 3000
}
};
dbTransaction.getTransaction = function(callback){
var connection = new sql.Connection(config, function (err) {
var transaction = new sql.Transaction(connection);
callback(sql, transaction);
})
};
module.exports = dbTransaction;
--测试-sql语句错误
错误位置:
age是int类型的,故意写成string
testTransaction.js
/*
测试连接sqlserver的事物机制
2016年7月22日15:51:52
*/
var async = require('async');
var dbTransaction = require('./dbTransaction.js');
dbTransaction.getTransaction(function(sql, transaction){
//开启事物
transaction.begin(function(err) {
if (err) {
console.log(err);
return;
}
//定义一个变量,如果自动回滚,则监听回滚事件并修改为true,无须手动回滚
var rolledBack = false;
//监听回滚事件
transaction.on('rollback', function(aborted) {
console.log('监听回滚');
console.log('aborted值 :', aborted);
rolledBack = true;
});
//监听提交事件
transaction.on('commit', function() {
console.log('监听提交');
rolledBack = true;
});
var request = new sql.Request(transaction);
var task1 = function(callback){
request.query("insert into test (name, age) values ('a1', 20)", function(err, result) {
if (err) {
console.log(err);
callback(err, null);
return;
}
console.log('第一条语句成功');
callback(null, result)
})
};
var task2 = function(callback){
request.query("insert into test (name, age) values ('a2', 22)", function(err, result) {
if (err) {
console.log(err);
callback(err, null);
return;
}
console.log('第二条语句成功');
callback(null, result)
})
};
var task3 = function(callback){
request.query("insert into test (name, age) values ('a3', 'a')", function(err, result) {
if (err) {
console.log(err);
callback(err, null);
return;
}
console.log('第三条语句成功');
callback(null, result)
})
}
async.series([task1, task2, task3],function(err,result){
var err = "11";
if (err) {
console.log('出现错误,执行回滚');
if (!rolledBack) {
//如果sql语句错误会自动回滚,如果程序错误手动执行回滚,不然事物会一致挂起.
transaction.rollback(function(err) {
if (err) {
console.log('rollback err :',err);
return;
}
console.log('回滚成功');
});
}
} else {
console.log('无错误,执行提交');
//执行提交
transaction.commit(function(err) {
if (err) {
console.log('commit err :',err);
return;
}
console.log('提交成功');
});
}
})
});
})
这个测试就是向test表插入3条数据,按照预期,如果这个过程出现任何错误,3条数据都不会插入成功.
看看是不是这样的
数据库
总结:sql错误,并没有触发我们写的回滚事件,但程序监听到了回滚事件,数据库插入失败,这是因为mssql模块自己写了回滚.
--测试-非sql语句错误
也就是程序错误
错误位置:
testTransaction.js
/*
测试连接sqlserver的事物机制
2016年7月22日15:51:52
*/
var async = require('async');
var dbTransaction = require('./dbTransaction.js');
dbTransaction.getTransaction(function(sql, transaction){
//开启事物
transaction.begin(function(err) {
if (err) {
console.log(err);
return;
}
//定义一个变量,如果自动回滚,则监听回滚事件并修改为true,无须手动回滚
var rolledBack = false;
//监听回滚事件
transaction.on('rollback', function(aborted) {
console.log('监听回滚');
console.log('aborted值 :', aborted);
rolledBack = true;
});
//监听提交事件
transaction.on('commit', function() {
console.log('监听提交');
rolledBack = true;
});
var request = new sql.Request(transaction);
var task1 = function(callback){
request.query("insert into test (name, age) values ('a1', 20)", function(err, result) {
if (err) {
console.log(err);
callback(err, null);
return;
}
console.log('第一条语句成功');
callback(null, result)
})
};
var task2 = function(callback){
request.query("insert into test (name, age) values ('a2', 22)", function(err, result) {
if (err) {
console.log(err);
callback(err, null);
return;
}
console.log('第二条语句成功');
callback(null, result)
})
};
var task3 = function(callback){
request.query("insert into test (name, age) values ('a3', 24)", function(err, result) {
if (err) {
console.log(err);
callback(err, null);
return;
}
console.log('第三条语句成功');
callback(null, result)
})
}
async.series([task1, task2, task3],function(err,result){
var err = "11";
if (err) {
console.log('出现错误,执行回滚');
if (!rolledBack) {
//如果sql语句错误会自动回滚,如果程序错误手动执行回滚,不然事物会一致挂起.
transaction.rollback(function(err) {
if (err) {
console.log('rollback err :',err);
return;
}
console.log('回滚成功');
});
}
} else {
console.log('无错误,执行提交');
//执行提交
transaction.commit(function(err) {
if (err) {
console.log('commit err :',err);
return;
}
console.log('提交成功');
});
}
})
});
})
执行结果:
数据库也为空,就不截图了.
总结:非sql错误,也就是程序错误,执行了我们写的回滚事件,程序监听到了回滚事件,数据库插入失败
--测试-无错误
无错误的情况,当然是皆大欢喜,程序不报错,数据插入成功.
去掉我们添加的错误,执行
数据库:
终于成功了.......
最后说下,从begin方法开始,所有的程序错误都要手动处理,如果发生错误,而又没处理到,是不会回滚的.