该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-02
最后修改:2009-04-03
最长见的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*************************************/ 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-04-02
效率惊人啊,3月29日动工,这么快完成。
看了语法。我有一点建议。 引用 $($eq("useYn","Y")).attr(HrEmployee.class,"useYn","N")
建议改为 引用 $(HrEmployee.class,$eq("useYn","Y")).attr("useYn","N")
引用 $($eq("useYn,"N")).delete();
这里似乎没有指定操作的Class,建议改为 引用 $(HrEmployee.class,$eq("useYn,"N")).delete();
|
|
返回顶楼 | |
发表时间:2009-04-02
jasongreen 写道 效率惊人啊,3月29日动工,这么快完成。
看了语法。我有一点建议。 引用 $($eq("useYn","Y")).attr(HrEmployee.class,"useYn","N")
建议改为 引用 $(HrEmployee.class,$eq("useYn","Y")).attr("useYn","N")
引用 $($eq("useYn,"N")).delete();
这里似乎没有指定操作的Class,建议改为 引用 $(HrEmployee.class,$eq("useYn,"N")).delete();
建议改为 $(HrEmployee.class,$eq("useYn","Y")).attr("useYn","N") 这个问题再设计之初我就很头疼,因为我想尽量和JQuery一样 所以在设计的时候就把HrEmployee.class给舍去,在最后的时候,也就是实际操作之时 才进行传递 那么我的构造函数就统一了 也和JQUERY比较接近 而还有一点 在有的时候是不需要Object.class的 比如你传递的就是一个entity $(empObj).attr("useYn","N") 这时候是无需class的 所以我设计的就是当你传递需要进行数据库加载数据的时候 方法会要求必须要传class,否则可以不传 比如save方法 我后台的方法是这2个 而且类的结构设计的就是当你需要哪个就会只显示哪个方法 不会2个方法一起显示 造成混乱 public void save(Class<? extends IdEntity> entityClass) { evaluation(entityClass,-1,-1); invoke(Persistent.SAVEORUPDATE); } public void save() { invoke(Persistent.SAVEORUPDATE); } 这里似乎没有指定操作的Class,建议改为 $(HrEmployee.class,$eq("useYn,"N")).delete(); 谢谢,帖代码时候忽略了,其实delete方法这时候必须要求传递class,这时 空的参数方法不存在。 |
|
返回顶楼 | |
发表时间:2009-04-02
欢迎竞争。我的仓库猫框架也是用来简化查询的。大家共同努力,让那些丑陋的代码都进垃圾箱吧。
|
|
返回顶楼 | |
发表时间:2009-04-02
zhenjia 写道 这个问题再设计之初我就很头疼,因为我想尽量和JQuery一样 所以在设计的时候就把HrEmployee.class给舍去,在最后的时候,也就是实际操作之时 才进行传递 那么我的构造函数就统一了 也和JQUERY比较接近 我觉得这样设计恰恰不符合JQuery的哲学。 JQuery: $(查询 or 元素 or 元素[]).操作(操作相关参数) current HQuery: $(限制条件 or 对象).操作([类名],操作相关参数) why not : $((类名,限制条件) or 对象 or List or Array).操作(操作相关参数) class 的存在并不影响与JQuery的相似度,即便是影响也只是形的影响,而不是神的影响。反之则对“神似”有影响。 强烈建议 |
|
返回顶楼 | |
发表时间:2009-04-02
jasongreen 写道 zhenjia 写道 这个问题再设计之初我就很头疼,因为我想尽量和JQuery一样 所以在设计的时候就把HrEmployee.class给舍去,在最后的时候,也就是实际操作之时 才进行传递 那么我的构造函数就统一了 也和JQUERY比较接近 我觉得这样设计恰恰不符合JQuery的哲学。 JQuery: $(查询 or 元素 or 元素[]).操作(操作相关参数) current HQuery: $(限制条件 or 对象).操作([类名],操作相关参数) why not : $((类名,限制条件) or 对象 or List or Array).操作(操作相关参数) class 的存在并不影响与JQuery的相似度,即便是影响也只是形的影响,而不是神的影响。反之则对“神似”有影响。 强烈建议 发一下$()的构造吧 protected HQueryGet $(Serializable id) {} //接收如id之类的 Long型构造 也就是出常常用到的byId方法 protected HQueryGet $(Serializable id, Selector... selectors) {}//接收id,+Selector protected HQueryGet $(Selector... selectors) {}//接收Selector protected HQueryLoad $(IdEntity o) {}//接收object protected HQueryLoad $(List<? extends IdEntity> o) {}//接收List<Object> 就少了一个你所说的Class.class这个构造参数 看见我前上个返回HQueryGet了吗 代表着他们的相关操作必须传递Class.class 因为这时候没有实际获取到对象所以需要加载 而后2个返回HQueryLoad 则代表 传进去的object就等于实际获取的对象 所以在相关的操作方法就不需要Class.class 之所以这样就想让$()构造起来比较简单 除了id Selector Object 就好 需要用到相关的class时候 在.后续的方法时会提醒的。 |
|
返回顶楼 | |
发表时间:2009-04-02
真是太方便了,以后要写的东西岂不是很少了。
支持楼主。 |
|
返回顶楼 | |
发表时间:2009-04-02
dino_zhang 写道 我是来当托的。javaeye回帖竟然要先做测试。
先看看。 托????????我可没花钱请托啊 呵呵 |
|
返回顶楼 | |
发表时间:2009-04-02
dino_zhang 写道 我是来当托的。javaeye回帖竟然要先做测试。 先看看。 服了,就是当拖的也不用写这么明白吧。 |
|
返回顶楼 | |
发表时间:2009-04-02
魔力猫咪 写道 欢迎竞争。我的仓库猫框架也是用来简化查询的。大家共同努力,让那些丑陋的代码都进垃圾箱吧。
呵呵 我大概看了一下你的 基于HQL 是吧 我的里面没有HQL 都是criteria实现的。 |
|
返回顶楼 | |