是否应去除持久层的JPQL,HQL,EJB QL

BigBlue 2011-05-17
凤舞凰扬 写道
BigBlue 写道

1、表面来看,JPQL与基本SQL的却别确实是数据集和对象这点差异,但本质上,用JPQL时你应该从对象的角度思考问题。不知道楼主抱怨JPQL不能做到对象化是什么意思,那么则样才是完全达到对象化呢?

2、导航是OO的一个特色,oo的时候别老想着Table怎么样,否则要出问题。我承认很多巨大的对象关系网的设计,这是用ood的一个挑战,必须要进行聚合的划分,必须要对关系进行一个取舍。导航关系是方便,但是不能为了方便而滥用。
   不知道楼主的专家职责是什么,是不是只单一职责的意思。我认为关系导航和这个没有关系。

3、封装JPQL?没看到有什么好处,也没有看到有什么好的解决方案。用一下JPA2提供的CriteriaQuery你就知道离了JPQL有多痛苦了。当然,要说没有好的解决方案也不完全,.NET 的Linq就比较完美,当然按楼主的标准,也是SQL的变体,不符合楼主的标准。

其实JPQL、SQL之类就是数据查询的DSL,发挥好一个事物的特点,需要一点智慧。

1. 说JPQL是从对象角度思考问题那完全就是扯淡了。面向对象从来没有QL这样的产物。JPQL的诞生完全是hibernate的HQL以及EJB实体Bean的EJBQL的一个衍生物罢了。QL诞生的根本原因就是从对象到关系的转换有时过于复杂。
2. 表达有误,是单一职责原则(本来是想说专家职责模式,但实质用在这里也不妥),谢谢指正。另外你想说的关系导航是关系映射吧?(ORM=Object Relationship Mapping,为啥会翻译成导航)你这里的说就是最大的一个问题了。实体模型也好,对象也模型也好,都是从概念模型本身转换的。完全不加思考通过对象构造表是最为愚蠢的做法。(这我就不批判你了,那些DBA童鞋会好好指导你的。)
3. 之所以进行封装QL就是为了让使用者更加通过面向对象的做法,比如hibernate的criteria,比如eclipselink中的query和expression.诚然,它们本来就不是解决所有查询问题的(但是可以解决90%以上的实体查询,你以为JPQL又有多强大?),真正复杂的非实体查询还是需要通过SQL的。


1.如果说面向对象从来就没有QL这样的产物,那你就错了。现在有些学校的研究生课程还在讲面向对象数据库,其查询语言是一个叫OQL的来自OMG的东西,这东西可是来自根红苗正的OO家族,实际上JPQL、EJBQL之类的都源自OQL。当然,OQL和SQL长的很像,如果你说他们之间没有渊源那是不可能的。

2.我说的你没听懂,可能是我用词不当,我的意思是关联导航(英文大约是 traversable association in the model)。此论题和DBA无关;
凤舞凰扬 2011-05-22
BigBlue 写道
凤舞凰扬 写道
BigBlue 写道

1、表面来看,JPQL与基本SQL的却别确实是数据集和对象这点差异,但本质上,用JPQL时你应该从对象的角度思考问题。不知道楼主抱怨JPQL不能做到对象化是什么意思,那么则样才是完全达到对象化呢?

2、导航是OO的一个特色,oo的时候别老想着Table怎么样,否则要出问题。我承认很多巨大的对象关系网的设计,这是用ood的一个挑战,必须要进行聚合的划分,必须要对关系进行一个取舍。导航关系是方便,但是不能为了方便而滥用。
   不知道楼主的专家职责是什么,是不是只单一职责的意思。我认为关系导航和这个没有关系。

3、封装JPQL?没看到有什么好处,也没有看到有什么好的解决方案。用一下JPA2提供的CriteriaQuery你就知道离了JPQL有多痛苦了。当然,要说没有好的解决方案也不完全,.NET 的Linq就比较完美,当然按楼主的标准,也是SQL的变体,不符合楼主的标准。

其实JPQL、SQL之类就是数据查询的DSL,发挥好一个事物的特点,需要一点智慧。

1. 说JPQL是从对象角度思考问题那完全就是扯淡了。面向对象从来没有QL这样的产物。JPQL的诞生完全是hibernate的HQL以及EJB实体Bean的EJBQL的一个衍生物罢了。QL诞生的根本原因就是从对象到关系的转换有时过于复杂。
2. 表达有误,是单一职责原则(本来是想说专家职责模式,但实质用在这里也不妥),谢谢指正。另外你想说的关系导航是关系映射吧?(ORM=Object Relationship Mapping,为啥会翻译成导航)你这里的说就是最大的一个问题了。实体模型也好,对象也模型也好,都是从概念模型本身转换的。完全不加思考通过对象构造表是最为愚蠢的做法。(这我就不批判你了,那些DBA童鞋会好好指导你的。)
3. 之所以进行封装QL就是为了让使用者更加通过面向对象的做法,比如hibernate的criteria,比如eclipselink中的query和expression.诚然,它们本来就不是解决所有查询问题的(但是可以解决90%以上的实体查询,你以为JPQL又有多强大?),真正复杂的非实体查询还是需要通过SQL的。


1.如果说面向对象从来就没有QL这样的产物,那你就错了。现在有些学校的研究生课程还在讲面向对象数据库,其查询语言是一个叫OQL的来自OMG的东西,这东西可是来自根红苗正的OO家族,实际上JPQL、EJBQL之类的都源自OQL。当然,OQL和SQL长的很像,如果你说他们之间没有渊源那是不可能的。

2.我说的你没听懂,可能是我用词不当,我的意思是关联导航(英文大约是 traversable association in the model)。此论题和DBA无关;

1.OQL只是面向对象数据库带查询语言,只可以说它是SQL在面向对象数据库中带一种变形罢了。但是有几点必须要明确:它属于面向对象数据库带一部分不代表它和面向对象本身有什么瓜葛;第二,它确实影响了JDOQL和EJBQL带设计思路,但是和它们也完全没有直接关系;第三,OQL本身只是SQL带一种基于面向对象存储查询带一种演化罢了,或者可以这么说它属于SQL基于面向对象存储带一种版本改进(如同C语言中带Struct演化成Class一样);第四,基本上来说,OO数据库没有太多商业价值和实际意义(也许IBM的Infomix算是个异类,现在都和DB2集成了),没有哪个学校讲面向对象会扯到面向对象数据库(只会是讲数据库原理,说关系型数据库时,在引入OO数据库而已)
2.traversable association,蛮少听到这样的术语表述,google了一下,发现果不其然,都是出现在少数的学术文章中。猜测楼上可能是位研究生或者学校教师。不过翻译成关联导航似乎不妥。导航一般用的英文单词是Navigation。如果直译,应该是模型中带可遍历的关联。这些和我们谈的没看出太多关系。附上搜索出的相关文章:http://codeidol.com/csharp/domain-driven-design/A-Model-Expressed-in-Software/Associations/
BigBlue 2011-05-22
凤舞凰扬 写道
1.OQL只是面向对象数据库带查询语言,只可以说它是SQL在面向对象数据库中带一种变形罢了。但是有几点必须要明确:它属于面向对象数据库带一部分不代表它和面向对象本身有什么瓜葛;第二,它确实影响了JDOQL和EJBQL带设计思路,但是和它们也完全没有直接关系;第三,OQL本身只是SQL带一种基于面向对象存储查询带一种演化罢了,或者可以这么说它属于SQL基于面向对象存储带一种版本改进(如同C语言中带Struct演化成Class一样);第四,基本上来说,OO数据库没有太多商业价值和实际意义(也许IBM的Infomix算是个异类,现在都和DB2集成了),没有哪个学校讲面向对象会扯到面向对象数据库(只会是讲数据库原理,说关系型数据库时,在引入OO数据库而已)
2.traversable association,蛮少听到这样的术语表述,google了一下,发现果不其然,都是出现在少数的学术文章中。猜测楼上可能是位研究生或者学校教师。不过翻译成关联导航似乎不妥。导航一般用的英文单词是Navigation。如果直译,应该是模型中带可遍历的关联。这些和我们谈的没看出太多关系。附上搜索出的相关文章:http://codeidol.com/csharp/domain-driven-design/A-Model-Expressed-in-Software/Associations/



1.关于OQL,我想我们已经偏离主题太远了。我不否认OQL确实有很强的SQL味道,我不看中一个东西在血统上的纯正,并且OO本来就是工业界实践的结果,缺乏理论的支撑,根不红,苗不正。我的观点,实用为主,是否OO不重要。
    我想我们的观点没有多大冲突:1)XQL(上述种种QL的统称)之类的还必须要用;2)报表统计的之类可以直接用SQL(都源自Martin Flower的观点,没什么创新);
    不同点是:怎样用XQL。
        我的观点是,直接用即可,因为XQL本身就是业务逻辑的一部分,借助XQL和traversable来达到对对象的访问。对XQL的封装,目前没有看到比较好的方案。
       你的观点是:从面向对象的角度应该是封装构建查询框架,实现JPQL,HQL或者其他ORM以及SQL的映射查询。
    总结:其实不是我不想封装,而是目前Java界没有好的封装办法(还是很欣赏C#的Linq)。与其用一些丑陋的封装,我还不如直接用XQL. 如果你有好的封装方案,欢迎共享一下。

2. 我原来以为traversable在OO中已经是人人皆知的概念,可能我错了。traversable至少在DDD那本书中出现过,也就是讲关联的那个章节。这东西在OO中确实让人既爱又恨。在DDD中traversable是个基本概念,与聚合以及根实体密切相关,那本书讲的很透彻,我不这里就不多啰嗦了。刚看了一下,你给的连接就是DDD的那个章节。DDD是工业界的实战结果,不属于学院派。
    关于我个人,属于工业界,本科没有毕业,目前已经退居二线不做开发了,可能已经有些脱离实际了
javamonkey 2011-05-26
每次导航,都有可能一次或者多次数据库查询,为什么不能把所需要的数据都一次性查出来呢?

而且导航也违背了分层设计原则。看起来也难受啊

BigBlue 2011-05-27
javamonkey 写道
每次导航,都有可能一次或者多次数据库查询,为什么不能把所需要的数据都一次性查出来呢?

而且导航也违背了分层设计原则。看起来也难受啊


1、 导航是否查询数据库,依赖于是否延时加载。你可以一次性加载你所用的数据,一般ORMap都提供这个功能,但这个是持久化层面的东西,和导航不是一个层次的东西;

2.导航怎么违背了分层设计的原则?请说来听听。
  导航是在领域对象之间进行,难道你的领域对象会分在两个层?
  导航是有限度的,一般在聚合内部使用。基本不会影响你的纵向和横向的划分的。

凤舞凰扬 2011-06-02
BigBlue 写道


1.关于OQL,我想我们已经偏离主题太远了。我不否认OQL确实有很强的SQL味道,我不看中一个东西在血统上的纯正,并且OO本来就是工业界实践的结果,缺乏理论的支撑,根不红,苗不正。我的观点,实用为主,是否OO不重要。
    我想我们的观点没有多大冲突:1)XQL(上述种种QL的统称)之类的还必须要用;2)报表统计的之类可以直接用SQL(都源自Martin Flower的观点,没什么创新);
    不同点是:怎样用XQL。
        我的观点是,直接用即可,因为XQL本身就是业务逻辑的一部分,借助XQL和traversable来达到对对象的访问。对XQL的封装,目前没有看到比较好的方案。
       你的观点是:从面向对象的角度应该是封装构建查询框架,实现JPQL,HQL或者其他ORM以及SQL的映射查询。
    总结:其实不是我不想封装,而是目前Java界没有好的封装办法(还是很欣赏C#的Linq)。与其用一些丑陋的封装,我还不如直接用XQL. 如果你有好的封装方案,欢迎共享一下。

2. 我原来以为traversable在OO中已经是人人皆知的概念,可能我错了。traversable至少在DDD那本书中出现过,也就是讲关联的那个章节。这东西在OO中确实让人既爱又恨。在DDD中traversable是个基本概念,与聚合以及根实体密切相关,那本书讲的很透彻,我不这里就不多啰嗦了。刚看了一下,你给的连接就是DDD的那个章节。DDD是工业界的实战结果,不属于学院派。
    关于我个人,属于工业界,本科没有毕业,目前已经退居二线不做开发了,可能已经有些脱离实际了

1. 其实啊,使用XQL也好,对象封装也好,具体的其实无所谓的,我从来不是一种方案的极端支持者的。只是目前XQL被使用得有些不伦不类,为了去得到数据,往往创建非常复杂的对象关联。尤其是做报表,为了获取不同实体中的对象,必须要维系许多对象之间的关联映射。这点,必须要很严肃地指出,这是非常低劣的设计。
2. 也许大家都知道traverable association,我没看过DDD的原书,所以真没有听到这个概念(不过准确说,它并不是概念,只是一种表述而已)。当然了,翻译成关联导航是不合理的,也许楼上没有找到合适的中文翻译吧。它想说明的其实和我前面谈到的是一样的,也就是建立对象关系的可访问(这点蛮类似垃圾回收中的reference,当然那不是面向对象层面)。
凤舞凰扬 2011-06-02
javamonkey 写道
每次导航,都有可能一次或者多次数据库查询,为什么不能把所需要的数据都一次性查出来呢?

而且导航也违背了分层设计原则。看起来也难受啊


  这倒不是问题所在,在很多ORM工具中,都支持batch read,也就是一次性将关联对象读取出来,但对于一对多关系,实际上是一个并集;而多对多关系,就是恐怖的笛卡尔积了。 比如A保护多个B,可能产生的SQL就是select A.*, B.* from A, B where A.id = B.parent_id (当然这个SQL只是参考)。
   问题的实质是A对象必须建立与B对象的关联关系。我举个简单例子,让大家知道问题所在吧。比如在电子商务系统中的会员对象,因为其他对象(主要是非业务对象)都需要通过会员信息去获取。为了方便通过QL获取,所以就会把十数个对象全部关联到会员对象下。会员对象就变成一个巨大冗肿基本无法复用的huge object了。千万不要有人告诉我,可以反向映射解决这个问题。这根本就是一个思维和设计理念的问题,反向映射也一样会遇到类似的问题。
    非常地不幸,我管理的有个项目,因为自己没有关注这些,就变成了这样。
BigBlue 2011-06-04
凤舞凰扬 写道

   问题的实质是A对象必须建立与B对象的关联关系。我举个简单例子,让大家知道问题所在吧。比如在电子商务系统中的会员对象,因为其他对象(主要是非业务对象)都需要通过会员信息去获取。为了方便通过QL获取,所以就会把十数个对象全部关联到会员对象下。会员对象就变成一个巨大冗肿基本无法复用的huge object了。千万不要有人告诉我,可以反向映射解决这个问题。这根本就是一个思维和设计理念的问题,反向映射也一样会遇到类似的问题。
    非常地不幸,我管理的有个项目,因为自己没有关注这些,就变成了这样。

1. 反向映射是个什么概念?
2. 想听听楼上的对huge object的解决办法;
3. 我的想法。对象traverable association确实是个双刃剑,处理起来比较棘手。处理不好,非常容易出现huge object。我的解决方案是,单向关联。会员参与的任何活动的记录(4色建模中的时间-时间段构造型)一般都会引用到会员。
  3.1 我们在基于数据库编程的处理方法是:活动的记录表中一般会保存会员的id.
  3.2 在OO中,我倾向于构建活动的记录对象到会员的单向关联。也就是说会员通过关联访问不到活动的记录,但是活动的记录通过关联可以访问到会员。这样,会员可独立于其它对象存在。其它对象当然要依赖会员,因为会员参与了这些活动,这个信息必须在模型中表达出来。
 
最后,终于找到一个我们概念之间的等价物,traverable association =  通过关联访问
凤舞凰扬 2011-06-10
BigBlue 写道

1. 反向映射是个什么概念?
2. 想听听楼上的对huge object的解决办法;
3. 我的想法。对象traverable association确实是个双刃剑,处理起来比较棘手。处理不好,非常容易出现huge object。我的解决方案是,单向关联。会员参与的任何活动的记录(4色建模中的时间-时间段构造型)一般都会引用到会员。
  3.1 我们在基于数据库编程的处理方法是:活动的记录表中一般会保存会员的id.
  3.2 在OO中,我倾向于构建活动的记录对象到会员的单向关联。也就是说会员通过关联访问不到活动的记录,但是活动的记录通过关联可以访问到会员。这样,会员可独立于其它对象存在。其它对象当然要依赖会员,因为会员参与了这些活动,这个信息必须在模型中表达出来。
 
最后,终于找到一个我们概念之间的等价物,traverable association =  通过关联访问

1. 反向映射就是指在进行对象关系映射(ORM)时,本来是A引用B,通过A查询B,但是因为目前A过于大,就采用B引用A的方式反向映射处理,减少所谓的关系复杂度。
2. Huge Object一个最主要的原因就是完全没有对象关系的概念,完全将表示层或者服务层的逻辑处理反应到实体关系中。举个例子,想查找一个学校的学生,并不意味这学校和学生有什么关联关系(是依赖关系),所以根本不需要在学生对象中引用学校对象。结果很多人做ORM时,根本就不进行对象分析,完全是方便QL查询的关系处理。说到这里,应该清楚如何解决Huge Object了。发生这个问题最为关键的映射是绝大多数系统缺乏有能力的BA/SA,在面向对象设计完全是程序员自己搞(所有的实体应该是来自业务概念模型,而这是BA/SA的职责)
3. traverable association和对象关系的单向与双向没有任何关系(T A指的是关系的可达和递进遍历)。使用所谓的单向关系其实大多只是出于简化目的以及一些特殊情况(比如需要通过JAXB转换成XML,避免对象解析递归问题)。单向关系在ORM中带来的一个重要问题就是需要程序员自己维护关系(这也违背了对象处理的根本目的),简单说,如果A和B的关系是单向的,那么从另外一个方向就需要自己处理和维护。 当然了,你说的这个例子其实和我说的有些不同。从我的角度看,其实会员与活动记录根本不存在任何关联关系(从OO的角度它们是依赖关系,而并非关联关系),ORM处理时根本也不需要做什么映射。(其实从另外一个角度说明就更容易理解了,活动记录的会员可以改么?其实会员实体对于活动记录来说只是一个只读引用的关系,也就是希望通过活动记录比较容易获得会员实体信息,但是如果如果活动记录对象A中引用会员实体B又是什么意思呢?,难道我可以通过A修改B的信息么?修改了又会怎么样?比如调用A.getB().setName("xxx");), 楼上的处理其实是绝大多数一开始就直接使用hibernate的程序员的通病,这样做的目的无非是显示页面想显示活动记录的会员名,但是活动记录表有没有会员名字段的冗余,所以就通过对象关系映射,解决所谓的两次访问问题(绝大多数人也不思考下,两次查询从来就没有被解决,只是实体缓存避免了数据库的两次查询而已)。
   不知道我这样说,楼上各位是否明白了。

BigBlue 2011-06-12
凤舞凰扬 写道

2. Huge Object一个最主要的原因就是完全没有对象关系的概念,完全将表示层或者服务层的逻辑处理反应到实体关系中。举个例子,想查找一个学校的学生,并不意味这学校和学生有什么关联关系(是依赖关系),所以根本不需要在学生对象中引用学校对象。结果很多人做ORM时,根本就不进行对象分析,完全是方便QL查询的关系处理。说到这里,应该清楚如何解决Huge Object了。发生这个问题最为关键的映射是绝大多数系统缺乏有能力的BA/SA,在面向对象设计完全是程序员自己搞(所有的实体应该是来自业务概念模型,而这是BA/SA的职责)


    不是十分清楚,你的模型里面没有学生属于哪个学校的信息,你的表示层或者服务层怎么去处理

凤舞凰扬 写道

3. traverable association和对象关系的单向与双向没有任何关系(T A指的是关系的可达和递进遍历)。使用所谓的单向关系其实大多只是出于简化目的以及一些特殊情况(比如需要通过JAXB转换成XML,避免对象解析递归问题)。单向关系在ORM中带来的一个重要问题就是需要程序员自己维护关系(这也违背了对象处理的根本目的),简单说,如果A和B的关系是单向的,那么从另外一个方向就需要自己处理和维护。 当然了,你说的这个例子其实和我说的有些不同。从我的角度看,其实会员与活动记录根本不存在任何关联关系(从OO的角度它们是依赖关系,而并非关联关系),ORM处理时根本也不需要做什么映射。(其实从另外一个角度说明就更容易理解了,活动记录的会员可以改么?其实会员实体对于活动记录来说只是一个只读引用的关系,也就是希望通过活动记录比较容易获得会员实体信息,但是如果如果活动记录对象A中引用会员实体B又是什么意思呢?,难道我可以通过A修改B的信息么?修改了又会怎么样?比如调用A.getB().setName("xxx");), 楼上的处理其实是绝大多数一开始就直接使用hibernate的程序员的通病,这样做的目的无非是显示页面想显示活动记录的会员名,但是活动记录表有没有会员名字段的冗余,所以就通过对象关系映射,解决所谓的两次访问问题(绝大多数人也不思考下,两次查询从来就没有被解决,只是实体缓存避免了数据库的两次查询而已)。
   不知道我这样说,楼上各位是否明白了。



traverable association里面单向和双和向很有讲究。 单向关系最重要的目的是减少对象间的耦合。不管单向还是双向关系,都需要程序员来维护。

会员与活动记录根本不存在任何关联关系是指什么?你总要有表示的信息。关联是一种表示学生和学校关系的一种办法而已,另外一种就是用学校的ID,你认为有多大差别么?会员名是否需要冗余是需求确定的。解决年n+1问题的解决方案很多。
Global site tag (gtag.js) - Google Analytics