昨天看Hibernate方面书时又看到了"dynamic -update =true"的配置. 在一个Model类的Mapping中设置它后, hibernate在初始化时就不再为此Model类生成更新语句了, 默认是生成的(至于什么情况下设置此选择这个问题,这里就不赘述了).也说不清什么原因, 突然想看下不设置此选项时,hibernate究竟怎么生成更新语句的, 毕竟眼见为实嘛,虽说以前无数次地见到书上/文档里/同事们都这么说.
再加上自己向来对Hibernate源码研究情有独钟(请见Hibernate源码研究碎得整理(一到十三) ). 说实话,以前这样想看SQL是怎么生成的话题想不出,即使想出来也无从下手. N长时间的思考/折磨/挣扎/痛定思痛的沉淀后, 觉得自己现在可以试它一试了.
环境搭建很简单,这里不再赘述. 这里以一个Model类来说明:Person类及Person.hbm.xml配置文件. Person类很简单就三个属性(id,name,age),配置文件也就很简单了.
.......Eclipse下设置断点跟踪........
1,生成一个Configuration对象时,没发现可疑代码.(心情log: 兴致勃勃,肯定能找到,见证这"辉煌时刻"吧!)
2,解析hibernate.cfg.xml配置文件时,也没发现可疑代码. (心情log:配置文件解析完了,怎么还没有呢? 有些纳闷了:我要的代码,你在哪? 不过有收获:PersistentClass类里有这么个方法useDynamicUpdate,于是在这"布控"了断点,虽然现在还没生成想要的SQL 语句,不过,想信真正生成时hibernate会调用这个方法)
3,由于上面在认为关键代码上"布控"了断点, 于是Eclipse中直接按了F8,不出所料在上面useDynamicUpdate方法时设置断点处停了下来. 原来是在Configuration在buildSessionFactory时给Person类生成一个EntityPersister时停的.于是, 集中看EntityPersister当前实现类的SingleTableEntityPersister的构造方法. 这个构造方法里先调用了父类AbstractEntityPersister的构造方法(父类构造方法很长,有300来行), 一步步跟踪看父类构造方法执行完了,还是看到SQL的生成,SQL生成这样的方法很公用的不用放到具体子类来执行吧? 父类构造方法中没发现,有些气馁了.
再看子类构造方法(同样长,也是300行), 一步步执行,看到了很像的customSQLUpdate,但不是(这里记下来,这个属性代表什么?). 眼看要执行完了,还是没发现. 难道自己的猜测不对? 在子类构造方法最后一类,发现了这么一个方法调用 postConstruct.直觉告诉我,有戏! 再看它是父类里的方法,更坚定了信心. 于是, 情况朝对自己有利的方向发展了: 见到了sqlUpdateStrings(感觉像猎人发现了猎物的足迹),发现了顾名思义的方法generateUpdateString 调用! 接下来的事就水到渠成了.
终于看到可爱的update语句了: update Person set name=?, age=? where id=?
............................................
总结下发现updateSQL过程中的关键点,用兴趣的看官可设置断点体会下:
1, 调用环境: 父类AbstractEntityPersister中的postConstruct方法.
2, 最终生成: org.hibernate.sql.Update类中toStatementString方法.
以上是updae语句的生成,其余insert/delete语句如出一辙,不过相应具体类换成了Insert/Delete.