Rails 2.3.5 查询A表记录时如何同时关联预加载B表和C表
结论
因为A表和C表没有直接关联,所以无法直接通过A查询的include参数同时预加载B表和C表,但有两种完全兼容你当前Rails2.3.5 + Ruby1.8.7环境的方案可以实现等效预加载效果,避免N+1查询问题。
方案1:手动触发预加载(无需修改模型关联)
适合临时查询、不想调整模型定义的场景:
- 先按现有逻辑查询A表并预加载关联的B表
a_records = A.all(:conditions => { :id => id }, :include => [:B])
- 提取所有关联的B对象,手动预加载B对象对应的C表关联
# 提取所有关联的B对象 b_records = a_records.map(&:B).flatten # 批量预加载B对应的C关联 ActiveRecord::Associations::Preloader.new(b_records, :C).run
执行完成后,你访问任意A记录的B.C属性都不会产生新的数据库查询。
方案2:新增间接关联后直接预加载(适合高频查询场景)
如果你经常需要从A侧访问关联的C数据,可以先在A模型中新增通过B表的间接关联:
class A < ActiveRecord::Base has_many :B # 你现有B表关联定义 # 新增通过B指向C的间接关联 has_many :C, :through => :B, :source => :C end
调整后就可以直接在查询时同时预加载B和C:
A.all(:conditions => { :id => id }, :include => [:B, :C])
注:如果你的模型关联用的是Rails默认的小写复数命名,把示例中的大写
:B/:C换成小写的:bs/:cs即可。
内容的提问来源于stack exchange,提问作者Topotan
相关产品推荐
相关产品推荐

