@axiosleo/orm-mysql 0.13.2 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/orm-mysql.js +1 -1
- package/index.d.ts +14 -3
- package/package.json +1 -1
- package/src/builder.js +35 -10
- package/src/migration.js +10 -1
- package/.vscode/extensions.json +0 -14
- package/.vscode/settings.json +0 -5
- package/dist/orm-mysql +0 -0
- package/examples/base_column.js +0 -28
- package/examples/migration/.connect.js +0 -16
- package/examples/migration/1706764048.init.js +0 -108
- package/examples/transaction_example.js +0 -228
package/bin/orm-mysql.js
CHANGED
package/index.d.ts
CHANGED
|
@@ -640,9 +640,20 @@ export declare class MigrationInterface {
|
|
|
640
640
|
createForeignKey(table: string, options: {
|
|
641
641
|
foreignKey?: string,
|
|
642
642
|
columnName: string,
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
643
|
+
references?: {
|
|
644
|
+
table: string,
|
|
645
|
+
column: string,
|
|
646
|
+
onDelete?: CascadeType,
|
|
647
|
+
onUpdate?: CascadeType,
|
|
648
|
+
},
|
|
649
|
+
/** @deprecated Use `references` instead */
|
|
650
|
+
reference?: {
|
|
651
|
+
table?: string,
|
|
652
|
+
column?: string,
|
|
653
|
+
/** @deprecated Use `table` instead */
|
|
654
|
+
tableName?: string,
|
|
655
|
+
/** @deprecated Use `column` instead */
|
|
656
|
+
columnName?: string,
|
|
646
657
|
onDelete?: CascadeType,
|
|
647
658
|
onUpdate?: CascadeType,
|
|
648
659
|
}
|
package/package.json
CHANGED
package/src/builder.js
CHANGED
|
@@ -582,8 +582,17 @@ class ManageSQLBuilder extends Builder {
|
|
|
582
582
|
});
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
-
createForeignKey(options) {
|
|
585
|
+
createForeignKey(options, onCreateTable = false) {
|
|
586
|
+
if (options.reference && !options.references) {
|
|
587
|
+
options.references = options.reference;
|
|
588
|
+
}
|
|
586
589
|
if (options.references) {
|
|
590
|
+
if (options.references.tableName && !options.references.table) {
|
|
591
|
+
options.references.table = options.references.tableName;
|
|
592
|
+
}
|
|
593
|
+
if (options.references.columnName && !options.references.column) {
|
|
594
|
+
options.references.column = options.references.columnName;
|
|
595
|
+
}
|
|
587
596
|
options.references.onDelete = options.references.onDelete ? options.references.onDelete.toUpperCase() : 'NO ACTION';
|
|
588
597
|
options.references.onUpdate = options.references.onUpdate ? options.references.onUpdate.toUpperCase() : 'NO ACTION';
|
|
589
598
|
}
|
|
@@ -591,17 +600,27 @@ class ManageSQLBuilder extends Builder {
|
|
|
591
600
|
name: 'required|string',
|
|
592
601
|
table: 'required|string',
|
|
593
602
|
column: 'required|string',
|
|
594
|
-
'references.
|
|
595
|
-
'references.
|
|
603
|
+
'references.table': 'required|string',
|
|
604
|
+
'references.column': 'required|string',
|
|
596
605
|
'references.onUpdate': [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }],
|
|
597
606
|
'references.onDelete': [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }]
|
|
598
607
|
});
|
|
608
|
+
if (onCreateTable === true) {
|
|
609
|
+
return _render('CONSTRAINT `${name}` FOREIGN KEY (`${column_name}`) REFERENCES `${foreign_table}` (`${foreign_column}`) ON DELETE ${on_delete} ON UPDATE ${on_update}', {
|
|
610
|
+
name: options.name,
|
|
611
|
+
column_name: options.column,
|
|
612
|
+
foreign_table: options.references.table,
|
|
613
|
+
foreign_column: options.references.column,
|
|
614
|
+
on_delete: options.references.onDelete || 'NO ACTION',
|
|
615
|
+
on_update: options.references.onUpdate || 'NO ACTION',
|
|
616
|
+
});
|
|
617
|
+
}
|
|
599
618
|
return _render('ALTER TABLE `${table_name}` ADD CONSTRAINT `${name}` FOREIGN KEY (`${column_name}`) REFERENCES `${foreign_table}` (`${foreign_column}`) ON DELETE ${on_delete} ON UPDATE ${on_update}', {
|
|
600
|
-
table_name: options.
|
|
619
|
+
table_name: options.table,
|
|
601
620
|
name: options.name,
|
|
602
|
-
column_name: options.
|
|
603
|
-
foreign_table: options.references.
|
|
604
|
-
foreign_column: options.references.
|
|
621
|
+
column_name: options.column,
|
|
622
|
+
foreign_table: options.references.table,
|
|
623
|
+
foreign_column: options.references.column,
|
|
605
624
|
on_delete: options.references.onDelete || 'NO ACTION',
|
|
606
625
|
on_update: options.references.onUpdate || 'NO ACTION',
|
|
607
626
|
});
|
|
@@ -663,6 +682,12 @@ class ManageSQLBuilder extends Builder {
|
|
|
663
682
|
column.references = column.reference;
|
|
664
683
|
}
|
|
665
684
|
if (column.references) {
|
|
685
|
+
if (column.references.tableName && !column.references.table) {
|
|
686
|
+
column.references.table = column.references.tableName;
|
|
687
|
+
}
|
|
688
|
+
if (column.references.columnName && !column.references.column) {
|
|
689
|
+
column.references.column = column.references.columnName;
|
|
690
|
+
}
|
|
666
691
|
column.references.onDelete = column.references.onDelete ? column.references.onDelete.toUpperCase() : 'NO ACTION';
|
|
667
692
|
column.references.onUpdate = column.references.onUpdate ? column.references.onUpdate.toUpperCase() : 'NO ACTION';
|
|
668
693
|
|
|
@@ -677,8 +702,8 @@ class ManageSQLBuilder extends Builder {
|
|
|
677
702
|
table,
|
|
678
703
|
column: column.name,
|
|
679
704
|
references: {
|
|
680
|
-
|
|
681
|
-
|
|
705
|
+
table: column.references.table,
|
|
706
|
+
column: column.references.column,
|
|
682
707
|
onDelete: column.references.onDelete,
|
|
683
708
|
onUpdate: column.references.onUpdate
|
|
684
709
|
}
|
|
@@ -697,7 +722,7 @@ class ManageSQLBuilder extends Builder {
|
|
|
697
722
|
}
|
|
698
723
|
if (referenceColumns.length) {
|
|
699
724
|
referenceColumns.forEach((r) => {
|
|
700
|
-
strs.push(this.createForeignKey(r));
|
|
725
|
+
strs.push(this.createForeignKey(r, true));
|
|
701
726
|
});
|
|
702
727
|
}
|
|
703
728
|
return strs.join(', ');
|
package/src/migration.js
CHANGED
|
@@ -227,13 +227,22 @@ function _initMigration(file, queries = {}) {
|
|
|
227
227
|
|
|
228
228
|
Object.defineProperty(migration, 'createForeignKey', {
|
|
229
229
|
value: function (table, options = {}) {
|
|
230
|
+
const refs = options.references || options.reference;
|
|
231
|
+
if (refs) {
|
|
232
|
+
if (refs.tableName && !refs.table) {
|
|
233
|
+
refs.table = refs.tableName;
|
|
234
|
+
}
|
|
235
|
+
if (refs.columnName && !refs.column) {
|
|
236
|
+
refs.column = refs.columnName;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
230
239
|
_assign(options, {
|
|
231
240
|
operator: 'create',
|
|
232
241
|
target: 'foreignKey',
|
|
233
242
|
name: options.foreignKey ? options.foreignKey : 'fk_' + table + '_' + options.columnName,
|
|
234
243
|
table: table,
|
|
235
244
|
column: options.columnName,
|
|
236
|
-
references:
|
|
245
|
+
references: refs
|
|
237
246
|
});
|
|
238
247
|
const builder = new ManageSQLBuilder(options);
|
|
239
248
|
queries[file].push({ sql: builder.sql, values: builder.values });
|
package/.vscode/extensions.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"recommendations": [
|
|
3
|
-
"vscode-icons-team.vscode-icons",
|
|
4
|
-
"formulahendry.docker-extension-pack",
|
|
5
|
-
"mikestead.dotenv",
|
|
6
|
-
"dbaeumer.vscode-eslint",
|
|
7
|
-
"codezombiech.gitignore",
|
|
8
|
-
"eamodio.gitlens",
|
|
9
|
-
"esbenp.prettier-vscode",
|
|
10
|
-
"wayou.vscode-todo-highlight",
|
|
11
|
-
"octref.vetur",
|
|
12
|
-
"pflannery.vscode-versionlens"
|
|
13
|
-
]
|
|
14
|
-
}
|
package/.vscode/settings.json
DELETED
package/dist/orm-mysql
DELETED
|
Binary file
|
package/examples/base_column.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @returns {Record<string, import('@axiosleo/orm-mysql').ColumnItem>}
|
|
5
|
-
*/
|
|
6
|
-
module.exports = {
|
|
7
|
-
id: {
|
|
8
|
-
type: 'int',
|
|
9
|
-
allowNull: false,
|
|
10
|
-
primaryKey: true,
|
|
11
|
-
autoIncrement: true
|
|
12
|
-
},
|
|
13
|
-
created_at: {
|
|
14
|
-
type: 'TIMESTAMP',
|
|
15
|
-
allowNull: false,
|
|
16
|
-
default: 'CURRENT_TIMESTAMP'
|
|
17
|
-
},
|
|
18
|
-
updated_at: {
|
|
19
|
-
type: 'TIMESTAMP',
|
|
20
|
-
allowNull: false,
|
|
21
|
-
default: 'CURRENT_TIMESTAMP',
|
|
22
|
-
onUpdate: 'CURRENT_TIMESTAMP'
|
|
23
|
-
},
|
|
24
|
-
disabled_at: {
|
|
25
|
-
type: 'TIMESTAMP',
|
|
26
|
-
allowNull: true
|
|
27
|
-
}
|
|
28
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const path = require('path');
|
|
4
|
-
|
|
5
|
-
const dotenv = require('dotenv');
|
|
6
|
-
dotenv.config({
|
|
7
|
-
path: path.join(__dirname, '../../../.env')
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
host: process.env.MYSQL_HOST,
|
|
12
|
-
port: process.env.MYSQL_PORT,
|
|
13
|
-
user: process.env.MYSQL_USER,
|
|
14
|
-
password: process.env.MYSQL_PASS,
|
|
15
|
-
database: process.env.MYSQL_DB
|
|
16
|
-
};
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const baseColumn = require('../base_column');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @param {import('@axiosleo/orm-mysql').MigrationInterface} migration
|
|
7
|
-
*/
|
|
8
|
-
function up(migration) {
|
|
9
|
-
migration.createTable('orgs', {
|
|
10
|
-
...baseColumn,
|
|
11
|
-
code: {
|
|
12
|
-
type: 'varchar',
|
|
13
|
-
length: 64,
|
|
14
|
-
allowNull: false,
|
|
15
|
-
uniqIndex: true
|
|
16
|
-
},
|
|
17
|
-
name: {
|
|
18
|
-
type: 'VARCHAR',
|
|
19
|
-
allowNull: false
|
|
20
|
-
},
|
|
21
|
-
type: {
|
|
22
|
-
type: 'VARCHAR',
|
|
23
|
-
comment: '集团 group;公司 company;',
|
|
24
|
-
allowNull: false
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
migration.createTable('account', {
|
|
29
|
-
...baseColumn,
|
|
30
|
-
uuid: {
|
|
31
|
-
type: 'VARCHAR',
|
|
32
|
-
length: 36,
|
|
33
|
-
allowNull: false,
|
|
34
|
-
uniqIndex: true,
|
|
35
|
-
comment: 'uuid'
|
|
36
|
-
},
|
|
37
|
-
username: {
|
|
38
|
-
type: 'varchar',
|
|
39
|
-
length: 64,
|
|
40
|
-
allowNull: false,
|
|
41
|
-
},
|
|
42
|
-
name: {
|
|
43
|
-
type: 'VARCHAR',
|
|
44
|
-
length: 100,
|
|
45
|
-
allowNull: false,
|
|
46
|
-
comment: '姓名',
|
|
47
|
-
},
|
|
48
|
-
avatar: {
|
|
49
|
-
type: 'VARCHAR',
|
|
50
|
-
allowNull: true,
|
|
51
|
-
comment: '头像文件索引'
|
|
52
|
-
},
|
|
53
|
-
password: {
|
|
54
|
-
type: 'varchar',
|
|
55
|
-
length: 64,
|
|
56
|
-
allowNull: false
|
|
57
|
-
},
|
|
58
|
-
last_token: {
|
|
59
|
-
type: 'VARCHAR',
|
|
60
|
-
length: 36,
|
|
61
|
-
allowNull: true,
|
|
62
|
-
comment: '最后一次登录的token'
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
migration.createIndex('account', ['username asc']);
|
|
66
|
-
|
|
67
|
-
migration.createTable('account_orgs', {
|
|
68
|
-
id: baseColumn.id,
|
|
69
|
-
account_id: {
|
|
70
|
-
type: 'int',
|
|
71
|
-
allowNull: false,
|
|
72
|
-
references: {
|
|
73
|
-
table: 'account',
|
|
74
|
-
column: 'id'
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
org_id: {
|
|
78
|
-
type: 'int',
|
|
79
|
-
allowNull: false,
|
|
80
|
-
references: {
|
|
81
|
-
table: 'orgs',
|
|
82
|
-
column: 'id'
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
type: {
|
|
86
|
-
type: 'varchar',
|
|
87
|
-
length: 32,
|
|
88
|
-
allowNull: false,
|
|
89
|
-
comment: '组织创建者creator;组织管理员admin;组织用户user;',
|
|
90
|
-
default: 'user'
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
migration.createColumn('created_at', 'TIMESTAMP', 'account_orgs');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @param {import('@axiosleo/orm-mysql').MigrationInterface} migration
|
|
98
|
-
*/
|
|
99
|
-
function down(migration) {
|
|
100
|
-
migration.dropTable('account_orgs');
|
|
101
|
-
migration.dropTable('account');
|
|
102
|
-
migration.dropTable('orgs');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
module.exports = {
|
|
106
|
-
up,
|
|
107
|
-
down
|
|
108
|
-
};
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 事务使用示例
|
|
6
|
-
*
|
|
7
|
-
* 这个示例展示了如何正确使用事务,避免连接阻塞问题
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const mysql = require('mysql2/promise');
|
|
11
|
-
const { QueryHandler } = require('../src/operator');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* 示例 1: 使用连接池(推荐)
|
|
15
|
-
* 优点:自动从池中获取新连接,不会阻塞其他操作
|
|
16
|
-
*/
|
|
17
|
-
async function exampleWithPool() {
|
|
18
|
-
const pool = mysql.createPool({
|
|
19
|
-
host: 'localhost',
|
|
20
|
-
port: 3306,
|
|
21
|
-
user: 'root',
|
|
22
|
-
password: 'password',
|
|
23
|
-
database: 'test_db',
|
|
24
|
-
connectionLimit: 10
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const queryHandler = new QueryHandler(pool);
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
// 方式 1: 使用 QueryHandler.beginTransaction()(推荐)
|
|
31
|
-
// 这会自动从连接池获取一个新连接用于事务
|
|
32
|
-
const transaction = await queryHandler.beginTransaction({ level: 'RC' });
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
// 执行事务操作
|
|
36
|
-
await transaction.table('users').insert({ name: 'John', age: 30 });
|
|
37
|
-
await transaction.table('orders').insert({ user_id: 1, total: 100 });
|
|
38
|
-
|
|
39
|
-
// 提交事务(会自动释放连接回池)
|
|
40
|
-
await transaction.commit();
|
|
41
|
-
console.log('Transaction committed successfully');
|
|
42
|
-
} catch (err) {
|
|
43
|
-
// 回滚事务(会自动释放连接回池)
|
|
44
|
-
await transaction.rollback();
|
|
45
|
-
console.error('Transaction rolled back:', err.message);
|
|
46
|
-
throw err;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// 同时,其他操作不会被阻塞
|
|
50
|
-
const users = await queryHandler.table('users').select();
|
|
51
|
-
console.log('Users:', users);
|
|
52
|
-
|
|
53
|
-
} finally {
|
|
54
|
-
await pool.end();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 示例 2: 使用单一连接(不推荐用于生产环境)
|
|
60
|
-
* 注意:事务执行期间会阻塞该连接的其他操作
|
|
61
|
-
*/
|
|
62
|
-
async function exampleWithSingleConnection() {
|
|
63
|
-
const connection = await mysql.createConnection({
|
|
64
|
-
host: 'localhost',
|
|
65
|
-
port: 3306,
|
|
66
|
-
user: 'root',
|
|
67
|
-
password: 'password',
|
|
68
|
-
database: 'test_db'
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const queryHandler = new QueryHandler(connection);
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
// 使用单一连接创建事务
|
|
75
|
-
const transaction = await queryHandler.beginTransaction({ level: 'RR' });
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
await transaction.table('users').insert({ name: 'Jane', age: 25 });
|
|
79
|
-
await transaction.commit();
|
|
80
|
-
console.log('Transaction committed');
|
|
81
|
-
} catch (err) {
|
|
82
|
-
await transaction.rollback();
|
|
83
|
-
console.error('Transaction rolled back:', err);
|
|
84
|
-
throw err;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
} finally {
|
|
88
|
-
await connection.end();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* 示例 3: 直接使用 TransactionHandler
|
|
94
|
-
* 适用于需要更多控制的场景
|
|
95
|
-
*/
|
|
96
|
-
async function exampleWithTransactionHandler() {
|
|
97
|
-
const { TransactionHandler } = require('../src/transaction');
|
|
98
|
-
|
|
99
|
-
const connection = await mysql.createConnection({
|
|
100
|
-
host: 'localhost',
|
|
101
|
-
port: 3306,
|
|
102
|
-
user: 'root',
|
|
103
|
-
password: 'password',
|
|
104
|
-
database: 'test_db'
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const transaction = new TransactionHandler(connection, { level: 'SERIALIZABLE' });
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
await transaction.begin();
|
|
111
|
-
|
|
112
|
-
// 执行多个操作
|
|
113
|
-
await transaction.table('users').insert({ name: 'Bob', age: 35 });
|
|
114
|
-
await transaction.table('user_profiles').insert({ user_id: 1, bio: 'Developer' });
|
|
115
|
-
|
|
116
|
-
// 使用锁
|
|
117
|
-
const lockedRows = await transaction.table('products')
|
|
118
|
-
.where('id', [1, 2, 3], 'IN')
|
|
119
|
-
.append('FOR UPDATE')
|
|
120
|
-
.select();
|
|
121
|
-
|
|
122
|
-
console.log('Locked rows:', lockedRows);
|
|
123
|
-
|
|
124
|
-
await transaction.commit();
|
|
125
|
-
console.log('Transaction completed');
|
|
126
|
-
} catch (err) {
|
|
127
|
-
await transaction.rollback();
|
|
128
|
-
console.error('Error:', err);
|
|
129
|
-
throw err;
|
|
130
|
-
} finally {
|
|
131
|
-
await connection.end();
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 示例 4: 并发事务(使用连接池)
|
|
137
|
-
* 展示多个事务可以同时执行而不相互阻塞
|
|
138
|
-
*/
|
|
139
|
-
async function exampleConcurrentTransactions() {
|
|
140
|
-
const pool = mysql.createPool({
|
|
141
|
-
host: 'localhost',
|
|
142
|
-
port: 3306,
|
|
143
|
-
user: 'root',
|
|
144
|
-
password: 'password',
|
|
145
|
-
database: 'test_db',
|
|
146
|
-
connectionLimit: 10
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const queryHandler = new QueryHandler(pool);
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
// 并发执行多个事务
|
|
153
|
-
const results = await Promise.all([
|
|
154
|
-
// 事务 1
|
|
155
|
-
(async () => {
|
|
156
|
-
const tx = await queryHandler.beginTransaction();
|
|
157
|
-
try {
|
|
158
|
-
await tx.table('users').insert({ name: 'User1', age: 20 });
|
|
159
|
-
await tx.commit();
|
|
160
|
-
return 'Transaction 1 completed';
|
|
161
|
-
} catch (err) {
|
|
162
|
-
await tx.rollback();
|
|
163
|
-
throw err;
|
|
164
|
-
}
|
|
165
|
-
})(),
|
|
166
|
-
|
|
167
|
-
// 事务 2
|
|
168
|
-
(async () => {
|
|
169
|
-
const tx = await queryHandler.beginTransaction();
|
|
170
|
-
try {
|
|
171
|
-
await tx.table('users').insert({ name: 'User2', age: 21 });
|
|
172
|
-
await tx.commit();
|
|
173
|
-
return 'Transaction 2 completed';
|
|
174
|
-
} catch (err) {
|
|
175
|
-
await tx.rollback();
|
|
176
|
-
throw err;
|
|
177
|
-
}
|
|
178
|
-
})(),
|
|
179
|
-
|
|
180
|
-
// 事务 3
|
|
181
|
-
(async () => {
|
|
182
|
-
const tx = await queryHandler.beginTransaction();
|
|
183
|
-
try {
|
|
184
|
-
await tx.table('users').insert({ name: 'User3', age: 22 });
|
|
185
|
-
await tx.commit();
|
|
186
|
-
return 'Transaction 3 completed';
|
|
187
|
-
} catch (err) {
|
|
188
|
-
await tx.rollback();
|
|
189
|
-
throw err;
|
|
190
|
-
}
|
|
191
|
-
})()
|
|
192
|
-
]);
|
|
193
|
-
|
|
194
|
-
console.log('All transactions completed:', results);
|
|
195
|
-
} finally {
|
|
196
|
-
await pool.end();
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* 最佳实践总结:
|
|
202
|
-
*
|
|
203
|
-
* 1. 生产环境推荐使用连接池(Pool)
|
|
204
|
-
* 2. 使用 QueryHandler.beginTransaction() 自动管理连接
|
|
205
|
-
* 3. 始终在 try-catch-finally 中使用事务
|
|
206
|
-
* 4. 确保调用 commit() 或 rollback()
|
|
207
|
-
* 5. 连接池会自动释放连接,无需手动管理
|
|
208
|
-
* 6. 避免在事务中执行长时间运行的操作
|
|
209
|
-
* 7. 根据需要选择合适的隔离级别:
|
|
210
|
-
* - 'RU' / 'READ UNCOMMITTED': 最低隔离级别,性能最好,可能读到脏数据
|
|
211
|
-
* - 'RC' / 'READ COMMITTED': 避免脏读
|
|
212
|
-
* - 'RR' / 'REPEATABLE READ': MySQL 默认级别,避免不可重复读
|
|
213
|
-
* - 'S' / 'SERIALIZABLE': 最高隔离级别,完全串行化,性能最差
|
|
214
|
-
*/
|
|
215
|
-
|
|
216
|
-
// 运行示例(取消注释以运行)
|
|
217
|
-
// exampleWithPool().catch(console.error);
|
|
218
|
-
// exampleWithSingleConnection().catch(console.error);
|
|
219
|
-
// exampleWithTransactionHandler().catch(console.error);
|
|
220
|
-
// exampleConcurrentTransactions().catch(console.error);
|
|
221
|
-
|
|
222
|
-
module.exports = {
|
|
223
|
-
exampleWithPool,
|
|
224
|
-
exampleWithSingleConnection,
|
|
225
|
-
exampleWithTransactionHandler,
|
|
226
|
-
exampleConcurrentTransactions
|
|
227
|
-
};
|
|
228
|
-
|