HQL中In的问题详解
最近比较忙,还要复习考研的内容。但突然发现blog的订阅数猛减,于是百忙之中抽空写了一篇关于前几天使用Hibernate时遇到到的问题,希望大家能对我继续的支持。
不要把HQL看的太神,第一眼看到HQL的in语句发现很强大。想当年直接写SQL时,每次都为in后面的参数感到麻烦。后来在网上看了很多文章后发现in的效率很低下,就渐渐避免用in来写SQL,后面参数少的就用=,<>来代替。
网上很多人鼓吹说HQL 很强大,我也就没关心HQL的实现。其实还是有很多问题的。
此处MaxResult等于2000以下没有什么问题,这里如果设成3000就挂了,这是什么原因呢,其实HQL实现in时最终还是通过拼接SQL,也没做过拆分SQL的操作(这里我高估它了),最终导致SQL过长,数据库不接受。那怎么办呢,我网上寻找了好久,想找到了一个好的解决方案。最终发现只能把查询List中的内容先插入数据库中,然后通过子查询的方式。这样可以保证List内容再长这查询也不会失败。我再拿size为2000的list做了实验发现,这种插入的方法虽然执行了2001条的SQL,竟然效率比q2.setParameterList("mytest", test)这种方式效率更高。解决方案代码如下:
数据库表配置如下
Table invoice(这是我以前项目中的表,由于数据比较多就用它了,呵呵)
Table Test(用于缓存数据)
这里再说明下由于这里我只是做下测试也没考虑数据库德设计,就使用了业务主键(呵呵,id不一定是逻辑主键,我做这个实验时把它暂时当成的是业务主键)这是你使用session.delete(test)来删除是没问题的。但如果你用String hql1 = " delete Test";,那你必须在前面的查询后session.flush();session.clear();不然你第二次做测试时就会遇到问题。这是由于主键一样,第一次插入后,这个Test对象处于游离态,你一定要清除掉这个游离态对象不然不能插入。
In虽然效率不是很高,但由于业务的复杂不得不使用,还好客户对那块的效率要求不是很高。可毕竟还是个问题,希望大家有什么好的意见,请在下面留言。