假设我有连接到另一个数据库的模型:
class Model1 < ActiveRecord::Base
establish_connection {config_to_connection_to_database2}
end
class Model2 < ActiveRecord::Base
establish_connection {config_to_connection_to_database2}
end
当我开始交易时,请说
Model1.transaction do
Model1.create! something
Model2.create! something
#some other thing
end
生成的SQL是:
BEGIN
INSERT INTO model1 ...
BEGIN
INSERT INTO model2 ...
COMMIT
#some other thing might happen here
COMMIT
当#some other thing
中发生错误时,INSERT INTO model2
将不会回滚,因为它在嵌套事务中并且已经提交,而INSERT INTO model1
将被回滚。
我找到了一个丑陋的解决方法:
Model1.transaction do
Model2.transaction do
Model1.create! something
Model2.create! something
#some other thing
end
end
SQL成为:
BEGIN
BEGIN
INSERT INTO model1 ...
INSERT INTO model2 ...
#some other thing might happen here
COMMIT
COMMIT
哪个有效,但有点烦我。
所以我的问题是:activerecord如何决定是否应该使用BEGIN
和COMMIT
包装一个SQL语句(看起来像activerecord将不会检查Model1和Model2是否连接到同一个数据库),这里有更好的解决方法吗?
答案 0 :(得分:0)
事实证明解决方案非常简单(在ActiveRecord :: Base文档中答案是正确的,我完全失明了)
设置课程
class Database2 < ActiveRecord::Base
self.abstract_class = true #this is important, otherwise the inherited class's table name would be 'database2'
establish_connection your_connection_config
end
然后Model1
和Model2
只需要继承Database2
,一切正常。
如果有人想知道,Model1
和Model2
以这种方式共享同一个连接池。如果你在每个类中调用establish_connection
,那么每个类都有自己的连接池,这会浪费资源,并且会在我的问题中提到事务问题。