开发人员:Ruby on Rails

从 Ruby on Rails 连接到 Oracle

作者:Obie Fernandez

了解如何从一个 Rails 应用程序连接到 Oracle 和与其相关的验证和性能问题。

2007 年 6 月发表

在使用 Java 时,有两种针对 Oracle 的常见驱动程序:纯 Java (又叫做瘦)驱动程序和原生 OCI 驱动程序。在写作这篇文章的时候,还没有和基于 JDBC 的 Java 瘦驱动程序类似的纯 Ruby 驱动程序。

要连接到 Oracle,用户必须安装 Ruby/Oracle 调用接口 (OCI8) 库 — 一个基于 Ruby/DBI (数据库接口模块)的数据库驱动程序。RubyDBI 提供了一个与数据库无关的、类似于 JDBC 或 ODBC 的接口,来实现 Ruby 和数据库之间的交互。Ruby OCI8 驱动程序通过标准的 Oracle 客户端软件连接到 Oracle 8 到 10 的所有版本。OCI8 是一个 Ruby 包装器,用本地 C 代码编写,实际的交互就由它来完成。

非 windows 开发人员可以通过输入 sudo gem install ruby-oci8 来进行安装。Windows 开发人员可以先从 www.rubyforge.org/projects/ruby-oci8 上下该载驱动程序的二进制版本,然后手动安装:

ruby ruby-oci8-0.1.16-mswin32.rb

可以通过下面的命令行 Ruby 程序查询一个包含演示 (HR) 模式的数据库,简单检测您所下载的 Ruby OCI8 驱动程序。替换下面命令中 Oracle 数据库的名称和口令:

set oracle_sid=xe

ruby -r oci8 -e "OCI8.new('hr', 'password').exec('SELECT * FROM jobs ORDER BY 1') {|r| puts r.join}"

如果连接和查询成功,输出应如下所示:

AC_ACCOUNT | Public Accountant | 4200 | 9000

AC_MGR | Accounting Manager | 8200 | 16000

AD_ASST | Administration Assistant | 3000 | 6000

AD_PRES | President | 20000 | 40000

AD_VP | Administration Vice President | 15000 | 30000

FI_ACCOUNT | Accountant | 4200 | 9000

FI_MGR | Finance Manager | 8200 | 16000

HR_REP | Human Resources Representative | 4000 | 9000

IT_PROG | Programmer | 4000 | 10000

MK_MAN | Marketing Manager | 9000 | 15000

MK_REP | Marketing Representative | 4000 | 9000

PR_REP | Public Relations Representative | 4500 | 10500

PU_CLERK | Purchasing Clerk | 2500 | 5500

PU_MAN | Purchasing Manager | 8000 | 15000

SA_MAN | Sales Manager | 10000 | 20000

SA_REP | Sales Representative | 6000 | 12000

SH_CLERK | Shipping Clerk | 2500 | 5500

ST_CLERK | Stock Clerk | 2000 | 5000

ST_MAN | Stock Manager | 5500 | 8500

Rails 配置

Rails 用于连接到数据库的参数存放在您的 Rails 应用程序目录中的 config/database.yml 中。下面的例子引用了主机 xe,它对应 tnsnames.ora 中的一项。使用了三种模式,分别用不同的用户名指定。

development:

adapter:oci

host:xe

username:development

password:password

test:

adapter:oci

hostxe

username:test

password:password

production:

adapter:oci

host:xe

username:production

password:password

也可以将 Oracle Easy Connect Naming 和 Ruby OCI8 驱动程序结合使用。用一个 Oracle Easy 连接字符串替换主机字段中的 SID,如下所示:

development:

adapter:oci

host://server:port/instance_name

username:development

password:password

身份验证

和大多数的三层应用程序体系结构一样,Rails 假设使用一套证书(在 database.yml 中指定)对 Oracle 进行身份验证。指定的证书必须有足够的权限来执行 Rails 应用程序的任何操作。

如果出于安全的考虑,不想把证书以明文的形式包含在配置文件中,您可以利用 database.yml 允许通过 ERb 标记使用动态内容的特性。语法与使用 标记将参数值插入 Rails 视图模版的语法相同。

下面的例子从启动时设置的环境变量中获取用户名和口令:

production:

adapter:oci

host:xe

username:

password:

传递身份验证 (Pass-Through Authentication)

目前还没有一个从 Rails 应用程序到 Oracle 的所谓的传递身份验证(一个终端用户使用他或她的 Oracle 证书来验证身份。验证通过后,对该应用程序的使用则受 Oracle 定义的访问权限和限制范围的控制)的标准方法。与 Rails 相关的涉及传递身份验证的自定义解决方案在理论上是可行的,但也存在各种各样的应用和性能问题。

比如,从理论上来讲,我们总可以使用已登录用户的证书创建一个到数据库的新连接。这可以通过在控制器的 before_filter 方法中建立一个连接(使用该用户的证书)完成。相应的,取消连接需要在 after_filter 方法中手动完成。与其他问题相比,这种方法的速度非常慢,因为需要为每一个请求建立一个连接。

难得就不可简单地将 Oracle 连接缓存在一个用户会话中吗?很遗憾,不能;因为 Rails 应用程序没有像 JEE 应用程序那样可以在请求间保持活动状态的内存会话存储。所有会话内容与文件系统的序列化和存储、数据库或分布式缓存相关。

假定已经找到在现有连接上验证指定用户身份的难点,那么传递身份验证与 ActiveRecord 的结合可能会提供某些价值。

比如,行级安全性对于一个在数据库级指定的用户来说可以透明的指定该用户可见的对象,而无需任何实现代码。此外,ActiveRecord 的属性动态生成特性也是一大亮点,因为它可以将列级安全性透明的反射到对象模型中。因为属性是动态读取的,所以该模型实例只包含与已登录用户可见的列相匹配的属性。不过要记住,虽然由于性能原因在生产模式下缓存属性信息,但是另一个优化使传递身份验证变成了一个性能问题。

对于通过授权实现的表级安全性,您可以假定一旦 SQL 由于权限问题运行失败,Oracle 会从驱动程序引发异常。您可以捕捉这些异常并进行妥善处理,但是如果当作出一次尝试时一个指定的操作是有效的,这种方法存在的问题就不会出现。比如,如果您想根据用户的插入权限在一张表上禁用一个“create”按钮,那么在执行插入操作之前您无法获知他的权限。

可能的变通方法就是在首次建立该连接的时候,将该用户的所有授权和权限信息加载到会话中。然后,可以使用这些授权和权限信息在视图中提供安全特性(根据权限隐藏/禁用按钮),或向模型添加安全性(在执行这项操作之前先用 before_save 和 before_update 等回调方法进行权限检查)。当然,这都是理论上的分析,而读取权限信息时可能遇到的困难也是未知的,尤其是在通过存储过程实现时。

使用多个数据库

建立一个可以和多个数据库交互的 Rails 应用程序一点都不复杂。您只要在 database.yml 文件中指定额外的数据库连接参数。比如,假设您需要访问另一个 Oracle 数据库来读取库存数据:

inventory:

adapter:oci

host:xe

username:inventory

password:password

然后,定义一个模型(名为 Inventory)来读取库存数据:

class Forum < ActiveRecord::Base

self.connection = "inventory"

end

Rails 应用程序部署为独立的服务器进程池,并且对于每个 rails 请求均按进程维护和重用一个数据库连接。我们通常分别使用 ActiveRecord::Base.establish_connection 和 ActiveRecord::Base.connection 来建立和检索连接。所有继承 ActiveRecord::Base 的类都将使用这个连接。您也可以为某些特定的模型建立一个为某个类所特有的连接(如前面所示),然后这个类和它所有的子类将会转而使用这个显示指定的连接。

ActiveRecord 在 ActiveRecord::Base 中将一个连接池作为按模型类名索引的散列。当请求连接时,retrieve_connection 方法会向上遍历类层次结构,直到在连接池中找到一个连接。

优化

Rails 现在还不支持在 SQL 查询中将变量和 Oracle 绑定,这对性能造成了一些负面影响。Rails (1.2) 的当前版本将 Oracle 连接选项 cursor_sharing 设置为 similar,这通过在数据库级自动将文字转换为绑定变量,显著改善了性能。此外,它还将预取行数设置为 100。

但无论是游标共享还是预取行数设置都不是理想的解决方案。虽然这两个方案都有可能给服务器带来额外的负担,但是大多数开发人员只片面报告他们连接 Oracle 的 Rails 应用程序在性能方面的显著改进,这使我们误以为这两个方案在大多数情况下都有效。但您的体会可能与此不同。

如果您需要额外的性能优化,Ruby OCI 驱动程序可以利用多种其他属性来调整数据库连接,只是 Rails 没有提供一个设置这些属性的标准方法。要了解更多优化方案,包括设置诸如 prefetch-rows 等选项的方法,请访问 www.ruby-forum.com/topic/86831。

Obie Fernandez 是 ThoughtWorks 的资深技术顾问;他主要研究基于 Web 的应用程序设计和实现,在集成大型的、分布式应用程序和旧式系统方面有着丰富的企业经验。Obie 近来主要研究如何创造性的将基于 Ruby 的技术(比如 Ruby on Rails)应用到企业。

ruby oracle数据,从 Ruby on Rails 连接到 Oracle相关推荐

  1. oracle数据泵整库备份,详解oracle 12c通过数据泵expdp/impdp工具实现对数据备份、恢复...

    标签: 简介 Oracle Database 10g引入了最新的数据泵(Data Dump)技术,数据泵导出导入(EXPDP和IMPDP)的作用 1.实现逻辑备份和逻辑恢复 2.数据库用户之间移动对象 ...

  2. 『Oracle数据库容灾案例系列』国元证券Oracle容灾案例

    『Oracle数据库 容灾案例系列』   国元证券Oracle数据库容灾案例 使用产品:DDS 上线时间:2007 系统环境:Oracle 10g RAC  IBM AIX5L 应用系统:金正 证券 ...

  3. oracle数据如何导入hadoop,hadoop hive 与 Oracle 互相导入数据

    #1.在Oracle上建立要处理的表 create table SOURCE_TABLE_NAME as SELECT t.*,rownum as row_num FROM SOURCE_TABLE_ ...

  4. oracle数据库主键自增序列_【oracle】oracle数据库建立序列、使用序列实现主键自增...

    2.建立序列 -- Create sequence create sequence SEQ_SHIP_IMAGE minvalue 20 maxvalue 999999999999999999 sta ...

  5. 导出oracle数据c#代码,C# 程序导入导出oracle数据库

    /// /// MrTom /// Oracle数据库备份 /// private void OracleBackUp() { //创建一个进程实例 Process p = new Process() ...

  6. kettle oracle数据从库到库,kettle 使用oracle数据库当做资源库

    kettle 使用oracle数据库当做资源库 kettle 使用oracle数据库当做资源库 连接oracle 12C数据库同理 第二步 找到kettle的安装目录下的 jdbc.propertie ...

  7. oracle 数据导入不成功,node.js往oracle数据库插入数据失败

    源码: var oracledb = require('oracledb'); oracledb.getConnection({ user: "hr", password: &qu ...

  8. c odac 连接 oracle,使用ODAC112040Xcopy_64bit 将sql server连接到oracle

    需要一个软件ODAC112040Xcopy_64bit 我连接的oracle是11g r2  sqlserver 是 2016 软件下载 https://pan.baidu.com/s/1OpYmpR ...

  9. ubuntu下oracle数据的导入,导入oracle数据库命令行

    Windows DOS窗体下Oracle 数据库的导入导出命令 oracle 用户创建 数据库的导入导出imp/exp 可以在SQLPLUS.EXE或者DOS(命令行)中执行 执行环境:可以在SQLP ...

最新文章

  1. esxi所连交换机划vlan导致vm不能通讯
  2. Python学习笔记:Day5 编写web框架
  3. 计算机网络-思维导图(2)物理层
  4. linux之快速过滤文本的关键字以及快速过滤目录下的关键字
  5. Android应用程序显示未读消息计数
  6. calender获取日期前几月_java获取当前时间和前一天日期(实现代码)
  7. java webdriver page object_Selenium2(java)页面对象模型(Page Object) 八
  8. static与get属性的作用
  9. KKT条件 拉格朗日乘子法
  10. Linux 系统编程技巧与概念 第14章 字节次序
  11. MVC Tutorial Movie DIY
  12. SharePoint 2013连接非默认端口的SQL Server
  13. TCPIP详解 IP路由选择
  14. 寻剑气世界java,Java——Unsafe
  15. GIS技巧100例20-Excel度分秒转十进制度
  16. DCM protocol Diagnostic session
  17. CE修改器入门:精确数值扫描
  18. 杀不死的人狼——我读《人月神话》(五)
  19. Navicat Premium 12 for Mac 破解
  20. it系统应急响应流程图_[应急处理程序] 应急响应程序6个过程

热门文章

  1. 深圳公司税务异常该如何处理?
  2. Unity替换启动Logo动画
  3. JS数组深拷贝、对象深拷贝
  4. java 用json删除注释
  5. css常用代码大全,html+css代码
  6. css实现上下左右居中显示,CSS实现一个标签上下左右居中的办法
  7. deepin允许root登录_王者荣耀安全改战区免root
  8. Java用户管理系统【完整版】
  9. 向微信公众号文章添加Excel表格文件、PPT演示文稿
  10. 双十一要来了,我去庙里给你求了一道护身符