OrientJS中Classes API能否配合事务使用?遇即时提交问题求助
我完全懂你这个头疼的问题——本来想靠事务把创建操作攒到最后一起提交,结果调用transaction.db.class.get()之后,create()一执行直接就提交了,根本没等你调用transaction.commit(),这确实和预期差得远。
先给你拆解下问题的核心:当你通过transaction.db获取数据库实例再调用class.get()时,这个操作其实脱离了事务的上下文绑定,相当于直接用了原数据库的连接来执行操作,而不是在事务的包裹下进行。所以后续的create()会直接生效并提交,完全没走事务的流程。
那怎么才能让Class API配合事务正常工作呢?给你两个实用的方案:
方案一:用事务的let()方法绑定类(保留Class API的便捷性)
虽然你提到了解db.let(),但其实可以把它和Class API结合起来用,既保证事务上下文,又能用上类的专属方法:
const db = server.use('MyDb'); const transaction = db.begin(); // 把类实例绑定到事务上下文,然后在事务内执行创建操作 const newProduct = await transaction .let('productClass', () => transaction.db.class.get('Product')) .let('createdProduct', ({ productClass }) => productClass.create({name: 'Milk', brand: 'Clover'})) .commit() .return('createdProduct') .one();
这种写法下,所有操作都被包裹在事务上下文里,create()不会提前提交,必须等commit()执行后才会把数据写入数据库。
方案二:直接通过事务实例调用创建操作(更简洁)
如果觉得let()的写法有点啰嗦,也可以跳过class.get()这一步,直接用事务实例的create()方法指定类名,这样也能确保操作在事务内执行:
const db = server.use('MyDb'); const transaction = db.begin(); // 直接通过事务实例创建指定类的记录 await transaction.create('Product', {name: 'Milk', brand: 'Clover'}); // 到这一步才真正提交事务 transaction.commit();
这种写法更直接,同样能保证所有操作都在事务中排队,只有调用commit()时才会统一提交。
最后再提个关键注意点:OrientDB的事务API对上下文绑定要求非常严格,所有需要在事务内执行的操作,都必须直接通过事务实例来调用,而不能通过transaction.db去间接获取类或执行操作——后者会直接绕开事务,导致操作立即生效。
内容的提问来源于stack exchange,提问作者Marthinus Engelbrecht

