`

iBATIS(N+1)级联查询解决方案

阅读更多
对于iBATIS一对多/多对多的问题,传统的办法是在一对多/多对多关联的属性上再做一次子查询,这个解决办法很简单易懂,但是有个缺点,会导致N+1 selects,导致查询的性能瓶颈,更好的解决办法是sql做一个表连接,然后主表的resultMap配置上加“groupBy='...'”属性,这样一次查询就搞定,避免了N+1问题,下面请看代码:
Xml代码
<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"   
 
"http://www.ibatis.com/dtd/sql-map-2.dtd"> 
<sqlMap namespace="sys"> 
    <typeAlias alias="menu" type="com.cuishen.sqlmaptest.vo.Menu" /> 
    <resultMap id="sub-menu-map" class="menu"> 
        <result property="id" column="subid" /> 
        <result property="name" column="subname" /> 
        <result property="url" column="suburl" /> 
        <result property="layer" column="sublayer" /> 
        <result property="grade" column="subgrade" /> 
        <result property="position" column="subposition" /> 
        <result property="parentId" column="subparentid" /> 
    </resultMap> 
    <resultMap id="menu-map" class="menu" groupBy="id"> 
        <result property="id" column="id" /> 
        <result property="name" column="name" /> 
        <result property="url" column="url" /> 
        <result property="layer" column="layer" /> 
        <result property="grade" column="grade" /> 
        <result property="position" column="position" /> 
        <result property="parentId" column="parentid" /> 
        <result property="subMenus" resultMap="sys.sub-menu-map" /> 
    </resultMap> 
 
    <select id="getTopMenu" parameterClass="java.util.HashMap" resultMap="sys.menu-map"> 
    select   
    t.id as id,t.name as name,t.url as url,t.layer as layer,t.grade as grade,t.position as position,  
    t.parentid as parentid,s.id as subid,s.name as subname,s.url as suburl,s.layer as sublayer,  
    s.grade as subgrade,s.position as subposition,s.parentid as subparentid  
    from menu t left join menu s  
    on t.id = s.parentid  
    where t.layer=1 order by t.position, s.position  
    </select> 
</sqlMap> 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"

"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="sys">
<typeAlias alias="menu" type="com.cuishen.sqlmaptest.vo.Menu" />
<resultMap id="sub-menu-map" class="menu">
<result property="id" column="subid" />
<result property="name" column="subname" />
<result property="url" column="suburl" />
<result property="layer" column="sublayer" />
<result property="grade" column="subgrade" />
<result property="position" column="subposition" />
<result property="parentId" column="subparentid" />
</resultMap>
<resultMap id="menu-map" class="menu" groupBy="id">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="url" column="url" />
<result property="layer" column="layer" />
<result property="grade" column="grade" />
<result property="position" column="position" />
<result property="parentId" column="parentid" />
<result property="subMenus" resultMap="sys.sub-menu-map" />
</resultMap>

<select id="getTopMenu" parameterClass="java.util.HashMap" resultMap="sys.menu-map">
select
t.id as id,t.name as name,t.url as url,t.layer as layer,t.grade as grade,t.position as position,
t.parentid as parentid,s.id as subid,s.name as subname,s.url as suburl,s.layer as sublayer,
s.grade as subgrade,s.position as subposition,s.parentid as subparentid
from menu t left join menu s
on t.id = s.parentid
where t.layer=1 order by t.position, s.position
</select>
</sqlMap>


com.cuishen.sqlmaptest.vo.Menu如下:
Java代码
package com.cuishen.sqlmaptest.vo;  
 
import java.util.List;  
 
/** 
* POJO - 菜单 
* @author cuishen 
*/ 
public class Menu implements java.io.Serializable {  
    private static final long serialVersionUID = 7172793340860021199L;  
 
    private Long id;  
    private String name;  
    private String url;  
    private Short layer;  
    private Short grade;  
    private Short position;  
    private Long parentId;  
    private List subMenus;  
 
    public Menu() { }  
 
    public Long getId() {  
        return this.id;  
    }  
 
    public void setId(Long id) {  
        this.id = id;  
    }  
 
    //...  
    //getter、setter方法  
    //...  
 
    public List getSubMenus() {  
        return subMenus;  
    }  
 
    public void setSubMenus(List subMenus) {  
        this.subMenus = subMenus;  
    }  


package com.cuishen.sqlmaptest.vo;

import java.util.List;

/**
* POJO - 菜单
* @author cuishen
*/
public class Menu implements java.io.Serializable {
private static final long serialVersionUID = 7172793340860021199L;

private Long id;
private String name;
private String url;
private Short layer;
private Short grade;
private Short position;
private Long parentId;
private List subMenus;

public Menu() { }

public Long getId() {
return this.id;
}

public void setId(Long id) {
this.id = id;
}

//...
//getter、setter方法
//...

public List getSubMenus() {
return subMenus;
}

public void setSubMenus(List subMenus) {
this.subMenus = subMenus;
}
}


测试类如下:
Java代码
package com.cuishen.sqlmaptest;  
 
import java.sql.SQLException;  
import java.util.List;  
 
import com.ibatis.sqlmap.client.SqlMapClient;  
 
import com.cuishen.sqlmaptest.vo.Menu;  
 
/** 
* iBATIS 1:N & M:N(N+1 selects)解决方案 
* @author cuishen 
*/ 
public class Test {  
    public static void main(String args[]) throws SQLException {  
        SqlMapClient sqlMapClient = SqlMapClientFactory.getSqlMapClient();  
        List topMenus = sqlMapClient.queryForList("getTopMenu", null);  
        for(int i = 0; i < topMenus.size(); i++) {  
            Menu menu = (Menu)topMenus.get(i);  
            List subMenus = (List)menu.getSubMenus();  
            System.out.println("top menu name >> " + menu.getName());  
            for(int j = 0; j < subMenus.size(); j++) {  
                Menu subMenu = (Menu)subMenus.get(j);  
                System.out.println(">> sub menu name >> " + subMenu.getName());               
            }  
        }  
    }  


package com.cuishen.sqlmaptest;

import java.sql.SQLException;
import java.util.List;

import com.ibatis.sqlmap.client.SqlMapClient;

import com.cuishen.sqlmaptest.vo.Menu;

/**
* iBATIS 1:N & M:N(N+1 selects)解决方案
* @author cuishen
*/
public class Test {
public static void main(String args[]) throws SQLException {
SqlMapClient sqlMapClient = SqlMapClientFactory.getSqlMapClient();
List topMenus = sqlMapClient.queryForList("getTopMenu", null);
for(int i = 0; i < topMenus.size(); i++) {
Menu menu = (Menu)topMenus.get(i);
List subMenus = (List)menu.getSubMenus();
System.out.println("top menu name >> " + menu.getName());
for(int j = 0; j < subMenus.size(); j++) {
Menu subMenu = (Menu)subMenus.get(j);
System.out.println(">> sub menu name >> " + subMenu.getName());
}
}
}
}



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

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上测试通过,更老旧的版本可能不支持该解决方案!!
分享到:
评论

相关推荐

    ibatis n+1选择问题 的几种解决方案

    在数据库查询优化中,"N+1 选择问题"是一个常见的性能瓶颈,特别是在使用ORM(对象关系映射)框架如iBATIS时。N+1问题发生在当我们执行一系列单独的SQL查询来获取关联数据,而不是一次性加载所有所需数据。这可能...

    ibatis N+1问题

    在IT行业中,数据库查询优化是提升系统性能的关键环节之一,而"Ibatis N+1问题"是使用MyBatis框架时常见的性能瓶颈。这个问题通常出现在一对多或者多对多的关联查询中,导致了大量的数据库交互,严重影响了应用的...

    iBATIS 级联iBATIS 级联

    iBATIS 级联iBATIS 级联iBATIS 级联

    Spring.net + iBatis.net + asp.net MVC 整合文档

    关于Spring.net + iBatis.net + asp.net MVC 整合的文档,值!

    ibatis解决多对一n+1问题(更新上传例子(mybatis)代码)

    "ibatis解决多对一n+1问题"这个主题聚焦于MyBatis框架中如何高效地处理多对一关联查询,避免出现性能瓶颈的“n+1”问题。这个问题通常发生在查询一对多关系时,如果不对查询进行优化,会导致大量的额外数据库访问,...

    ibatis驱动+Mysql驱动+SQL驱动

    结合这三个元素,“ibatis驱动+Mysql驱动+SQL驱动”组合为Java开发者提供了完整的数据库操作解决方案。开发者可以通过Ibatis的API编写SQL,利用MySQL JDBC驱动与数据库建立连接,执行SQL语句,最后通过SQL驱动处理...

    ibatis3.0+jsp(demo)

    在"ibatis3.0+jsp(demo)"项目中,JSP页面可能用于显示从数据库查询到的数据,或者接收用户输入,与后台JavaBean进行交互,实现数据的增删改查功能。 【数据库脚本】 项目中包含了创建数据库和表的脚本,这些脚本...

    struts2+spring+ibatis+mysql

    "Struts2+Spring+Ibatis+MySQL" 是一个经典的Java Web开发框架组合,用于构建高效、可扩展的企业级应用程序。这个组合集成了强大的MVC(Model-View-Controller)框架Struts2、依赖注入与面向切面编程的Spring框架、...

    Struts2+Spring2+iBatis2+MySQL的完整示例

    开发环境说明 ...本示例完整地结合Struts2+Spring2+iBatis2+MySQL5,演示了一个用户表的增、删、改、查。 想完整学习Struts2+Spring+iBatis的同仁,可以在这个例子中学习或模仿最基本也是最核心的技术要点。

    velocity+ibatis+mysql+exlipse实例

    velocity+ibatis+mysql+exlipse实例 velocity+ibatis+mysql+exlipse实例 velocity+ibatis+mysql+exlipse实例 velocity+ibatis+mysql+exlipse实例 velocity+ibatis+mysql+exlipse实例

    Ibatis+Spring+struts1框架搭建

    【标题】:Ibatis+Spring+Struts1框架搭建 在Web开发中,Ibatis、Spring和Struts1是三个非常重要的组件,它们分别负责不同的职责。Ibatis是一个优秀的持久层框架,Spring是一个全面的后端应用框架,而Struts1则是一...

    最新版本 IBatis.net+Castal_DLL

    最新版本 IBatis.net+Castal_DLL 整合集合,测试通过可用,基于IBatis.net框架+Castal容器的框架DLL Castle.Core.dll 2.5.2 核心DLL Castle.Facilities.AutoTx.dll 2.5.1自动事务 Castle.Services.Transaction.dll ...

    compass+ibatis+spring+struts2整合开发

    compass+ibatis+spring+struts2整合开发compass+ibatis+spring+struts2整合开发compass+ibatis+spring+struts2整合开发compass+ibatis+spring+struts2整合开发

    Ext简单后台交互(struts2+ibatis2+mysql5.5)

    从描述中我们无法获取具体的信息,但可以推测这个项目可能是为了演示如何在Web应用中实现前端(可能使用Ext库)与后端(Struts2+iBatis+MySQL)的交互。 **Ext**:这里提到的“Ext”可能是指Ext JS,一个用于构建富...

    asp.net mvc2.0+Spring.net1.3+Ibatis.net+memcached文档

    asp.net mvc2.0+Spring.net1.3+Ibatis.net+memcached的帮助,里面有spring.net和asp.netMVC的教程和一个贯穿案例。希望对大家有所帮助。绝对值这个分。

    spring.net+ibatis.net+mvc配置demo

    spring.net+ibatis.net+mvc配置demo.rar spring.net版本:1.3.2 ibatis.net版本:1.6.1 demo运行环境是VS2013 数据库表,我就没传了,测试的时候,建立表 CREATE TABLE [dbo].[Hair8_AD]( [ADId] [int] ...

    ibatis2.0+sqlserver2005环境搭建

    1. JDK 1.6.0 或更高版本:这是运行Ibatis所必需的Java运行环境。 2. SQL Server 2005:作为数据库管理系统,用于存储和处理数据。 3. SQL Server JDBC驱动:Ibatis通过JDBC与数据库交互,因此需要对应的驱动jar包。...

    IBatis源码+xsd+帮助

    IBatis的帮助文档通常包含详细的用户指南、API参考和示例,有助于快速上手和解决问题。主要知识点涵盖: 1. **安装与配置**:如何在项目中引入IBatis,以及相关的配置步骤。 2. **基本使用**:如何编写Mapper接口和...

    仓储管理系统(struts2+ibatis+jsp+jquery)

    Ibatis与Hibernate等ORM框架不同,它不完全封装SQL,而是提供灵活的SQL控制,更适合复杂的数据库操作,如联表查询、存储过程调用等。 **jQuery**: jQuery是一个广泛使用的JavaScript库,它简化了HTML文档遍历、...

    oa_权限系统ibatis+spring+struts2

    oa_权限系统ibatis+spring+struts2 oa_权限系统ibatis+spring+struts2 oa_权限系统ibatis+spring+struts2

Global site tag (gtag.js) - Google Analytics