`
min4450
  • 浏览: 13158 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

[ibatis]:延迟加载和N+1问题

阅读更多
  数据库I/O可以很好的度量数据库的使用情况,同时也是影响数据库性能的主要瓶颈之一。数据从磁盘到内存或则从内容写到磁盘这种操作时非常耗时。高速缓存能很好的应到到这一问题来提高性能。
  N+1问题是由于试图加载和父记录相关的子记录而造成的。当如果你已经获取一个父记录时,若想获得所有的这个父记录的子记录时,你需要多执行N个查询,为了把子记录查询出来。
  延迟加载将加载分层了更小的易管理的小过程,只有在需要的时候才会加载额外的数据。这样很好解决了数据库I/O问题,但它导致了N+1问题。数据库I/O和N+1问题两个问题必有其一。这往往要考虑到实际的需要来决定采用哪个策略。

iBATIA延迟加载
  Person 可以有多个Address。
package com.min.ibatis.model;

import java.util.List;

public class Person {
	private int id;
	private String name;
	private List<Address> addresses;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<Address> getAddresses() {
		return addresses;
	}
	public void setAddresses(List<Address> addresses) {
		this.addresses = addresses;
	}
}


package com.min.ibatis.model;

public class Address {
	private int id;
	private String address;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
}

iBATIS的sql映射配置文件
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap>
	<typeAlias alias="Person" type="com.min.ibatis.model.Person"/>
 	<typeAlias alias="Address" type="com.min.ibatis.model.Address"/>

	<resultMap class="Person" id="personMap">
		<result property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="addresses" select="getAddresses" column="id"/>
	</resultMap>
	<resultMap class="Address" id="addressMap">
		<result property="id" column="id"/>
		<result property="address" column="address"/>
	</resultMap>
	
	<select id="getAddresses" resultMap="addressMap">
		select * from address where personId=#value#
	</select>
	
	<select id="getPerson" resultMap="personMap">
		select * from person where id = #value#
	</select>
</sqlMap>

测试类
package com.min.ibatis.model;

import java.io.Reader;
import java.sql.SQLException;

import junit.framework.TestCase;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;


public class Test extends TestCase {
	private SqlMapClient sqlMap;
	@Override
	protected void setUp() throws Exception {
		String resource = "SqlMapConfig.xml";
		Reader reader = Resources.getResourceAsReader(resource);
		sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

	}
	
	public void testLoadLazy(){
		int id = 1;
		try {
			Person person = (Person)sqlMap.queryForObject("getPerson",id);
			System.out.println(person.getName());
			Address address = person.getAddresses().get(0);
			System.out.println(address.getAddress());
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
}


默认情况下,SqlMapConfig.xml中
<settings lazyLoadingEnabled="true" enhancementEnabled="true"/>
enhancementEnabled="true" 说明使用延迟加载cglib增强版。 只需加入cglib.jar包就可以了。

通过debug,我们发现 person的addresses属性引用的是代理类。

避免N+1查询问题

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap>
	<typeAlias alias="Person" type="com.min.ibatis.model.Person"/>
 	<typeAlias alias="Address" type="com.min.ibatis.model.Address"/>

	<resultMap class="Person" id="personMap" groupBy="id">
		<result property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="addresses"  resultMap="addressMap"/>
	</resultMap>
	
	<resultMap class="Address" id="addressMap">
		<result property="id" column="id"/>
		<result property="address" column="address"/>
	</resultMap>
	

	
	<select id="getPerson" resultMap="personMap">
		select * from person join address on person.id = address.personId
	</select>
</sqlMap>


延迟加载适用于大型的但并非所有的数据都有用的那些数据集。
避免N+1查询方案使用于小型的或则所有的数据都会被使用的那些数据集。

参考:iBATIS in action
分享到:
评论
1 楼 yunzhongxia 2009-04-30  
写的不错,收藏了

相关推荐

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

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

    ibatis N+1问题

    但是,如果在循环中访问关联数据,延迟加载反而会导致N+1问题,因此需要谨慎使用。 4. **子查询或子集合映射(Subquery or Subcollection Mapping)**: 在映射文件中,可以使用子查询来获取关联数据,这样在原始...

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

    综上所述,解决iBATIS中的N+1选择问题需要结合业务场景和数据库设计,选择合适的策略进行优化。通过合理地使用批处理、联合查询、预加载、缓存等方法,我们可以显著提升系统的性能和响应速度。在实践中,还需要注意...

    ibatis高级特性

    但 iBATIS 提供了两种方式来处理关联查询:N+1 次查询和新的查询方式。 1. **N+1 次查询** 这种方式在 SQL 映射文件中通过 `select` 属性指定一个单独的查询语句。虽然这种方法会导致额外的数据库读取操作,但可以...

    ibatis开发手册(pdf)

    - **避免 N+1 Select(1:M 和 M:N)**:进一步讲解如何优化多对多查询。 - **组合键值或多个复杂参数属性**:当一个参数由多个属性组成时的处理方法。 - **支持 ParameterMap 和 ResultMap 的数据类型**:详细...

    iBATIS实战

    6.2.3 避免N+1查询问题 105 6.3 继承 107 6.4 其他用途 109 6.4.1 使用语句类型和DDL 109 6.4.2 处理超大型数据集 109 6.5 小结 115 第7章 事务 116 7.1 事务是什么 116 7.1.1 一个简单的银行转账示例 116 7.1.2 ...

    ibatis 指导书 PDF

    - **避免 N+1 Select**:通过联合查询等方式优化查询性能。 - **延迟加载 VS 联合查询**:选择合适的查询策略以提高效率。 - **复杂类型集合的属性**:处理复杂类型集合的映射。 - **组合键值或多个复杂参数属性**:...

    ibatis开发指南(中文版)

    - **避免N+1 Select(1:M和M:N)**:进一步优化多对多关系的查询效率。 - **组合键值或多个复杂参数属性**:支持同时传递多个参数或组合键值。 - **支持ParameterMap和ResultMap的数据类型**:提供了广泛的类型支持...

    ibatis net 指导 手册

    - **3.4.9 避免N+1查询(一对多或多对多)** - 使用关联查询或子查询来减少查询次数。 - **3.4.10 组合键或多个复杂参数属性** - 可以通过组合多个属性来映射复合主键或复杂参数。 - **3.5 支持的参数映射和...

    iBATIS 帮助文档

    - **避免 N+1 Select**:通过适当的缓存策略和联合查询优化,减少不必要的数据库查询次数。 - **延迟加载与联合查询**:权衡查询效率与内存消耗,选择合适的加载策略。 #### 六、缓存机制 - **只读与可读写缓存**...

    高效使用JavaEE+ORM框架.pdf

    在JavaEE开发中,ORM(Object-Relational Mapping,对象关系映射)框架是...在处理大数据量或复杂业务逻辑时,还需注意优化查询,避免N+1查询问题,以及注意事务隔离级别和并发控制,确保系统的稳定性和数据的一致性。

    java面试知识

    - **load**:延迟加载对象,如果找不到记录,则返回null。 ##### Hibernate、Ibatis、Jdbc三者的区别 - **Hibernate**:全ORM解决方案,自动管理对象的生命周期。 - **MyBatis (原Ibatis)**:半ORM框架,提供动态...

    MyBatis学习资料

    1. 属性配置文件(如`sqlMapConfig.xml`),用于设置全局属性,如延迟加载(lazyLoadingEnabled)等。 2. DAO配置文件(映射文件),定义SQL语句、参数类型和返回结果映射。这包括一对一、一对多和多对多的关联映射...

Global site tag (gtag.js) - Google Analytics