当前位置: 首页 > 编程日记 > 正文

ORM查询语言(OQL)简介--概念篇

 相关文章内容索引:

ORM查询语言(OQL)简介--概念篇
ORM查询语言(OQL)简介--实例篇
ORM查询语言(OQL)简介--高级篇:脱胎换骨
ORM查询语言(OQL)简介--高级篇(续):庐山真貌

一、SQL与ORM

  关系数据库(RDBMS)的查询有SQLStructured Query Language)结构化查询语言,相比高级程序语言(命令式语言)而言,SQL主要描述想要做什么,而不是命令式语言的具体如何做,因此,SQL也被称第四代语言4GL),它为现代大多数的关系数据库系统所支持。SQL的核心是对关系的操作,数据库理论研究证明,SQL是关系上完备的,但是当代大多数高级语言都是面向对象的,高级语言程序要跟关系数据库进行交互,SQL就成了必须的桥梁,由于SQL基于的关系和程序语言的对象是不同的体系,它们之间要完成很好的交互,就得有一个映射过程,实现这个过程的程序,就是ORMObject/Relation Mapping)。

  应用程序调用ORM的方法,ORM自动生成相应的SQL语句到数据库进行查询,然后ORM将接收到的关系数据映射成实体对象。如果没有使用ORM,那么通常应用程序会拆分出一个数据访问层(DAL)来生成SQL语句并执行相应的查询。所以,ORM出现后,在一定程度上,它可以取代DAL,这使得你少了一个层的工作量,对于提高工作效率是很重要的。

  下图是应用程序使用ORM和使用传统的DAL的一个示意图。

(图1:两种数据访问架构)

二、ORM带来的问题

  使用ORM后,再也不用去写那些枯燥的DAL代码了,不用拼接那些可能存在安全问题或者敲错字段名的SQL语句,但是我们发现,仅仅使用ORM它反而丧失了SQL的灵活性,这也是不少人拒绝使用ORM的理由。我们看看很多人的ORM是怎么定义数据操作接口的,他们常常把这些接口方法由实体类去实现,从而制造一个个充血的实体类:

public interface IEntity<T> where T:class
{
void Add();
void Update();
void Delete();
List<T> GetAll();
T GetOne(int id);
}

使用充血实体类,在使用上还是比较方便的,但是Insert \Update\Delete 都只能操作一条数据,GetAll 方法不仅仅把全部数据拿出来了,而且还可能把不需要的字段值也拿了出来,那个GetOne方法,也许实际上表的主键并不是int 类型的,那么这些定义就会有问题。。。

  所以,我们见到很多使用了ORM的项目,不管数据是否全部需要,先拿出来再说,不管主键是不是int 类型,先定一个方法在那里,大不了是个空方法,不管当前实体是否需要Delete功能(比如某些系统用户数据是不能删除的),都基类给直接实现了。。。。。。

三、ORM查询语言

1,分离关注点

  那么,这些问题ORM能够解决吗?ORM本来是完成“对象-关系映射”的,但这里大多数的ORM都包含了“生成SQL”的功能,而要实现SQL那样的灵活性,那么我们必须分离出ORM这个关注点,将“生成SQL”的功能从ORM中抽取出来,这样我们就能够有更多的精力致力于发明一个面向对象的,用于ORM查询的语言,(ORM Query Language) ,这就是OQL

ORM查询语言,其实早就有了,从早期的HibernateHQL,到MSLinqLinq2SQLEF其实内部都是使用Linq生成的SQL),它们都可以生成复杂的SQL语句,它们都是直接作用于ORM框架的。几乎在与Linq同一时期,PDF.NET也发明了自己的ORM查询语言,称为OQL。下面提到的OQL,都是指的PDFOQL

2,PDF.NET的ORM框架

PDF.NETORM框架包括4个部分:

  1. Entity Object PDF.NET实体类,它继承于基类 EntityBase,使得每一个实体类都成为一个“数据容器”;
  2. OQLORM查询语言,以实体类对象为操作对象,生成查询表达式,供实体查询对象使用。
  3. AdoHelper数据访问提供程序抽象类,封装了对ADO.NET的各种访问,包括事物操作;框架默认提供了OledbProviderOdbcProviderAccessProviderSqlServerProviderOracleProvider等,要支持更多的数据库,只需要继承AdoHelper即可。
  4. EntityQuery<T> 实体查询对象,它是一个O/R Mapping对象,它操作涉及的对象类型是一个实体类(类型T);在对象内部,它会把OQL转换成SQL,然后调用AdoHelper完成查询。

(图2:PDF.NET OQL 架构)

  如果仅从查询调用端来观察,我们发现OQL,跟SQL逻辑上是等价的,一个是“对象化”的查询,一个是“结构化”的查询:

对象化查询:OQL->ORM-> Entity Objects

等于

结构化查询:SQL ->DB-> DataSet

  如果最终效果Entity Object==DataSet,那么OQL==SQL

  所以,OQL的设计目标,就是要它生成的SQL语句效果基本达到手写的SQL语句一样。由于SQL的具体实现又有很多不同的版本,所以很多时候SqlServer用的SQL语句在Oracle 上不一定能够使用,只有那些完全标准的SQL语句才是通用的,因此,OQL的设计,也必须是这样标准的SQL规范,目前,实现的是SQL92标准规范。

3,OQL查询范式

  下面是OQL支持的查询范式举例,注意下面的定义里面使用了“BNF”范式,为了避免大家误会,这里补充下BFN的内容,详细内容请参考这个链接:http://baike.baidu.com/view/1137652.htm

 

巴科斯范式的内容

在双引号中的字("word")代表着这些字符本身。而double_quote用来代表双引号。

在双引号外的字(有可能有下划线)代表着语法部分。

尖括号( < > )内包含的为必选项。

方括号( [ ] )内包含的为可选项。

大括号( { } )内包含的为可重复0至无数次的项。

竖线( | )表示在其左右两边任选一项,相当于"OR"的意思。

::= 是“被定义为”的意思。

1,数据查询:


OQL q=OQL.From(entityObject)

[.[InnerJoin|LeftJoin|RightJoin](entityObject2).On(entityObject.PK,entityObject2.FK)]

[.[InnerJoin|LeftJoin|RightJoin](entityObject3).On(entityObject.PK,entityObject3.FK)]

.Select([entityObjectX.Property1][,entityObjectX.Property2][{,…}])

.Where([<entityObject.Property1>[,entityObject.Property2][,…]]|[OQL2]|[OQLCompare])

.GroupBy(entityObjectX.PropertyN,<"asc">|<"desc">)

.HavingBy(entityObjectX.PropertyM)

.End;

 如果需要分页,仅需要这样操作:

q.Limit(分页大小[,页码[,总记录数]]);

 执行该方法,会生成特定数据库平台的分页SQL语句。

2,数据统计:


OQL q=OQL.From(entityObject)

.Select().Count(entityObject.PropertyX,<””>|<"CountAsName">)

.Where([<entityObject.Property1>[,entityObject.Property2][,…]]|[OQL2]|[OQLCompare])

.End;

3,数据更新:

OQL q=OQL.From(entityObject)

.Update([entityObject.Property1][,entityObject.Property2][{,…}])

.Where([<entityObject.Property1>[,entityObject.Property2][,…]]|[OQL2]|[OQLCompare])

.End;

4,数据删除:

OQL q=OQL.From(entityObject)

.Delete()

.Where([<entityObject.Property1>[,entityObject.Property2][,…]]|[OQL2]|[OQLCompare])

.End;

下篇我们将使用实例来讲解OQL的具体使用,敬请期待。

注:PDF.NET现在已经开源,有关框架的详细信息,请看官网介绍:http://www.pwmis.com/sqlmap

开源信息介绍:

节前送礼:PDF.NET(PWMIS数据开发框架)V4.5版开源
---------------------分界线-----------------------------------------
文章发布后,热心网友 对我提了一些意见,由于不涉及个人隐私,这里贴上他的原文,如果他看到有异议的话请及时跟我联系。在此感谢他提出的下列意见!
另外大家觉得好请点个推荐,反对的话请留个理由,谢谢。
---------------------分界线-----------------------------------------

shawn(630235793) 1:10:46
大体浏览了一下,感觉还不错

shawn(630235793) 1:14:32
只是博文过于技术细节化而缺少了框架解决的具体问题域、面向的使用者类型,以及整体架构思想与基于关系数据访问框架的差异性描述,让读者一上来很难理解ORM框架的意图。

复:

这些问题的确没有表述清楚,也是因为我的撰文水平有限,没有想到这些问题,也不知道该怎样来表述。

PDF.NET的OQL要解决的主要问题就是让ORM操作能够有SQL那样的灵活性现有大多数ORM框架都是基于CRUD方法级别的操作,还没有像SQL那样具有语言级别的操作,要不然它怎么会被称为4GL呢?现在,我觉得LINQ也具有了这样的能力,而我框架中的OQL,也有这样的能力,所以我大胆的称呼它是一个“ORM Query Laguage”,就像SQL是提供给RDBMS的查询引擎使用一样,OQL是提供给ORM使用的。

所以,OQL面向的使用者是那些喜欢ORM方式来访问数据库,又喜欢SQL的灵活性的技术人员,或者是提供给喜欢其中一种(ORM或者SQL)而不太喜欢另外一种方式的人,让他们有机会体会到另一种方式的优势。

整体思想就是,用面向对象的方式来操作数据库,用OO的方式来写SQL!

PS:OQL与LINQ相比,它更接近于SQL风格,用惯了SQL的人,第一次接触LINQ是很不习惯的,至少我是如此。

shawn(630235793) 2012-10-6 1:39:15
数据访问框架设计的初始设想,首先应该是满足调用层的使用要求,换句话说请求是事务性的,还是非事务性的。如果用户的请求是事务性的,在访问层应该提供事务性的处理机制。而不是应用层自己来对是否事务性进行处理。这些应该放在访问层的对外交互接口处提供给用户来选择比较合理。
所以,框架内部的分层,我感觉还应该再多考虑一下比较好。

回复:

实体层的接口是有的,只是这个图里面不好放置而且不是重点,省略了。
是否使用事物,是放在访问层的对外交互接口处提供给用户来选择的。

shawn(630235793) 2012-10-6 1:47:13
毕竟数据访问框架对于用户来讲就应该屏蔽所有数据库之间操作的差异性,所有与数据库相关的一切操作都封装于内部。对于用户来讲这些都是完全不必去考虑的,只需要提出具体请求是什么就可以了。对于如何解读用户请求、如何根据用户选择的具体数据库,而将请求翻译成底层数据库操作指令等等,这些都是访问层内部机制完成的。

回复:

正如你所说,框架正是这样去做的,OQL屏蔽了SQL不同数据库之间的差异,它会根据具体使用的数据库,去生成本地化的SQL。

广州-海華²º¹²<harvey.cai@qq.com>  17:04:10
跟 linq 有什么相似/区别?
广州-海華²º¹²<harvey.cai@qq.com>  17:05:45
这篇博文里主推的理念,让人想到 linq。

pdf.net 主推的应该是:linq 般好用,但是性能卓越

复:

LINQ是.NET独有的特性,“语言集成查询”,它是集成在.NET语言中的,这是它的先天优势。LINQ基于表达式树,所以它要求必须是.NET平台而且框架版本要求在.NET3.5及以上。

PDF.NET的OQL跟LINQ一样都是ORM框架使用的语言,但是OQL语法更接近于SQL,很容易上手,而且,OQL没有使用.NET的高级特性,这使得它只要是面向对象的语言而且支持泛型即可实现,因此将它移植到C++、Java是完全可能的,而且在.NET平台上,它也仅需.NET2.0版本的支持。

转载于:https://www.cnblogs.com/bluedoctor/archive/2012/10/06/2712699.html

相关文章:

mysql优化 top_Top 20+ MySQL Best Practices【sql优化】

Database operations often tend to be the main bottleneck for most webapplications today. It’s not only the DBA’s (database administrators)that have to worry about these performance issues. We as programmersneed to do our part by structuring tables proper…

hibernate分页

分页从网上考的&#xff0c;好用。这个框架 /** * 用于分页的工具类 * author 莫取网名 */ public class Pager<T> {private List<T> list; //对象记录结果集 private int total 0; // 总记录数 private int limit 10; // 每页显示记录数 private int pages 1; …

Scrum Meeting 博客汇总

Scrum Meeting 博客汇总 一、Scrum Meeting 1. Alpha 第一次 Scrum Meeting第二次 Scrum Meeting第三次 Scrum Meeting第四次 Scrum Meeting第五次 Scrum Meeting第六次 Scrum Meeting第七次 Scrum Meeting第八次 Scrum Meeting第九次 Scrum Meeting第十次 Scrum Meeting第十一…

mysql字符串外键约束_MySQL中的约束函数主外键

/*select语句有6大子句&#xff1a;(1)from子句(2)where子句(3)group by子句(4)having子句(5)order by子句(6)limit子句强调&#xff1a;每一个select的6大子句的顺序是(1)-(6)(1)from子句&#xff0c;后面跟表&#xff0c;视图&#xff0c;多行多列的二维表的结构from意思从哪…

POJ 3683 【2-sat+求一组可行解】.cpp

题意&#xff1a; 有一个牧师要给好几对新婚夫妇准备婚礼.. 已知每对新婚夫妇的有空的时间以及婚礼持续时间.. 问是否可以让每对新婚夫妇都得到该牧师的祝福~ 如果可以就输出YES以及可行解 不可以就输出NO 输入&#xff1a; 一个n 表示有n对新婚夫妇 接下来n行每行a b c 表示在…

Matlab并行编程方法1

相信很多朋友在利用matlab进行计算时&#xff0c;会遇到循环次数过大&#xff0c;或者是单次计算量过大的问题&#xff0c;比如需要计算的数值阵列数据量过大&#xff0c;利用传统的编程方式&#xff0c;跑一次程序几个小时&#xff0c;都要等的急死了是不是呢&#xff1f;如果…

使用postman修改SAP Marketing Cloud contact主数据

Marketing Cloud里的contact主数据&#xff0c;创建成功后也不是所有字段都能够被修改。在Personal data区域的字段是可以被修改的。 比如我在“客户属性”字段里维护了一些值&#xff1a; 然后点保存&#xff1a; 其中第二个batch操作是通过一个roundtrip读取contact模型下多个…

java判断一个对象是否为空_Java中判断对象是否为空的方法的详解

首先来看一下工具StringUtils的判断方法&#xff1a;一种是org.apache.commons.lang3包下的&#xff1b;另一种是org.springframework.util包下的。这两种StringUtils工具类判断对象是否为空是有差距的&#xff1a;StringUtils.isEmpty(CharSequence cs); //org.apache.commons…

解决cocos2dx 3.x 导入cocostudio的ui界面出现错位问题

笔者今天发现导入cocostudio的ui界面时&#xff0c;会有部分控件出现错位的现象&#xff0c;后来我看了一下源码&#xff0c;发现是部分控件是没有继承 Layout类&#xff0c;导致不能设置控件位置造成&#xff0c;原因可以看看cocos2dx 源码的CCSGUIReader.cpp文件的函数&#…

Media Queries

支持情况罗列成如下表&#xff1a; Media Queries 使用 说起CSS3的新特性&#xff0c;就不得不提到 Media Queries 。 本文比较详细&#xff0c;所以很多实际中用不到。所以如果只是想简单了解Media Queries&#xff0c;推荐参考 CSS3 Media Queries 。 CSS2.1定义了 Media 的部…

AndroidStudio脚本命令指定AAR生成目录与版本号

A build.gradle全局常量&#xff1a; //根路径def ROOT_PATH rootProject.rootDir.pathdef GROUP "com.genialsir.mobileads"def MOB_SDK_VERSION_NAME "1.1.2" 复制代码 B 在当前库项目的build.gradle文件中android{}中配置如下&#xff1a; //自定义a…

文本文件 java_简单的用java实现读/写文本文件的示例

简单的用java实现读/写文本文件的示例更新时间&#xff1a;2008年07月26日 13:09:26 作者&#xff1a;同时也展示了如果从输入流中读出来内容写入输出流中(仅限文本流)三个例子可以独立存在&#xff0c;所以根据需要只看其中一个就行了。/** 简单的读/写文本文件的示例* 这里…

7个华丽的基于Canvas的HTML5动画

说起HTML5&#xff0c;可能让你印象更深的是其基于Canvas的动画特效&#xff0c;虽然Canvas在HTML5中的应用并不全都是动画制作&#xff0c;但其动画效果确实让人震惊。本文收集了7个最让人难忘的HTML5 Canvas动画&#xff0c;包括画板、文字、图表等&#xff0c;希望你会喜欢。…

网络工程师课程---4、网络层(网关是什么)

网络工程师课程---4、网络层&#xff08;网关是什么&#xff09; 一、总结 一句话总结&#xff1a; 必在当前网段&#xff1a;你到达另外一个网段必过的一个端口&#xff0c;所以必在当前网段 1、icmp如何检测双向通路的连通性&#xff1f; ping 命令 2、计算机1-65535这些端口…

团队分数分配方法——BY 李栋

作为一个团队&#xff0c;自然是一体的&#xff0c;所以要摒弃个人开发的不良习惯&#xff0c;互帮互助&#xff0c;共同进步。以期望在项目过程中能够不使一个人掉队&#xff0c;不因一个人的工作而使全队进度拖延。所以在分工的基础上还是要互帮互助&#xff0c;团队整体的分…

autowired java_Java 基础之Autowired 是否是自动注入

Java 基础之Autowired 是否是自动注入相信很多人对Autowired 注解理解不深入&#xff0c;或者是认为此注解就是spring的自动注入。相信看完本篇文章&#xff0c;你会有更加不一样的理解。首先我们先看下什么是手动注入&#xff1f;在我们的spring应用程序中&#xff0c;定义多个…

Eclipse进行可视化的GUI开发3大GUI插件

Eclipse进行可视化的GUI开发3大GUI插件 转自http://www.cnblogs.com/NationWoo/archive/2011/05/31/2065176.htmlEclipse并不自带GUI的可视化开发工具&#xff0c;那么如果要在Eclipse进行可视化的GUI开发&#xff0c;就需要依靠第三方的插件。 1. Visual Editor Eclipse官方提…

【BZOJ 4016】[FJOI2014]最短路径树问题

&#xff01; 卡时过了 为什么我的这么慢&#xff1f;姿势不对&#xff1f;&#xff1f;&#xff1f; -->谢 ws_fqk 我的Do&#xff08;num[i]&#xff09;应该用 DO(root) 找了半天的root居然没有用.... define的教训永远忘不了了&#xff01;&#xff01;&#xff01; 优化…

mongodb索引--从55.7秒到毫秒级别

从头开始&#xff0c;验证mongodb的索引的好处。(window7环境下) 下载mongodb服务器&#xff0c;并解压到d盘&#xff0c;并使用以下命令启动 mongod --dbpath D:\mongodb\datamongo客户端Robo 3T 去官网下载&#xff0c;安装准备数据&#xff0c;条数为1亿public static void …

汉字转16进制java_java实现汉字转unicode与汉字转16进制实例

本文实例讲述了java实现汉字转unicode与汉字转16进制的实现方法。分享给大家供大家参考。具体实现方法如下&#xff1a;一、汉字转unicodepublic static String toUnicode(String s){String as[] new String[s.length()];String s1 "";for (int i 0; i < s.len…

使用pytest对django项目单元测试

2019独角兽企业重金招聘Python工程师标准>>> 背景 使用django开发了个人博客&#xff0c;欲单元测试&#xff0c;后遍寻网络&#xff0c;然相关资料甚少&#xff0c;遂成此文&#xff0c;望对汝有所助 环境 pytestpytest-djangopytest-covpytest-htmldjangomixer测试…

jquery通知插件toastr

使用方法3个简单步骤对于其他API调用,看到演示。<link href"toastr.css" rel"stylesheet"/> <script src"toastr.js"></script> //显示一个信息没有标题 toastr.info(Are you the 6 fingered man?)其他选项/显示一个警告,没有…

1282. Game Tree

http://acm.timus.ru/problem.aspx?space1&num1282 简单博弈 注意题意的理解 代码&#xff1a; #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<vector> #include<queue> #include<map> #i…

java web dao_JavaWeb项目,DAO应该怎么写?

有一张字段足够多的表&#xff0c;要对它进行各种各样的查询&#xff1a;根据字段A根据字段B&#xff0c;或者根据字段A和B&#xff0c;或者再加上字段C&#xff0c;然后可能还要加上分页&#xff0c;排序等等的逻辑。现在的项目的DAO层为了满足上面这些需要出现了很多参数列表…

2016 - 1- 21 - RunLoop使用(2016-1-24修改一次)(2016 - 1 - 24 再次修改)

一&#xff1a;常驻线程 &#xff1a;当需要一个线程一直处理一些耗时操作时&#xff0c;可以让它拥有一个RunLoop。具体代码如下&#xff1a; 1.通过给RunloopMode里加源来保证RunLoop不直接退出。 这里有个很重要得知识点&#xff0c;runloop对象如果mode为空得话&#xff…

【BZOJ1016】【Luogu P4208】 [JSOI2008]最小生成树计数 最小生成树,矩阵树定理

蛮不错的一道题&#xff0c;遗憾就遗憾在数据范围会导致暴力轻松跑过。 最小生成树的两个性质&#xff1a; 不同的最小生成树&#xff0c;相同权值使用的边数一定相同。不同的最小生成树&#xff0c;将其都去掉同一个权值的所有边&#xff0c;其连通性一致。这样我们随便跑一个…

Asterisk安装

一、获取asterisk安装包wget http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-1.6.0.tar.gz后面的版本号可以改变&#xff0c;可以安装的版本可以参考http://downloads.asterisk.org/pub/telephony/asterisk/releases/二、解压安装1. [root~]# tar -z…

java编写一个通讯录_java写的通讯录(小玩意)

上次有发个超级菜鸟级别的连接access的小程序受兄弟委托&#xff0c;如今表妹期末了&#xff0c;要写个通讯录于是草草的给写了个&#xff0c;毕竟有一个学期了&#xff0c;所以这次的代码会比较合理些……使用说明:实现技术:java语言,界面采用java swing编程,数据库用access数…

20175203 2018-2019 实验五《网络编程与安全》

20175203 2018-2019 实验五《网络编程与安全》 知识重点&#xff08;摘自实验资料&#xff09; 栈 &#xff1a;(Stack)是一种只允许在表尾插入和删除的线性表&#xff0c;有先进后出&#xff08;FILO&#xff09;&#xff0c;后进先出(LIFO)的特点。允许插入和删除的一端称为栈…

统计文件种类数+获取子shell返回值的其它方法

前言 只是作为一个shell的小小练习和日常统计用&#xff0c;瞎折腾的过程中也是摸到了获取子shell返回值的几种方法&#xff1b; 肯定还有别的方法&#xff0c;跟进程间的通信相关&#xff0c;希望你能提出建议和补充&#xff0c;谢谢~ 完整程序&#xff1a; #! /bin/bash #检查…