自连接

对于表中的一个记录连接同一个表中的另一个记录也是可能发生的。举个例子,公司里
每一个雇员有一个manager 和一个mentor,这两个也是雇员。在Rails 你可以这样建模。
class Employee < ActiveRecord::Base
belongs_to :manager,
:class_name => "Employee",
:foreign_key => "manager_id"
belongs_to :mentor,
:class_name => "Employee",
:foreign_key => "mentor_id"
has_many :mentored_employees,
:class_name => "Employee",
:foreign_key => "mentor_id"
has_many :managed_employees,
:class_name => "Employee",
:foreign_key => "manager_id"
end
让我们加载一些数据。Clem 和Dawn 每个都一个mamager 和一个mentor。
Employee.delete_all
adam = Employee.create(:id => 1, :name => "Adam")
beth = Employee.create(:id => 2, :name => "Beth")
clem = Employee.new(:name => "Clem")
clem.manager = adam
clem.mentor = beth
clem.save!
dawn = Employee.new(:name => "Dawn")
dawn.manager = adam
dawn.mentor = clem
dawn.save!
然后,我们可以看看关系,回答这样的问题,“谁是X 的mentor?”和“哪个雇员是Y
的manager?“
p adam.managed_employees.map {|e| e.name} # => [ "Clem", "Dawn" ]
p adam.mentored_employees # => []
p dawn.mentor.name # => "Clem"
你也可能看到关系的不同用法。它在243 页描述。
Preloading Child Rows
正常情况下Active Record 都会推后加载数据库的子记录,一直到他们要用到的时候。
例如,
class Post < ActiveRecord::Base
belongs_to :author
has_many :comments, :order => 'created_on DESC'
end
如果我们迭代posts,访问author 和comment 属性,我们将使用一个SQL 查询,它返回
posts 表中n 行记录,又从authors 和comments 表中得到相关的记录,总共2n+1 次查询。
for post in Post.find(:all)
puts "Post: #{post.title}"
puts "Written by: #{post.author.name}"
puts "Last comment on: #{post.comments.first.created_on}"
end
这种性能问题有时使用find()方法的:include 参数选项来解决。当这个查询完成时,它
列出被预先加载的关联表。Active Record 是以一种比较聪明的方式来处理所有的数据都在
一个单一的SQL 查询里返回。如果有100 个posts,下面的代码将会消除这100 个查询的性
能。
for post in Post.find(:all, :include => :author)
puts "Post: #{post.title}"
puts "Written by: #{post.author.name}"
puts "Last comment on: #{post.comments.first.created_on}"
end
这个例子将会把只有一个查询造成的影响消除。
for post in Post.find(:all, :include => [:author, :comments])
puts "Post: #{post.title}"
puts "Written by: #{post.author.name}"
puts "Last comment on: #{post.comments.first.created_on}"
end
这种预加载并不保证一定会提高性能。[事实上,它可能不会工作!如果你的数据库不支
持左侧连接的话,你就不能使用这个特性。例如,Oracle8 的用户将需要更新到9 来使用预
加载。]它连接查询中的所有表,返回很多数据,这些数据转换成Active Record 对象。如果
你的应用程序不使用额外的信息,你将会为此付出代价。如果你父表包含很多很多记录的话,
你可能也会碰到问题-与一行一行的懒加载相比。预加载的技术是要消耗很多服务器内存。
如果使用:include,你将需要确定用在find()的参数中的所有列名-每个前面都以表名
作为前缀。在下面例子中,条件句中的title 列要有表名作前缀来让查询成功。
for post in Post.find(:all, :conditions => "posts.title like '%ruby%'",
:include => [:author, :comments])
# ...
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值