遇到的情况是,我有个Page对象,里面有totalProperty(总记录条数)和root(结果集)2 个属性。同时,有个Company公司类和Department部门类,是一对多的关系。
当查询公司列表的时候,我分页查询20条数据,hql如:from Company limit 0,20; 并将结果使用struts2 的jsonplugin插件转换为json对象返回。
出现的问题是,我在action中只查询了公司类,但是打印的sql是执行了20+1条,也就是典型的N+1问题。
分析出现问题的原因:
1.是否配置了lazy=false;
2.是否在取了部门类对象的属性;
都是否定的;
最后分析原因是:由于使用了opensessioninview,在action中执行完成前,session没有关闭,此时,json插件在序列化公司类对象的时候,发现了部门这个属性,就会进行序列化,这样,hibernate就会去查询这20个公司的对应的部门,出现了n+1的问题。
解决方案:
1.考虑使用@JSON(serialize=false)配置到公司类的部门对象的get方法上;但是不灵活,如果下次要用json序列化这个对象的时候,也不行了。修改插件原代码也不保险。
2.考虑使用gson这个json插件转换,但是由于公司对象有部门对象这个属性,部门对象有公司对象这个属性,出现了循环引用,报com.google.gson.CircularReferenceException: circular reference error,处理起来也麻烦。
3.最后,想到strust配置文件可以使用excludeProperties,于是配置
<result type="json">
<param name="root">page</param>
<!-- json不会序列化page对象中的root这个集合中的对象的departments属性 -->
<param name="excludeProperties">root.*/.departments</param>
</result>
,终于解决这个问题,并且也比较灵活。