用于在 Python 或 Ruby 中自动映射外键的 ORM 库

Posted

技术标签:

【中文标题】用于在 Python 或 Ruby 中自动映射外键的 ORM 库【英文标题】:ORM library for automatically mapping foreign keys in Python or Ruby 【发布时间】:2009-12-13 19:32:06 【问题描述】:

我在工作中经常遇到的一项任务是针对预先存在的数据库编写脚本。有时我连接到 Oracle,有时它可能是 mysql 甚至是 sql server。

我想要一个工具,它可以对数据库的表和外键进行逆向工程,并允许我针对数据库编写 OO 风格的脚本。这实际上可以是任何语言,但首选 python 或 ruby​​。

例如 - 这是我理想的 ruby​​ 脚本:(假设 manager 和 employee 表已经存在外键)

DB = Database.connect(connect_string)
DB.managers.each do |manager|
  puts manager.name
  manager.employees.each do |employee|
    puts employee.name
  end
end

这种类型的库存在吗?如果是这样,那将节省我很多时间!

编辑 - 我想要的主要功能是它可以自动从数据库元数据中发现外键关联,而无需显式映射它们 - 我已经尝试过 ActiveRecord、SQLAlchemy、Sequel 和 DataMapper,据我所知,他们都做不到。

【问题讨论】:

【参考方案1】:

您应该看看SQLAlchemy 中的SQLSoup extension。它声称可以为您完成所有这些工作(包括外键)。我自己没有测试过。

【讨论】:

这是我想得到的最接近的结果——我仍然需要声明关系,但这很容易:db.managers.relate('employees', db.employees)跨度> 【参考方案2】:

严重的 Ruby ORM 不这样做是有原因的:它不灵活、不够明确并且太神奇了。

如果您真的想要在您的项目中使用它,请尝试使用 Ruby 自己编写代码。以下是我在 ActiveRecord 上用 5 分钟完成的工作:

require 'active_record'

class ActiveRecord::Base
  def self.magic!
    connection.tables.map  |table|
      klass = Class.new(self)
      Object.send(:const_set, table.singularize.camelize, klass)
    .each  |model|
      model.column_names.grep(/_id$/).each  |foreign_key|
        name = foreign_key.sub(/_id$/, '')
        model.belongs_to(name)
        name.camelize.constantize.has_many(model.name.tableize)
      
    
  end
end

让我们设置我们的数据库表并让magic! 分析它们:

ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')

ActiveRecord::Schema.define do
  create_table "managers" do |t|
    t.string "name"
  end
  create_table "employees" do |t|
    t.string "name"
    t.belongs_to "manager"
  end
end

# it happens!
ActiveRecord::Base.magic!

创建一些测试记录并以您想要的方式使用它:

mislav = Manager.create :name => "Mislav"
mislav.employees.create(:name => "Josh")
mislav.employees.create(:name => "Mike")

Manager.all.each do |manager|
  puts manager.name
  manager.employees.each do |employee|
    puts employee.name
  end
end

Full code available on this Gist.

这仅适用于 belongs_tohas_many 关联。如果您需要一个真正的库来执行此操作以及更多功能,请查看Dr Nic's Magic Models。

【讨论】:

有趣。感谢您深思熟虑的回应。我同意将名称基于列命名约定是一个坏主意,但实际上我正在寻找一个可以分析数据库元数据中的外键以查找关联的库。查看 ruby​​ 数据库驱动程序,似乎它们中的大多数都没有保留任何有关外键的信息,这会使这变得非常困难。我知道大多数 JDBC 驱动程序都会存储这些信息,所以也许我可以使用 JRuby 来执行此操作。【参考方案3】:

试用 SQLAlchemy 的 sqlautocode 模块。它将通过反映数据库来生成 ORM 类。

【讨论】:

【参考方案4】:

在 Ruby 中,有几个 ORM,例如 ActiveRecord、DataMapper 甚至 Sequel。

例如使用 ActiveRecord 你会这样做:

##################################
#mysql conection
##################################
begin
  ActiveRecord::Base.establish_connection(
    :adapter  => DBAdapter,
    :host     => DBHost,
    :username => DBUserName,
    :password => DBPass,
    :database => DBDatabase,
    :encoding=> DBEncoding,
    :socket=> DBSocket #drop this option for windows machines 
  )
rescue Exception => ex
  fout.puts "Error connecting to mysql : #ex"
  puts "Migration was terminated due to connection error , check out the log file"
  break
end

######################
# Define models
######################

class Employee < ActiveRecord::Base
 belongs_to :manager
end 

class Manager < ActiveRecord::Base
 has_many :employees
end 

【讨论】:

这些库都需要你手动设置关联。

以上是关于用于在 Python 或 Ruby 中自动映射外键的 ORM 库的主要内容,如果未能解决你的问题,请参考以下文章

JAPANESE 如何在没有额外列或额外映射表的情况下拥有主键外键关系

Ruby on Rails - rails g 脚手架外键

Hibernate JPA与共享主键外键字段的一对一双向映射为空(hb无法自动设置)

如何在 ruby​​ on rails 中命名外键?

从Ruby中的两个数组映射值

LinQ的增删改查