`
zhenjia
  • 浏览: 7104 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

“write less,do more” Hibernate下的JQuery --->HQuery

阅读更多
    但凡所有程序员都有一个希望,那就是用最少的代码完成最多的事情,而热门的语言,流行的框架也一直在这方面做出了颇多的努力。“write less,do more”这是JQuery 的口号,熟悉他的朋友们都知道他的方便之处,而在Hibernate中,我们能不能以最少的代码做最多的事情呢?有的人也许会说 Hibernate已经很方便了,面向对象的持久化操作,强大的级联,等等,但是我们能不能让他再简单一点呢?我的回答:能!
    最长见的Hibernate使用,最简单的需求如下:
    有一张员工表【HR_EMPLOYEE】
现在需要查询HR_EMPLOYEE表里USE_YN 字段值为Y的然后把他变更为N 通常大家的做法也许会象下面这样:
查询方法
public List<HrEmployee> getHrEmployeeListByUse(){
	DetachedCriteria dc=DetachedCriteria.forClass(SysEmployee.class);
	dc.add(RestrictionBuild.eq("useYn", "Y"));
        return this.sysEmployeeDao.findByCriteria(dc);
}


public void updateHrEmployeeUse(){
       List<HrEmployee> empList=this.getHrEmployeeListByUse();
       if(empList!=null&&!empList.isEmpty){
          for(HrEmployee employee:empList){
              employee.setUseYn("N");
              this.sysEmployeeDao.update(employee);
          }
        }
}

然后在action里调用这个Service的updateHrEmployeeUse()方法实现上面的需求,(而且这还有一个批量更新的问题 一条SQL语句可以实现的 现在会出现N*2条SQL)
好了,举了点以前的例子,现在来说说HQuery到底是个什么东西,能怎么帮我们呢,就按上面的例子 看看HQuery怎么写的 代码如下:
$($eq("useYn","Y")).attr(HrEmployee.class,"useYn","N").save();

看见$了没有,没错 JAVA里也是可以用$做类名 方法名的,其他特殊字符则不行,我来解释一下HQuery这段代码里实际有什么操作
首先HQuery需要以选择器(HQuerySelector)进行构造,如果构造方法参数为null则无条件进行全表查询,HQuerySelector无需大家实例 只需要调用以$开头的方法即可构造 上面使用$eq()方法表示构造的选择器使用eq逻辑进行匹配,还有其他方法$gt(),$ge(),$lt(),$le(),$like(),$or(),$and(),$avg(),$max(),$count(),$min(),$distinct(),
$countDistinct(),$order()太多了 写不过来,但是只要加进去构造方法 即可生效。
$($eq("useYn","Y"))//完成选择器的注入 

$($eq("useYn","Y")).attr(HrEmployee.class,"useYn","N")//通过选择器 加载对象 并把useYn属性赋予N值
//attr会自动判断是否需要迭代  

$($eq("useYn","Y")).attr(HrEmployee.class,"useYn","N").save();
//将加载的全部对象的useYn属性赋予N值以后进行保存,注意 此处如果是单表自属性批量更新 会自动判断只发送一条//SQL语句

如此一来 原来那么多行的代码 用HQuery以后一行代码即可实现,从某种概念上来说,有点JQuery的意思,因为我当初设计HQuery时候是按着JQuery来的,因为我很喜欢JQuery 呵呵!
下面再展示一下HQuery还提供了哪些亮点!
以下代码演示了HQuery 支持page分页 && each()方法的迭代 自动将迭代出的对象传至invoke方法提供快速调用
这个each()方法是完全模仿JQuery写的
Page<HrEmployee> empPage=$($eq("useYn","N")).page(HrEmployee.class,0,5);
        List<HrEmployee> empList=empPage.getResultList();
        $(empList).each(new EachAdapter() {
            @Override
            public void invoke(Object o) {
                HrEmployee hrEmployee= (HrEmployee) o;
                System.out.println(hrEmployee.getEmpNameZh());
                System.out.println(hrEmployee.getUseYn());
            }
        });

除了page()方法以外 还提供了.get();.list().array();.value()方法
HrEmployee hrEmployee=$(Long.valueOf(1)).get(HrEmployee.class);
List<HrEmployee> hrEmployeeList=$($eq("useYn","Y")).list(HrEmployee.class);
int count =$($count("id")).returnType(ReturnType.PLAIN).value(HrEmployee.class,Integer.class);
HrEmployee[] hrEmployeeArray=$($eq("useYn","Y")).array(HrEmployee.class);
$($order("id")).list(HrDuty.class);

还有最基本的save() delete()方法
$(o).save();//保存对象
$(o).delete();//删除对象
//以上两个方法 自动判断 是否是数组以及集合 会自动调用相应的方法


需要说明的一点$()方法传HQuerySelector时候需要从数据库get结果才能进行相关操作
而传object时候 不需要从数据库get结果 因为本身就是结果 进行相关操作
$($eq("useYn,"N")).delete(HrEmployee.class);//删除所以USEYN=N的数据

//又一个模仿JQuery.attr()的例子 一个SET 一个GET 同一个入口
List<String> useYnList=$($eq("useYn","Y")).attr(HrEmployee.class,"useYn");//获取属性 并且封装为List 或者Object[] Object类型为属性在JAVA里的类型 自动转换

接着还有回调
//回调在SAVE执行之前
$(hrEmployee).save(HrDuty.class, new BeforeCallback() {
            @Override
       public void invoke() {
            HrEmployee hrEmployee=this.get(hrEmployee.class);
            hrEmployee.setUseYn("Y");

        }
});
//回调在SAVE执行以后
$(hrEmployee).save(HrDuty.class, new AfterCallback() {
            @Override
       public void invoke() {
            HrEmployee hrEmployee=this.get(HrEmployee .class);
            hrEmployee.setUseYn("Y");

        }
});
//回调在SAVE执行之前&之后
$(hrEmployee).save(HrDuty.class, new AllCallback() {
            @Override
       public void invoke() {
            HrEmployee hrEmployee=this.get(HrEmployee .class);
            hrEmployee.setUseYn("Y");

        }
});

一个复杂的包含OR AND orderby条件的查询
$($order("id",false),$eq("dutyId.useYn","Y"),$alias("dutyId","dutyId"),
$or($like("dutyId.dutyNameZh","a"),
$like("dutyId.dutyNameEn","b"),$like("dutyId.dutyNameKo","c"))).each(
HrEmployee.class,new EachAdapter() {
            @Override
            public void invoke(Object o) {
                HrEmployee hrEmployee= (HrEmployee) o;
                System.out.println(hrEmployee.getEmpNameZh());
                //To change body of implemented methods use File | Settings | File Templates.
            }
        } );

生成SQL如下
select
    this_.id as id1_1_,
    this_.CARD_ID as CARD2_1_1_,
    this_.CREATED as CREATED1_1_,
    this_.CREATEDBY as CREATEDBY1_1_,
    this_.DUTY_ID as DUTY16_1_1_,
    this_.EMP_BECOME_DATE as EMP5_1_1_,
    this_.EMP_DIMISSION_DATE as EMP6_1_1_,
    this_.EMP_ENTRY_DATE as EMP7_1_1_,
    this_.EMP_ID as EMP8_1_1_,
    this_.EMP_NAME_EN as EMP9_1_1_,
    this_.EMP_NAME_KO as EMP10_1_1_,
    this_.EMP_NAME_PY as EMP11_1_1_,
    this_.EMP_NAME_ZH as EMP12_1_1_,
    this_.UPDATED as UPDATED1_1_,
    this_.UPDATEDBY as UPDATEDBY1_1_,
    this_.USE_YN as USE15_1_1_,
    dutyid1_.id as id0_0_,
    dutyid1_.CREATED as CREATED0_0_,
    dutyid1_.CREATEDBY as CREATEDBY0_0_,
    dutyid1_.DISPLAY_ORDER as DISPLAY4_0_0_,
    dutyid1_.DUTY_ID as DUTY5_0_0_,
    dutyid1_.DUTY_NAME_EN as DUTY6_0_0_,
    dutyid1_.DUTY_NAME_KO as DUTY7_0_0_,
    dutyid1_.DUTY_NAME_ZH as DUTY8_0_0_,
    dutyid1_.UPDATED as UPDATED0_0_,
    dutyid1_.UPDATEDBY as UPDATEDBY0_0_,
    dutyid1_.USE_YN as USE11_0_0_
from
    HR_EMPLOYEE this_
inner join
    HR_DUTY dutyid1_
        on this_.DUTY_ID=dutyid1_.id
where
    dutyid1_.USE_YN=?
    and (
        (
            dutyid1_.DUTY_NAME_ZH like ?
            or dutyid1_.DUTY_NAME_EN like ?
        )
        or dutyid1_.DUTY_NAME_KO like ?
    )
order by
    this_.id desc

总的来说 HQuery以JQuery的语法实现了Hibernate的基本的简单的一些操作,也能“write less,do more”
但是因为这个作品是3月29日动工的于昨晚完成,所以有可能会有一些不足,也请各位看完以后留下您的宝贵意见。
批评和建议均可~谢谢。
PS:在HQuery设计初期 差点放弃,就因为多线程下的稳定性原因,还好,在梦种想到如何解决多线程下调用的问题,目前已经圆满解决。希望通过这次发帖 得到大家的意见 然后再次改进,并加入的http://www.iteye.com/topic/232885
这个框架中,guiceSide已经开源了,但是这几天整合进去了Freemarker 与HQuery 将暂停几天开源 等最终修改完成的代码通过测试,再上传googlecode:http://code.google.com/p/guice-side/


/*************************超级无敌分割线*************************************/
/*************************已把jar删除 打包时候存在一点bug 暂时删除 待提供配置文件以后能让大家方便集成时候上传 估计得等周末了 SORRY*************************************/
分享到:
评论
32 楼 zhenjia 2009-04-03  
downpour 写道
还是挺有想法的,不过好像除了少敲了几个字母以外,好像看不出什么原创性的东西。不知道能否加上一些动态查询的封装,比如对参数进行判断,当参数为null时,不用在外面再包一层来判断。

不过再怎么说,也比拼SQL的工具来得有想法。

 public Selector $eq(String column, Object value) {
        return $eq(column, value, defaultIgnoreCase, defaultIgnoreBank);
    }

    public Selector $eq(String column, Object value, boolean ignoreCase) {
        return $eq(column, value, ignoreCase, defaultIgnoreBank);
    }

    public Selector $eq(String column, Object value, boolean ignoreCase, boolean ignoreBank) {
        return $createSelector(Condition.EQ, column, value, ignoreCase, ignoreBank, defaultMatch);
    }

看我的构造
boolean ignoreCase, 是否忽略大小写 默认否 除非设置
boolean ignoreBank  是否忽略空值  默认是   为null 时 这个Selector不生效。
这样的判断应该是最基本 一直都有 呵呵。

HQuery里所有的东西都用的Hibernate提供的API 没有自己发明这个轮子
要说创,那么顶多说的上是模仿 不算创 。为的确实就是"少敲了几个字母"


31 楼 downpour 2009-04-03  
还是挺有想法的,不过好像除了少敲了几个字母以外,好像看不出什么原创性的东西。不知道能否加上一些动态查询的封装,比如对参数进行判断,当参数为null时,不用在外面再包一层来判断。

不过再怎么说,也比拼SQL的工具来得有想法。
30 楼 pertghost 2009-04-03  
QBC 一对多时,多方为EAGER加载,查询一方会有自动全连接的问题 不知道楼主是怎么解决这个问题的?
29 楼 zhenjia 2009-04-02  
flyfan 写道
厉害,这样也行,等你发布了好好试试。还有楼主基本每贴都回复了,有耐心

只有交流 才能做出比较完善的东西

在实际开发中不是也一样嘛。

已经上传beta版 有点简陋 但是包括全部功能

等明天弄API给大家看看。
PS:我还不知道那JAR 包能不能跑呢 呵呵。 
28 楼 zhenjia 2009-04-02  
魔力猫咪 写道
把我的框架整合到你那里如何?我的框架只处理HQL语句,和你的功能互补。

是个想法,我的guiceSide有点大,什么破东西都有 总之就是基于google-guice
抛弃了spring 自己实现了webwork的一些亮点的一个乱七八糟的东西,谢谢你看得上。
27 楼 flyfan 2009-04-02  
厉害,这样也行,等你发布了好好试试。还有楼主基本每贴都回复了,有耐心
26 楼 zhenjia 2009-04-02  
已经将HQuery beta版上传,尝新的朋友可下载使用 欢迎提出各种问题,一起完善。
25 楼 魔力猫咪 2009-04-02  
把我的框架整合到你那里如何?我的框架只处理HQL语句,和你的功能互补。
24 楼 zhenjia 2009-04-02  
黑暗浪子 写道
问一下,事务是怎么控制的?还有连接池,二级缓存这些还是和原来一样?
我只大致看了一下你的文章,问的问题也许初级,请见谅~
盼望你的回复,谢谢。

事务采用annotation 在方法上进行声明
@Transactional(type = TransactionType.READ_WRITE)
public void xxx(){
  $().save();
}

类似上面这样的
连接池这个可以自行更换,HQuery如果需要集成到您的项目中 只需要继承HQuery 实现他的抽象方法getSession();
HQuery内部会进行调用,
至于Session的管理方法是由您的项目去定制的,我只关心给我的Session是可用的就OK
缓存这些同理。
它的定位只是一个帮助快速操作HibernateAPI 并且封装一些常用写法 帮助大家而已。
23 楼 zhenjia 2009-04-02  
starfeng 写道
看了一下.可是感觉就像是把除了把Hibernate Critia的所有方法加了个$的前缀外, 然后把引用变成继承外, 没任何不同啊? 是不是我理解错了...

比方:
$eq("useYn","Y") ==> Restrictions.eq("useYn","Y")

继承虽然省去了一个Class名的引用(或对象的引用),比方"Restrictions.", 看起来少写了一点代码,但他带来的高耦合是得不偿失的.

没错,我是把构造Criterion的各种方法都以$来代替再加上逻辑代号
$eq("useYn","Y") ==> Restrictions.eq("useYn","Y")

你说的完全正确 可光这样还不行啊,这样只构造了Criterion,$eq("useYn","Y")他的操作是构造了Selector
Selector里包含了Criterion来进行求值,前面我也说了 HQuery的实现99%基于Criteria
它只希望以JQuery形式的写法和特性来完成一些比较常见的操作,
再一个公司里随时会有新人报道,或者项目里随时会有人员变动,不保证所以人都会Hibernate 或者会Criterion
我封装了Criterion的目的也是希望他们不需要再去看Hibernate的相关文档,看下团队开发指南等就能快速上手,
而且出了问题也不需要他们去考虑如何解决,HQuery提供了自己的异常机制 能清楚的定位是什么地方出的问题。
thanks.
22 楼 zhenjia 2009-04-02  
yuxiangel007 写道
学习一下 ^0^

共同学习,可以给一点建议什么的,帮助我改进。
21 楼 zhenjia 2009-04-02  
Snow_Young 写道
真是看了之后让人眼前一亮啊,大呼一声,本人真的很喜欢这种书写方式呢,没想到Java也可以做到,而且还是在Hibernate上,哈哈。不过我有一个问题,请问性能和多线程方面怎么样呢?另外想用spring托管事务,不知道好实现吗?


如果要用HQuery的话 只需要继承HQuery的一个类,然后 实现他的抽象方法getSession();就好了,至于你是以什么方式管理Session,这HQuery就不关心了。你只要给他Session就好
多线程方面
经过测试没有问题,因为这个问题我差点放弃HQuery,一个线程类资源共享不会冲突与多线程资源共享也不会,放心,这个也可以等周末 我整理出来 给大家下载使用。
20 楼 黑暗浪子 2009-04-02  
问一下,事务是怎么控制的?还有连接池,二级缓存这些还是和原来一样?
我只大致看了一下你的文章,问的问题也许初级,请见谅~
盼望你的回复,谢谢。
19 楼 zhenjia 2009-04-02  
魔力猫咪 写道
zhenjia 写道
魔力猫咪 写道
欢迎竞争。我的仓库猫框架也是用来简化查询的。大家共同努力,让那些丑陋的代码都进垃圾箱吧。

呵呵 我大概看了一下你的 基于HQL 是吧
我的里面没有HQL
都是criteria实现的。

是的。不过我的框架不止HQL,JPA的EQL和SQL也可以处理。

 
但是我如果把HQL SQL这些实现在$()构造里,估计会很丑陋 忑长了那句子。。
18 楼 zhenjia 2009-04-02  
whaosoft 写道
HQuery是什么东东啊???

......是一个没有名的东东
主要用来做Hibernate查询的一个快速帮助工具
17 楼 whaosoft 2009-04-02  
HQuery是什么东东啊???
16 楼 魔力猫咪 2009-04-02  
zhenjia 写道
魔力猫咪 写道
欢迎竞争。我的仓库猫框架也是用来简化查询的。大家共同努力,让那些丑陋的代码都进垃圾箱吧。

呵呵 我大概看了一下你的 基于HQL 是吧
我的里面没有HQL
都是criteria实现的。

是的。不过我的框架不止HQL,JPA的EQL和SQL也可以处理。
15 楼 Snow_Young 2009-04-02  
真是看了之后让人眼前一亮啊,大呼一声,本人真的很喜欢这种书写方式呢,没想到Java也可以做到,而且还是在Hibernate上,哈哈。不过我有一个问题,请问性能和多线程方面怎么样呢?另外想用spring托管事务,不知道好实现吗?
14 楼 starfeng 2009-04-02  
看了一下.可是感觉就像是把除了把Hibernate Critia的所有方法加了个$的前缀外, 然后把引用变成继承外, 没任何不同啊? 是不是我理解错了...

比方:
$eq("useYn","Y") ==> Restrictions.eq("useYn","Y")

继承虽然省去了一个Class名的引用(或对象的引用),比方"Restrictions.", 看起来少写了一点代码,但他带来的高耦合是得不偿失的.
13 楼 yuxiangel007 2009-04-02  
学习一下 ^0^

相关推荐

    jquery 的 万年历

    **jQuery 万年历插件详解** 在网页应用中,日期选择器是一个常见的功能,用于用户输入或选择日期。jQuery 万年历插件提供了一种便捷的方式,为用户提供直观且易于操作的日历界面。本篇文章将深入探讨如何使用jQuery...

    hquery:使用hquery,您可以在命令行的html字符串中找到某些内容

    hquery 在您的推荐行中使用jQuery和Lodash解析HTML。 入门 安装: npm install hquery -g 用法 Usage: hquery [options] [commands] Options: -p if you use hquery in pipe -s if you want parse html string ...

    hQuery.php:一种极其快速的Web抓取工具,可在瞬间眨眼就能解析出数百万字节的无效HTML。 PHP5.3 +,无依赖性

    实际上,根据我的拙劣测试,在某些情况下,它比DOMCrawler快两个数量级,特别是在选择数千个元素时,平均使用的RAM少x2。 参见 。 :light_bulb: 产品特点 快速解析和查找 解析损坏HTML 类似于jQuery的DOM遍历...

    DishServer

    Global $SQLitepath,$SQLitename,$hQuery, $aRow,$SQLite_Data_Path $SQLitepath = "D:\Glutton\" $SQLitename = "Result.db" $SQLite_Data_Path = $SQLitepath & $SQLitename If Not FileExists($SQLitepath) ...

    如何启动操作系统性能计数器编程小程序,C++.net源代码编写,VisualStudio.net

    本文将详细介绍如何通过C++.NET在Visual Studio .NET环境下启动一个性能计数器编程小程序。 1. **了解性能计数器**: - 性能计数器是操作系统提供的一组度量,用于跟踪系统和应用程序的性能。 - 它们分为内置和...

    第1步:使用docker在hquery中转换MOS的第一步

    步骤1 使用docker在hquery中转换MOS的第一步。

    c和c++在windows下获取时间和计算时间差的方法总结.rar

    在Windows环境下,C和C++编程中获取时间与计算时间差是常见的任务,尤其是在性能测试、日志记录或定时任务中。本总结将详细介绍几种常用的方法。 1. **使用&lt;ctime&gt;库** C++标准库中的`&lt;ctime&gt;`提供了基本的时间...

    OtMatlab:Omnitrans 交通规划数据库的 Matlab 接口。-matlab开发

    为了能够使用 Omnitrans 传输数据,可以使用这个 Matlab 接口。... 而 ~OtQueryEof(hquery) disp(OtQueryGetAll(hquery)); OtQueryNext(hquery); 结尾OtQueryClose(hquery); OtQueryFree(hquery); 停止();

    Matlab 链接到 OmniTRANS 5.1:工具包与 OmniTRANS 数据库接口。-matlab开发

    OmniTRANS 的 Matlab 接口。 您可以读写表、执行 SQL 查询以及读写矩阵。... 而 ~OtQueryEof(hquery) disp(OtQueryGetAll(hquery)); OtQueryNext(hquery); 结尾OtQueryClose(hquery); OtQueryFree(hque

    非常好好看的几个登录页面(html,css)2

    &lt;input type="text" id="username" name="username"&gt;&lt;br&gt;&lt;br&gt; &lt;label for="password"&gt;密码:&lt;/label&gt; &lt;input type="password" id="password" name="password"&gt;&lt;br&gt;&lt;br&gt; &lt;button type="submit"&gt;登录&lt;/button&gt; ...

    非常好好看的几个登录页面(html,css)1

    1. `&lt;form&gt;`:定义了一个表单,用户可以在这里输入登录信息。 2. `&lt;input type="text"&gt;` 或 `&lt;input type="email"&gt;`:创建文本输入框,用户输入用户名或邮箱。 3. `&lt;input type="password"&gt;`:创建密码输入框,确保...

    获取CPU占用率的代码

    这段代码使用了PDH(Performance Data Helper)库来获取CPU的% Processor Time计数器,它表示CPU在用户模式和内核模式下执行指令所消耗的时间。`Sleep`函数是为了确保获取的是一个时间段内的平均CPU使用率,而不是...

    query-composer

    注意:目前,在正在进行hQuery开发。 查询 查询编辑器是一个基于Web的应用程序,它提供了用于创建,管理和执行查询的前端。 这些查询是针对查询网关执行的,该查询网关公开查询API,接受查询,针对患者数据运行这些...

    query-gateway

    注意:目前,在正在进行hQuery开发。 查询 查询网关是基于Web的应用程序,它提供了用于执行查询的后端。 查询网关公开查询API,接受查询,针对患者数据运行这些查询,并将查询结果返回给查询编写器。 环境环境 ...

    获取指定进程的内存和cpu使用率

    PDH_HQUERY hQuery; PDH_HCOUNTER hCounter; if (PdhOpenQuery(NULL, NULL, &hQuery) == ERROR_SUCCESS && PdhAddCounter(hQuery, L"\\Process(进程名这里)\% Processor Time", NULL, &hCounter) == ERROR_SUCCESS...

    mixture-data:混合数据

    项目实现功能 这个repo主要放一些公开的数据, 用于开发, 测试, 研究等等... 目录结构说明 buildings: 世界排名前100的建筑 flights: 全年世界航班 literature: 3万条成语,...安装hquery,(npm) 修改update.sh 中的路径

    cpu_usage.rar_CPU usage C++_CPU使用率_CpuUsageInfo使用_c++ cpu使用率_cpu

    3. 创建`PDH_HQUERY`和`PDH_HCOUNTER`句柄,通过`PdhOpenQuery`,`PdhAddCounter`等函数来打开并添加性能计数器。 4. 使用`PdhCollectQueryData`收集性能计数器的值。 5. 解析性能计数器返回的数据,转换为CPU使用率...

    vc获取windows的运行内存,CPU占用,磁盘等信息

    在C++中,我们可以使用`&lt;windows.h&gt;`头文件来获取这些API。 **1. 获取系统名称** 系统名称可以通过`GetComputerName`函数获取。这个函数接受一个缓冲区和一个指针,用于存储计算机名的长度。例如: ```cpp TCHAR ...

    asmtools6.0

    《ASMTools 6.0:深入理解汇编与ASM库的应用》 ASMTools 6.0 是一个专门针对汇编语言(Assembly)和ASM库的工具集,它为开发者提供了丰富的功能,帮助他们在处理底层代码时更加高效。ASM库是一个Java字节码操控和...

    charles 4.2.1 cracked

    win 直接替换掉: 安装目录/lib/ 建议把原charles.jar备份一下

Global site tag (gtag.js) - Google Analytics