- 浏览: 7096 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
文章分类
最新评论
-
java10000:
我个人觉得组织一个开源项目才能更好的发展,另外,我觉得楼主完全 ...
Q+ 桌面版 web版 web q+的升级版。附带DEMO地址 -
icewubin:
<div class="quote_title ...
“write less,do more” Hibernate下的JQuery --->HQuery -
小豆冰:
欣赏LZ的态度,想法不错,LZ加油。Hibernate Cri ...
“write less,do more” Hibernate下的JQuery --->HQuery -
zhenjia:
<div class="quote_title ...
“write less,do more” Hibernate下的JQuery --->HQuery -
linliangyi2007:
兄弟,我看着有点晕啊,不好意思,水平不够!你的$()是方法吧, ...
“write less,do more” Hibernate下的JQuery --->HQuery
但凡所有程序员都有一个希望,那就是用最少的代码完成最多的事情,而热门的语言,流行的框架也一直在这方面做出了颇多的努力。“write less,do more”这是JQuery 的口号,熟悉他的朋友们都知道他的方便之处,而在Hibernate中,我们能不能以最少的代码做最多的事情呢?有的人也许会说 Hibernate已经很方便了,面向对象的持久化操作,强大的级联,等等,但是我们能不能让他再简单一点呢?我的回答:能!
最长见的Hibernate使用,最简单的需求如下:
有一张员工表【HR_EMPLOYEE】
现在需要查询HR_EMPLOYEE表里USE_YN 字段值为Y的然后把他变更为N 通常大家的做法也许会象下面这样:
查询方法
然后在action里调用这个Service的updateHrEmployeeUse()方法实现上面的需求,(而且这还有一个批量更新的问题 一条SQL语句可以实现的 现在会出现N*2条SQL)
好了,举了点以前的例子,现在来说说HQuery到底是个什么东西,能怎么帮我们呢,就按上面的例子 看看HQuery怎么写的 代码如下:
看见$了没有,没错 JAVA里也是可以用$做类名 方法名的,其他特殊字符则不行,我来解释一下HQuery这段代码里实际有什么操作
首先HQuery需要以选择器(HQuerySelector)进行构造,如果构造方法参数为null则无条件进行全表查询,HQuerySelector无需大家实例 只需要调用以$开头的方法即可构造 上面使用$eq()方法表示构造的选择器使用eq逻辑进行匹配,还有其他方法$gt(),$ge(),$lt(),$le(),$like(),$or(),$and(),$avg(),$max(),$count(),$min(),$distinct(),
$countDistinct(),$order()太多了 写不过来,但是只要加进去构造方法 即可生效。
如此一来 原来那么多行的代码 用HQuery以后一行代码即可实现,从某种概念上来说,有点JQuery的意思,因为我当初设计HQuery时候是按着JQuery来的,因为我很喜欢JQuery 呵呵!
下面再展示一下HQuery还提供了哪些亮点!
以下代码演示了HQuery 支持page分页 && each()方法的迭代 自动将迭代出的对象传至invoke方法提供快速调用
这个each()方法是完全模仿JQuery写的
除了page()方法以外 还提供了.get();.list().array();.value()方法
还有最基本的save() delete()方法
需要说明的一点$()方法传HQuerySelector时候需要从数据库get结果才能进行相关操作
而传object时候 不需要从数据库get结果 因为本身就是结果 进行相关操作
//又一个模仿JQuery.attr()的例子 一个SET 一个GET 同一个入口
接着还有回调
一个复杂的包含OR AND orderby条件的查询
生成SQL如下
总的来说 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/
呵呵 我大概看了一下你的 基于HQL 是吧
我的里面没有HQL
都是criteria实现的。
Hibernate的criteria是有先天缺陷的,这条路不好走啊。
本人曾经研究并实践QBC和QBDC也有1年多,近来还是逐渐转向HQL,原因极其繁杂一言难尽啊。
$()是HQuery的方法
是需要继承HQuery然后就会有一系列的支持
据我所知 $可以用做class name method name
保证每个$()操作的是一个属于自己的对象(也就是新的对象) 就好了。
HQuery里没有用到FetchMode.EAGER 类似这样的代码
关联的持久化类全部是
Criteria.createAlias()
关于这个问题,我举个例子:
@Entity
@Table(name = "EDUCATION")
public class Education implements Serializable {
private static final long serialVersionUID = -7255604367478847959L;
private String uuid;
private Employee employee;
private Date date;
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the employee
*/
@ManyToOne
@JoinColumn(name = "EMPLOYEE_UUID")
public Employee getEmployee() {
return employee;
}
/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
/**
* @return the date
*/
@Column(name = "EDU_DATE")
@Temporal(TemporalType.DATE)
public Date getDate() {
return date;
}
/**
* @param date the date to set
*/
public void setDate(Date date) {
this.date = date;
}
}
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
private static final long serialVersionUID = -2543903410221123484L;
private String uuid;
private String name;
private List<Education> educations = new ArrayList<Education>();
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the name
*/
@Column(name = "NAME")
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the educations
*/
@OneToMany(fetch=FetchType.EAGER,targetEntity=Education.class)
@JoinColumn(name = "EMPLOYEE_UUID")
public List<Education> getEducations() {
return educations;
}
/**
* @param educations the educations to set
*/
public void setEducations(List<Education> educations) {
this.educations = educations;
}
}
测试代码如下:
public class test {
public static void main(String[] arg) {
try {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Employee employee = new Employee();
employee.setName("simon");
session.save(employee);
Education edu1 = new Education();
edu1.setDate(new Date());
edu1.setEmployee(employee);
session.save(edu1);
Education edu2 = new Education();
edu2.setDate(new Date());
edu2.setEmployee(employee);
session.save(edu2);
session.flush();
tx.commit();
Criteria crit = session.createCriteria(Employee.class);
crit.add(Restrictions.eq("name", "simon"));
List<Employee> list = crit.list();
} catch (Exception e) {
e.printStackTrace();
}
}
}
List<Employee> list = crit.list(); 这个代码生成的SQL如下,ORACLE 10g的语句
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_, EDUCATION educations2_ where this_.UUID=educations2_.EMPLOYEE_UUID(+) and this_.NAME=?
mySQL 下的语句:
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_ left outer join EDUCATION educations2_ on this_.UUID=educations2_.EMPLOYEE_UUID where this_.NAME='simon'
LIST 结果集有两条记录,这个显然不是我们想要的结果,这个例子在业务层面可能不恰当,但感觉这是一个QBC的处理问题,想请教下,如果有这种EAGER加载的需求,如何用QBC得到正确的结果?
如果是Criteria.createAlias() 这样处理,是不是在查询时先得把所有有关联的对象都要起个别名?
Criteria.createAlias("column","asName",joinType) ;有这样一个方法
你试试。一般 set的我都延迟加载的
HQuery里没有用到FetchMode.EAGER 类似这样的代码
关联的持久化类全部是
Criteria.createAlias()
关于这个问题,我举个例子:
@Entity
@Table(name = "EDUCATION")
public class Education implements Serializable {
private static final long serialVersionUID = -7255604367478847959L;
private String uuid;
private Employee employee;
private Date date;
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the employee
*/
@ManyToOne
@JoinColumn(name = "EMPLOYEE_UUID")
public Employee getEmployee() {
return employee;
}
/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
/**
* @return the date
*/
@Column(name = "EDU_DATE")
@Temporal(TemporalType.DATE)
public Date getDate() {
return date;
}
/**
* @param date the date to set
*/
public void setDate(Date date) {
this.date = date;
}
}
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
private static final long serialVersionUID = -2543903410221123484L;
private String uuid;
private String name;
private List<Education> educations = new ArrayList<Education>();
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the name
*/
@Column(name = "NAME")
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the educations
*/
@OneToMany(fetch=FetchType.EAGER,targetEntity=Education.class)
@JoinColumn(name = "EMPLOYEE_UUID")
public List<Education> getEducations() {
return educations;
}
/**
* @param educations the educations to set
*/
public void setEducations(List<Education> educations) {
this.educations = educations;
}
}
测试代码如下:
public class test {
public static void main(String[] arg) {
try {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Employee employee = new Employee();
employee.setName("simon");
session.save(employee);
Education edu1 = new Education();
edu1.setDate(new Date());
edu1.setEmployee(employee);
session.save(edu1);
Education edu2 = new Education();
edu2.setDate(new Date());
edu2.setEmployee(employee);
session.save(edu2);
session.flush();
tx.commit();
Criteria crit = session.createCriteria(Employee.class);
crit.add(Restrictions.eq("name", "simon"));
List<Employee> list = crit.list();
} catch (Exception e) {
e.printStackTrace();
}
}
}
List<Employee> list = crit.list(); 这个代码生成的SQL如下,ORACLE 10g的语句
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_, EDUCATION educations2_ where this_.UUID=educations2_.EMPLOYEE_UUID(+) and this_.NAME=?
mySQL 下的语句:
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_ left outer join EDUCATION educations2_ on this_.UUID=educations2_.EMPLOYEE_UUID where this_.NAME='simon'
LIST 结果集有两条记录,这个显然不是我们想要的结果,这个例子在业务层面可能不恰当,但感觉这是一个QBC的处理问题,想请教下,如果有这种EAGER加载的需求,如何用QBC得到正确的结果?
如果是Criteria.createAlias() 这样处理,是不是在查询时先得把所有有关联的对象都要起个别名?
恩 对于jquery的使用者来说,
应该对HQuery的语法会比较容易接受。
会进一步完善的。
我赞同stevensinclair的观点:不为了少写单词,引入另外一种“语法”。楼主的改造,有些类似一种新的语法了(区别与java的语法)。
我赞同楼主创新精神、效率精神:write less, do more!
确实很多代码非常类似,又不好抽取。呵呵,但换个思路,大部分还是能够抽取出来的。比如Spring的jdbc template。呵呵,Spring之前,我当时也搞了个template。很多Jdbc操作代码变的简单了。
我有个建议和楼主探讨一下:
使用类似JAVA API的方式,提供这种write less, do more!
这样的好处是:
1,让广大java初学者不至于迷茫,也让我这样爱偷懒的编程者(我也不大喜欢学习新语法)有福;
2,用有意义的词做api,比这种语法更有表现意义。(你的语法已经有表现意义了,我只是觉得可以更有表现意义些)
3,用api调试起来会更方便一些。
例如您的update例子,是否可以这么改造一下(也不知道是否对,期望指正):
1.对于这种“新的语法”确实对于一些人来说 需要花时间去理解去学习,但是对于JQuery用户来说我觉得能迅速掌握,包括当初我开发这个的时候基本的方法名称,参数传递方式都是按照JQuery来的
2.HQuery现在我还在内部测试阶段,基本功能都已经完成,准备看看有没有什么性能,线程,和使用的优化,接着生成JavaDocs 让大家能尽快试用,至于有用的词语可待我API出来以后大家看看 并提建议。
3.update例子,我个人觉得 如果改造成传2个参数的Collection entities, DetachedCriteria dc方法 那么又回到最初的模式去了,dc又需要自己构造,entities也同样。而且又有一部分人需要学习dc的构造
类似如上代码 HQuery
省去2点 1 DC的构建在$eq("deptName","HQuery")已经完成
2 entities在save方法执行前会去判断是否需要从数据库进行加载 这也是自动完成
3 至于SAVE方法调用的是session.saveOrUpdate();这也是我个人使用的原因 因为大部分时候我没有用到session.save() session.update() 而是直接saveOrUpdate 而在封装时候以save方法名称而已
谢谢你的建议
我赞同stevensinclair的观点:不为了少写单词,引入另外一种“语法”。楼主的改造,有些类似一种新的语法了(区别与java的语法)。
我赞同楼主创新精神、效率精神:write less, do more!
确实很多代码非常类似,又不好抽取。呵呵,但换个思路,大部分还是能够抽取出来的。比如Spring的jdbc template。呵呵,Spring之前,我当时也搞了个template。很多Jdbc操作代码变的简单了。
我有个建议和楼主探讨一下:
使用类似JAVA API的方式,提供这种write less, do more!
这样的好处是:
1,让广大java初学者不至于迷茫,也让我这样爱偷懒的编程者(我也不大喜欢学习新语法)有福;
2,用有意义的词做api,比这种语法更有表现意义。(你的语法已经有表现意义了,我只是觉得可以更有表现意义些)
3,用api调试起来会更方便一些。
例如您的update例子,是否可以这么改造一下(也不知道是否对,期望指正):
理解
HQuery的最初设计也是解决部门内部开发的问题。
再一个就是让项目做到尽量简洁.
再者,同样的事情 少写几行代码不是更好。
因为设计的另一个
[url="http://www.iteye.com/topic/232885" ]guiceSide[/url]也是为了简洁.
但是如果要集成的话也很简单,它可以代替dao.
对于$这个 在JAVA里出现 仁者见仁了
我没有理解你的意思
不过 你可以给出伪代码。谢谢
HQuery里没有用到FetchMode.EAGER 类似这样的代码
关联的持久化类全部是
Criteria.createAlias()
最长见的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*************************************/
评论
52 楼
icewubin
2009-04-23
zhenjia 写道
魔力猫咪 写道
欢迎竞争。我的仓库猫框架也是用来简化查询的。大家共同努力,让那些丑陋的代码都进垃圾箱吧。
呵呵 我大概看了一下你的 基于HQL 是吧
我的里面没有HQL
都是criteria实现的。
Hibernate的criteria是有先天缺陷的,这条路不好走啊。
本人曾经研究并实践QBC和QBDC也有1年多,近来还是逐渐转向HQL,原因极其繁杂一言难尽啊。
51 楼
小豆冰
2009-04-22
欣赏LZ的态度,想法不错,LZ加油。
Hibernate Criteria其实是从SQL到relation algebra的回归,把relation algebra实践化了,在思维方式上和结构化的SQL,HQL有所不同。我觉得LZ可以从relation algebra的角度上考虑一下,其实不用完全拘泥于Hibernate的模式。
Hibernate Criteria其实是从SQL到relation algebra的回归,把relation algebra实践化了,在思维方式上和结构化的SQL,HQL有所不同。我觉得LZ可以从relation algebra的角度上考虑一下,其实不用完全拘泥于Hibernate的模式。
50 楼
zhenjia
2009-04-16
linliangyi2007 写道
兄弟,我看着有点晕啊,不好意思,水平不够!
你的$()是方法吧,如果$是类名,那么构造函数也要用个new $()吧,否则写在java里面,不报错?
这个看不明白:)是不是要将类继承HQuery呢?
你的$()是方法吧,如果$是类名,那么构造函数也要用个new $()吧,否则写在java里面,不报错?
这个看不明白:)是不是要将类继承HQuery呢?
$()是HQuery的方法
是需要继承HQuery然后就会有一系列的支持
据我所知 $可以用做class name method name
49 楼
linliangyi2007
2009-04-14
兄弟,我看着有点晕啊,不好意思,水平不够!
你的$()是方法吧,如果$是类名,那么构造函数也要用个new $()吧,否则写在java里面,不报错?
这个看不明白:)是不是要将类继承HQuery呢?
你的$()是方法吧,如果$是类名,那么构造函数也要用个new $()吧,否则写在java里面,不报错?
这个看不明白:)是不是要将类继承HQuery呢?
48 楼
penciltim
2009-04-13
可以简单地认为楼主的所做的工作是jQuery化的通用DAO么?
我认为写两次代码来进行一项查询更新工作和一次写完分别不大,
与其写在一起,不如加入点代码冗余使得耦合更加松散.
另外,由于对数据库同样hit了两次,性能方面是没有改变的
我认为写两次代码来进行一项查询更新工作和一次写完分别不大,
与其写在一起,不如加入点代码冗余使得耦合更加松散.
另外,由于对数据库同样hit了两次,性能方面是没有改变的
47 楼
eric860
2009-04-09
想法挺有意思的,抽空看看。
46 楼
foolfly
2009-04-08
减少代码量,偷懒还是真理
45 楼
zhenjia
2009-04-07
femto 写道
不错,能讲讲多线程是怎么处理的吗?
保证每个$()操作的是一个属于自己的对象(也就是新的对象) 就好了。
44 楼
zhenjia
2009-04-07
pertghost 写道
zhenjia 写道
pertghost 写道
QBC 一对多时,多方为EAGER加载,查询一方会有自动全连接的问题 不知道楼主是怎么解决这个问题的?
HQuery里没有用到FetchMode.EAGER 类似这样的代码
setFetchMode("orders",FetchMode.EAGER)
关联的持久化类全部是
Criteria.createAlias()
关于这个问题,我举个例子:
@Entity
@Table(name = "EDUCATION")
public class Education implements Serializable {
private static final long serialVersionUID = -7255604367478847959L;
private String uuid;
private Employee employee;
private Date date;
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the employee
*/
@ManyToOne
@JoinColumn(name = "EMPLOYEE_UUID")
public Employee getEmployee() {
return employee;
}
/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
/**
* @return the date
*/
@Column(name = "EDU_DATE")
@Temporal(TemporalType.DATE)
public Date getDate() {
return date;
}
/**
* @param date the date to set
*/
public void setDate(Date date) {
this.date = date;
}
}
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
private static final long serialVersionUID = -2543903410221123484L;
private String uuid;
private String name;
private List<Education> educations = new ArrayList<Education>();
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the name
*/
@Column(name = "NAME")
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the educations
*/
@OneToMany(fetch=FetchType.EAGER,targetEntity=Education.class)
@JoinColumn(name = "EMPLOYEE_UUID")
public List<Education> getEducations() {
return educations;
}
/**
* @param educations the educations to set
*/
public void setEducations(List<Education> educations) {
this.educations = educations;
}
}
测试代码如下:
public class test {
public static void main(String[] arg) {
try {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Employee employee = new Employee();
employee.setName("simon");
session.save(employee);
Education edu1 = new Education();
edu1.setDate(new Date());
edu1.setEmployee(employee);
session.save(edu1);
Education edu2 = new Education();
edu2.setDate(new Date());
edu2.setEmployee(employee);
session.save(edu2);
session.flush();
tx.commit();
Criteria crit = session.createCriteria(Employee.class);
crit.add(Restrictions.eq("name", "simon"));
List<Employee> list = crit.list();
} catch (Exception e) {
e.printStackTrace();
}
}
}
List<Employee> list = crit.list(); 这个代码生成的SQL如下,ORACLE 10g的语句
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_, EDUCATION educations2_ where this_.UUID=educations2_.EMPLOYEE_UUID(+) and this_.NAME=?
mySQL 下的语句:
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_ left outer join EDUCATION educations2_ on this_.UUID=educations2_.EMPLOYEE_UUID where this_.NAME='simon'
LIST 结果集有两条记录,这个显然不是我们想要的结果,这个例子在业务层面可能不恰当,但感觉这是一个QBC的处理问题,想请教下,如果有这种EAGER加载的需求,如何用QBC得到正确的结果?
如果是Criteria.createAlias() 这样处理,是不是在查询时先得把所有有关联的对象都要起个别名?
Criteria.createAlias("column","asName",joinType) ;有这样一个方法
你试试。一般 set的我都延迟加载的
43 楼
pertghost
2009-04-07
zhenjia 写道
pertghost 写道
QBC 一对多时,多方为EAGER加载,查询一方会有自动全连接的问题 不知道楼主是怎么解决这个问题的?
HQuery里没有用到FetchMode.EAGER 类似这样的代码
setFetchMode("orders",FetchMode.EAGER)
关联的持久化类全部是
Criteria.createAlias()
关于这个问题,我举个例子:
@Entity
@Table(name = "EDUCATION")
public class Education implements Serializable {
private static final long serialVersionUID = -7255604367478847959L;
private String uuid;
private Employee employee;
private Date date;
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the employee
*/
@ManyToOne
@JoinColumn(name = "EMPLOYEE_UUID")
public Employee getEmployee() {
return employee;
}
/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
/**
* @return the date
*/
@Column(name = "EDU_DATE")
@Temporal(TemporalType.DATE)
public Date getDate() {
return date;
}
/**
* @param date the date to set
*/
public void setDate(Date date) {
this.date = date;
}
}
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
private static final long serialVersionUID = -2543903410221123484L;
private String uuid;
private String name;
private List<Education> educations = new ArrayList<Education>();
/**
* @return the uuid
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "UUID", length = 32)
public String getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return the name
*/
@Column(name = "NAME")
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the educations
*/
@OneToMany(fetch=FetchType.EAGER,targetEntity=Education.class)
@JoinColumn(name = "EMPLOYEE_UUID")
public List<Education> getEducations() {
return educations;
}
/**
* @param educations the educations to set
*/
public void setEducations(List<Education> educations) {
this.educations = educations;
}
}
测试代码如下:
public class test {
public static void main(String[] arg) {
try {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Employee employee = new Employee();
employee.setName("simon");
session.save(employee);
Education edu1 = new Education();
edu1.setDate(new Date());
edu1.setEmployee(employee);
session.save(edu1);
Education edu2 = new Education();
edu2.setDate(new Date());
edu2.setEmployee(employee);
session.save(edu2);
session.flush();
tx.commit();
Criteria crit = session.createCriteria(Employee.class);
crit.add(Restrictions.eq("name", "simon"));
List<Employee> list = crit.list();
} catch (Exception e) {
e.printStackTrace();
}
}
}
List<Employee> list = crit.list(); 这个代码生成的SQL如下,ORACLE 10g的语句
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_, EDUCATION educations2_ where this_.UUID=educations2_.EMPLOYEE_UUID(+) and this_.NAME=?
mySQL 下的语句:
select this_.UUID as UUID0_1_, this_.NAME as NAME0_1_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_3_, educations2_.UUID as UUID3_, educations2_.UUID as UUID1_0_, educations2_.EDU_DATE as EDU2_1_0_, educations2_.EMPLOYEE_UUID as EMPLOYEE3_1_0_ from EMPLOYEE this_ left outer join EDUCATION educations2_ on this_.UUID=educations2_.EMPLOYEE_UUID where this_.NAME='simon'
LIST 结果集有两条记录,这个显然不是我们想要的结果,这个例子在业务层面可能不恰当,但感觉这是一个QBC的处理问题,想请教下,如果有这种EAGER加载的需求,如何用QBC得到正确的结果?
如果是Criteria.createAlias() 这样处理,是不是在查询时先得把所有有关联的对象都要起个别名?
42 楼
femto
2009-04-07
不错,能讲讲多线程是怎么处理的吗?
41 楼
zhenjia
2009-04-05
nbkangta 写道
期待进一步完善,我觉得这个对于熟悉jquery的java的开发者来说,会是一个很好的开源项目
恩 对于jquery的使用者来说,
应该对HQuery的语法会比较容易接受。
会进一步完善的。
40 楼
zhenjia
2009-04-05
metadmin 写道
我赞同stevensinclair的观点:不为了少写单词,引入另外一种“语法”。楼主的改造,有些类似一种新的语法了(区别与java的语法)。
我赞同楼主创新精神、效率精神:write less, do more!
确实很多代码非常类似,又不好抽取。呵呵,但换个思路,大部分还是能够抽取出来的。比如Spring的jdbc template。呵呵,Spring之前,我当时也搞了个template。很多Jdbc操作代码变的简单了。
我有个建议和楼主探讨一下:
使用类似JAVA API的方式,提供这种write less, do more!
这样的好处是:
1,让广大java初学者不至于迷茫,也让我这样爱偷懒的编程者(我也不大喜欢学习新语法)有福;
2,用有意义的词做api,比这种语法更有表现意义。(你的语法已经有表现意义了,我只是觉得可以更有表现意义些)
3,用api调试起来会更方便一些。
例如您的update例子,是否可以这么改造一下(也不知道是否对,期望指正):
public static void update( Collection entities, DetachedCriteria dc ) { ... }
1.对于这种“新的语法”确实对于一些人来说 需要花时间去理解去学习,但是对于JQuery用户来说我觉得能迅速掌握,包括当初我开发这个的时候基本的方法名称,参数传递方式都是按照JQuery来的
2.HQuery现在我还在内部测试阶段,基本功能都已经完成,准备看看有没有什么性能,线程,和使用的优化,接着生成JavaDocs 让大家能尽快试用,至于有用的词语可待我API出来以后大家看看 并提建议。
3.update例子,我个人觉得 如果改造成传2个参数的Collection entities, DetachedCriteria dc方法 那么又回到最初的模式去了,dc又需要自己构造,entities也同样。而且又有一部分人需要学习dc的构造
类似如上代码 HQuery
$($eq("deptName","HQuery")).save(Entity.class);
省去2点 1 DC的构建在$eq("deptName","HQuery")已经完成
2 entities在save方法执行前会去判断是否需要从数据库进行加载 这也是自动完成
3 至于SAVE方法调用的是session.saveOrUpdate();这也是我个人使用的原因 因为大部分时候我没有用到session.save() session.update() 而是直接saveOrUpdate 而在封装时候以save方法名称而已
谢谢你的建议
39 楼
metadmin
2009-04-04
stevensinclair 写道
我相信大家不会为了少写几个单词而使用你再次封装的东西 而且源码里跳出个$是不是有点别扭
我只喜欢页面上出现${} ,至于后台 我想那就算了
另 我不是打击你啊 我只是说我的看法 没恶意
我只喜欢页面上出现${} ,至于后台 我想那就算了
另 我不是打击你啊 我只是说我的看法 没恶意
我赞同stevensinclair的观点:不为了少写单词,引入另外一种“语法”。楼主的改造,有些类似一种新的语法了(区别与java的语法)。
我赞同楼主创新精神、效率精神:write less, do more!
确实很多代码非常类似,又不好抽取。呵呵,但换个思路,大部分还是能够抽取出来的。比如Spring的jdbc template。呵呵,Spring之前,我当时也搞了个template。很多Jdbc操作代码变的简单了。
我有个建议和楼主探讨一下:
使用类似JAVA API的方式,提供这种write less, do more!
这样的好处是:
1,让广大java初学者不至于迷茫,也让我这样爱偷懒的编程者(我也不大喜欢学习新语法)有福;
2,用有意义的词做api,比这种语法更有表现意义。(你的语法已经有表现意义了,我只是觉得可以更有表现意义些)
3,用api调试起来会更方便一些。
例如您的update例子,是否可以这么改造一下(也不知道是否对,期望指正):
public static void update( Collection entities, DetachedCriteria dc ) { ... }
38 楼
nbkangta
2009-04-04
期待进一步完善,我觉得这个对于熟悉jquery的java的开发者来说,会是一个很好的开源项目
37 楼
zhenjia
2009-04-03
stevensinclair 写道
楼主 你的东东我大致了解了下 个人认为你的东西只限于项目组内推广使用 我相信大家不会为了少写几个单词而使用你再次封装的东西 而且源码里跳出个$是不是有点别扭
我只喜欢页面上出现${} ,至于后台 我想那就算了
另 我不是打击你啊 我只是说我的看法 没恶意
我只喜欢页面上出现${} ,至于后台 我想那就算了
另 我不是打击你啊 我只是说我的看法 没恶意
理解
HQuery的最初设计也是解决部门内部开发的问题。
再一个就是让项目做到尽量简洁.
再者,同样的事情 少写几行代码不是更好。
因为设计的另一个
[url="http://www.iteye.com/topic/232885" ]guiceSide[/url]也是为了简洁.
但是如果要集成的话也很简单,它可以代替dao.
对于$这个 在JAVA里出现 仁者见仁了
36 楼
stevensinclair
2009-04-03
楼主 你的东东我大致了解了下 个人认为你的东西只限于项目组内推广使用 我相信大家不会为了少写几个单词而使用你再次封装的东西 而且源码里跳出个$是不是有点别扭
我只喜欢页面上出现${} ,至于后台 我想那就算了
另 我不是打击你啊 我只是说我的看法 没恶意
我只喜欢页面上出现${} ,至于后台 我想那就算了
另 我不是打击你啊 我只是说我的看法 没恶意
35 楼
zhenjia
2009-04-03
xiao0556 写道
如果能做到写查询语句 全部有代码提示就好了,包括要查的主对象下的所有字段
我没有理解你的意思
不过 你可以给出伪代码。谢谢
34 楼
xiao0556
2009-04-03
如果能做到写查询语句 全部有代码提示就好了,包括要查的主对象下的所有字段
33 楼
zhenjia
2009-04-03
pertghost 写道
QBC 一对多时,多方为EAGER加载,查询一方会有自动全连接的问题 不知道楼主是怎么解决这个问题的?
HQuery里没有用到FetchMode.EAGER 类似这样的代码
setFetchMode("orders",FetchMode.EAGER)
关联的持久化类全部是
Criteria.createAlias()
相关推荐
**jQuery 万年历插件详解** 在网页应用中,日期选择器是一个常见的功能,用于用户输入或选择日期。jQuery 万年历插件提供了一种便捷的方式,为用户提供直观且易于操作的日历界面。本篇文章将深入探讨如何使用jQuery...
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 ...
实际上,根据我的拙劣测试,在某些情况下,它比DOMCrawler快两个数量级,特别是在选择数千个元素时,平均使用的RAM少x2。 参见 。 :light_bulb: 产品特点 快速解析和查找 解析损坏HTML 类似于jQuery的DOM遍历...
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在Visual Studio .NET环境下启动一个性能计数器编程小程序。 1. **了解性能计数器**: - 性能计数器是操作系统提供的一组度量,用于跟踪系统和应用程序的性能。 - 它们分为内置和...
步骤1 使用docker在hquery中转换MOS的第一步。
在Windows环境下,C和C++编程中获取时间与计算时间差是常见的任务,尤其是在性能测试、日志记录或定时任务中。本总结将详细介绍几种常用的方法。 1. **使用<ctime>库** C++标准库中的`<ctime>`提供了基本的时间...
为了能够使用 Omnitrans 传输数据,可以使用这个 Matlab 接口。... 而 ~OtQueryEof(hquery) disp(OtQueryGetAll(hquery)); OtQueryNext(hquery); 结尾OtQueryClose(hquery); OtQueryFree(hquery); 停止();
OmniTRANS 的 Matlab 接口。 您可以读写表、执行 SQL 查询以及读写矩阵。... 而 ~OtQueryEof(hquery) disp(OtQueryGetAll(hquery)); OtQueryNext(hquery); 结尾OtQueryClose(hquery); OtQueryFree(hque
<input type="text" id="username" name="username"><br><br> <label for="password">密码:</label> <input type="password" id="password" name="password"><br><br> <button type="submit">登录</button> ...
1. `<form>`:定义了一个表单,用户可以在这里输入登录信息。 2. `<input type="text">` 或 `<input type="email">`:创建文本输入框,用户输入用户名或邮箱。 3. `<input type="password">`:创建密码输入框,确保...
这段代码使用了PDH(Performance Data Helper)库来获取CPU的% Processor Time计数器,它表示CPU在用户模式和内核模式下执行指令所消耗的时间。`Sleep`函数是为了确保获取的是一个时间段内的平均CPU使用率,而不是...
注意:目前,在正在进行hQuery开发。 查询 查询编辑器是一个基于Web的应用程序,它提供了用于创建,管理和执行查询的前端。 这些查询是针对查询网关执行的,该查询网关公开查询API,接受查询,针对患者数据运行这些...
注意:目前,在正在进行hQuery开发。 查询 查询网关是基于Web的应用程序,它提供了用于执行查询的后端。 查询网关公开查询API,接受查询,针对患者数据运行这些查询,并将查询结果返回给查询编写器。 环境环境 ...
PDH_HQUERY hQuery; PDH_HCOUNTER hCounter; if (PdhOpenQuery(NULL, NULL, &hQuery) == ERROR_SUCCESS && PdhAddCounter(hQuery, L"\\Process(进程名这里)\% Processor Time", NULL, &hCounter) == ERROR_SUCCESS...
项目实现功能 这个repo主要放一些公开的数据, 用于开发, 测试, 研究等等... 目录结构说明 buildings: 世界排名前100的建筑 flights: 全年世界航班 literature: 3万条成语,...安装hquery,(npm) 修改update.sh 中的路径
3. 创建`PDH_HQUERY`和`PDH_HCOUNTER`句柄,通过`PdhOpenQuery`,`PdhAddCounter`等函数来打开并添加性能计数器。 4. 使用`PdhCollectQueryData`收集性能计数器的值。 5. 解析性能计数器返回的数据,转换为CPU使用率...
在C++中,我们可以使用`<windows.h>`头文件来获取这些API。 **1. 获取系统名称** 系统名称可以通过`GetComputerName`函数获取。这个函数接受一个缓冲区和一个指针,用于存储计算机名的长度。例如: ```cpp TCHAR ...
《ASMTools 6.0:深入理解汇编与ASM库的应用》 ASMTools 6.0 是一个专门针对汇编语言(Assembly)和ASM库的工具集,它为开发者提供了丰富的功能,帮助他们在处理底层代码时更加高效。ASM库是一个Java字节码操控和...
win 直接替换掉: 安装目录/lib/ 建议把原charles.jar备份一下