搜索
您的当前位置:首页正文

iBATIS一对多/多对多N+1问题解决方案。

来源:步旅网
对于iBATIS一对多/多对多的问题,传统的办法是在一对多/多对多关联的属性上再做一次子查询,这个解决办法很简单易懂,但是有个缺点,会导致N+1 selects,导致查询的性能瓶颈,更好的解决办法是sql做一个表连接,然后主表的resultMap配置上加“groupBy='...'”属性,这样一次查询就搞定,避免了N+1问题,下面请看代码: 
Xml代码  


com.cuishen.sqlmaptest.vo.Menu如下: 
Java代码  
  1. package com.cuishen.sqlmaptest.vo;  
  2.   
  3. import java.util.List;  
  4.   
  5. /** 
  6.  * POJO - 菜单 
  7.  * @author cuishen 
  8.  */  
  9. public class Menu implements java.io.Serializable {  
  10.     private static final long serialVersionUID = 7172793340860021199L;  
  11.   
  12.     private Long id;  
  13.     private String name;  
  14.     private String url;  
  15.     private Short layer;  
  16.     private Short grade;  
  17.     private Short position;  
  18.     private Long parentId;  
  19.     private List subMenus;  
  20.   
  21.     public Menu() { }  
  22.   
  23.     public Long getId() {  
  24.         return this.id;  
  25.     }  
  26.   
  27.     public void setId(Long id) {  
  28.         this.id = id;  
  29.     }  
  30.   
  31.     //...  
  32.     //getter、setter方法  
  33.     //...  
  34.   
  35.     public List getSubMenus() {  
  36.         return subMenus;  
  37.     }  
  38.   
  39.     public void setSubMenus(List subMenus) {  
  40.         this.subMenus = subMenus;  
  41.     }  
  42. }  


测试类如下: 
Java代码  
  1. package com.cuishen.sqlmaptest;  
  2.   
  3. import java.sql.SQLException;  
  4. import java.util.List;  
  5.   
  6. import com.ibatis.sqlmap.client.SqlMapClient;  
  7.   
  8. import com.cuishen.sqlmaptest.vo.Menu;  
  9.   
  10. /** 
  11.  * iBATIS 1:N & M:N(N+1 selects)解决方案 
  12.  * @author cuishen 
  13.  */  
  14. public class Test {  
  15.     public static void main(String args[]) throws SQLException {  
  16.         SqlMapClient sqlMapClient = SqlMapClientFactory.getSqlMapClient();  
  17.         List topMenus = sqlMapClient.queryForList("getTopMenu"null);  
  18.         for(int i = 0; i < topMenus.size(); i++) {  
  19.             Menu menu = (Menu)topMenus.get(i);  
  20.             List subMenus = (List)menu.getSubMenus();  
  21.             System.out.println("top menu name >> " + menu.getName());  
  22.             for(int j = 0; j < subMenus.size(); j++) {  
  23.                 Menu subMenu = (Menu)subMenus.get(j);  
  24.                 System.out.println(">> sub menu name >> " + subMenu.getName());               
  25.             }  
  26.         }  
  27.     }  
  28. }  



是不是很简单,但是有三点需要注意: 

1. 注意这个配置:<result property="subMenus" resultMap="sys.sub-menu-map" />,resultMap是sys.sub-menu-map,要加命名空间sys,而不是sub-menu-map,否则iBATIS可能会报错! 

2. 一对多/多对多映射的集合属性subMenus必须用简单的getter/setter,不能在getter/setter里做其他处理,否则会导致iBATIS报错!! 

3. 在iBATIS2.3.0.677上测试通过,更老旧的版本可能不支持该解决方案!! 


从iBATIS3.0开始该解决方案的配置改为: 
Xml代码  
  1. <resultMap id="blogResult" type="Blog">  
  2.     <id property=”id” column="blog_id" />  
  3.     <result property="title" column="blog_title"/>  
  4.     <collection property="posts" ofType="Post">  
  5.         <id property="id" column="post_id"/>  
  6.         <result property="subject" column="post_subject"/>  
  7.         <result property="body" column="post_body"/>  
  8.     </collection>  
  9. </resultMap>  

更详细的信息请参阅iBATIS-3-User-Guide 


转载:

因篇幅问题不能全部显示,请点此查看更多更全内容

Top