`
yjhexy
  • 浏览: 331573 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

ibatis 延迟加载 探究

阅读更多

ibatis延迟加载的含义(可能我讲不太清楚,具体看下面代码就明白什么含义了):

 

在牵涉到1:N关系,或 N:N关系的时候查询,那么会需要查询多张表,但并不是所有情况都会需要查询另一张相关的表。

采用延迟加载可以在真正使用的时候去查询另一张相关表。提高性能。

 

我用的是maven构建我的测试代码,其中pom文件配置如下:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.yajun</groupId>
	<artifactId>IbatisDemo</artifactId>
	<packaging>jar</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>IbatisDemo</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.4.726</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.4</version>
			<scope>provide</scope>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>1.0</version>
			<scope>complie</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.9</version>
			<scope>provide</scope>
		</dependency>
	</dependencies>
</project>
 

 


先把我遇到的问题抛下出来,大家在用的时候也注意下吧,不知道是不是我个人的问题:

第一个问题:


cacheModelsEnabled="true" 与 lazyLoadingEnabled="true" 相冲突?

如果启用延迟加载,并且启用 cacheModelsEnabled="true",那么会报如下错误

Caused by: java.io.NotSerializableException: com.ibatis.sqlmap.engine.mapping.result.loader.LazyResultLoader

网上搜罗了一圈找到这个:http://issues.apache.org/jira/browse/IBATIS-529

是否是个BUG?

 

 

第二个问题:

 

ibatis中要使用延迟加载功能必须要有<settings/>设置。
lazyLoadingEnabled="true"
enhancementEnabled="true"
这二项在<settings/>中默认为true,如果没有在config.xml中没有出现<settings/>,就当做false来处理。
enhancementEnabled="true"时要在项目中
导入cglib的jar。
如果enhancementEnabled="false",lazyLoadingEnabled="true",延迟加载只对某个属性为集合生效。
如果属性是个类,则不会延迟加载。
看到网上有人说: 但enhancementEnabled="true"时就不同,不论是集合还是类都延迟加载。
ibatis的其它功能还须其它jar,继续摸索中。
但是至少我没有试成功。我都是用集合类来做的。如果有人知道这个,渴望帮我指点迷津!




========================================================================

 

下面开始我的测试。

 

第一步,构建我的测试代码

 

建立DO类 BabyDO和AddressDO,其中 baby 的id 和address 的id是相关联的:

 

package com.yajun.dataobject;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateFormatUtils;

import com.yajun.enumdemo.SexEnum;

/**
 * Baby DO类
 * 
 * @author yajun
 * 
 */
public class BabyDO implements Serializable {

	private static final long serialVersionUID = -579987226803641422L;

	private int id;
	private String name; // 姓名
	private SexEnum sex; // 性别
	private Date birthday; // 生日
	private String hobby; // 喜好
	private int age; // 年龄 注意这里是原生类型
	private List<AddressDO> address; // 地址复杂类型
  // 一堆get set  方法
	public List<AddressDO> getAddress() {
		return address;
	}

	public void setAddress(List<AddressDO> address) {
		this.address = address;
	}

	@Override
	public String toString() {
		String s = "id :" + id + "\t" + "name :" + name + "\t" + "\t" + "birthday:"
				+ DateFormatUtils.format(birthday, "yyyy-MM-dd") + "\t" + "hobby:" + hobby;
		if (address != null) {
			s = address.toString();
		}
		return s;
	}
}

 

package com.yajun.dataobject;

import java.io.Serializable;

/**
 * 地址类
 * 
 * @author yajun
 * 
 */
public class AddressDO implements Serializable {

	private static final long serialVersionUID = -7544474673567062502L;

	private Integer id; // id 与 baby的id关联
	private String address; // 地址

	public Integer getId() {
		return id;
	}

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

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

}
 

 

 

第二步,配置文件

 

baby.xml中重要配置

	<resultMap id="baby-Result" class="baby">
		<result property="id" column="id" jdbcType="Integer" javaType="integer" />
		<result property="name" column="name" jdbcType="VARCHAR"
			javaType="string" />
		<result property="sex" column="sex" jdbcType="VARCHAR"
			javaType="com.yajun.enumdemo.SexEnum" typeHandler="com.yajun.typehandler.SexEnumTypeHandlerCallBack" />
		<result property="birthday" column="birthday" jdbcType="DATE"
			javaType="date" />
		<result property="hobby" column="hobby" jdbcType="VARCHAR"
			javaType="string" />
		<result property="age" column="age" jdbcType="INTEGER"
			javaType="int" nullValue="0" />
		<result property="address" select="getAddressById" column="id" />
	</resultMap>

	<select id="getBabyByParams" resultMap="baby-Result" cacheModel="baby-cache">
		select * from Baby
		<dynamic prepend="where">
			<isPropertyAvailable property="name" prepend="and">
				name = #name#
		   	</isPropertyAvailable>
			<isPropertyAvailable property="sex" prepend="and">
				sex =
				#sex,jdbcType=VARCHAR,javaType=com.yajun.enumdemo.SexEnum#
			</isPropertyAvailable>
			<isPropertyAvailable property="BirthdayBondStart"
				prepend="and"> 
		   	   <![CDATA[
		   	         birthday >= cast(#BirthdayBondStart# as datetime)
		   	   ]]>
			</isPropertyAvailable>
			<isPropertyAvailable property="BirthdayBondEnd"
				prepend="and">
				 <![CDATA[
				     birthday <= cast(#BirthdayBondEnd# as datetime)
				 ]]>
			</isPropertyAvailable>
			<isPropertyAvailable property="hobby" prepend="and">
				hobby like #hobby#||'%'
			</isPropertyAvailable>
		</dynamic>
	</select>
 

  address.xml中重要配置

 

<?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 namespace="babyStore">

	<typeAlias alias="address" type="com.yajun.dataobject.AddressDO" />

	<resultMap id="address-Result" class="address">
		<result property="id"      column="id"      jdbcType="INTEGER" javaType="integer"/>
		<result property="address" column="address" jdbcType="VARCHAR" javaType="string" />
	</resultMap>
	
	<select id="getAddressById" resultMap="address-Result">
	    select * from address where id = #id#
	</select>
</sqlMap>
 

 

sqlMapConfig.xml中重要配置

<settings lazyLoadingEnabled="true" cacheModelsEnabled="true"></settings>
 

 

 

第三步,建立测试类:

package com.yajun;

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

import com.yajun.dataobject.BabyDO;
import com.yajun.impl.BabyDAOImpl;

/**
 * 专门测试延迟加载的
 * 
 * @author yajun
 * 
 */
public class LazyLoadTest {
	private BabyDAOImpl babyDAO = new BabyDAOImpl();

	public static void main(String[] args) throws SQLException {
		LazyLoadTest test = new LazyLoadTest();
		// System.out.println(test.addressDAO.query(9));

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("name", "吴亚军");
		List<BabyDO> list = test.babyDAO.testBabyLazyLoad(params);
		BabyDO baby = list.get(0);
		System.out.println(baby.getId());
		System.out.println(baby.getHobby());
		System.out.println(baby.getAge());
		System.out.println(baby.getAddress());
	}
}

 

 

BabyDAOImpl   中重要代码

	/**
	 * 测试延迟加载的
	 * 
	 * @param params
	 * @return
	 * @throws SQLException
	 */
	public List<BabyDO> testBabyLazyLoad(Map params) throws SQLException {
		return client.queryForList("getBabyByParams", params);
	}
 

 

 

第四步,调试可得当执行到

System.out.println(baby.getAddress);

 

这句话的时候并没有地址,地址那个属性是个被代理过的类,当真正去取address的时候才把这个类查出来。

 

 

那么延迟加载和连接查询,到底选用哪一个就要看使用者平衡了:

 

延迟加载

Join

如果要加载大量的数据,它们不会马上用到,延迟加载会比较合适。

数据量较小或者数据马上就会用到, Join方法比较合适。

 

我觉得还有一条很重要的原则,那就是永远只加载必需的数据

 

 

 

 

 

分享到:
评论
1 楼 xiaokang1582830 2013-04-17  
遇到同样的问题,请教如何解决的java.io.NotSerializableException: $java.util.List$$EnhancerByCGLIB$$a80b8ab4

相关推荐

    实现ibatis手动控制加载sqlmap文件,终于不用重启应用了

    综上所述,通过监听文件系统变化并自定义SqlSessionFactory,我们可以实现在不重启应用的情况下手动控制加载iBatis的SQL映射文件。这极大地提高了开发效率,同时也对开发流程提出了更高的要求,比如需要更严格的文件...

    ibatis配置文件自动加载组件

    标题 "ibatis配置文件自动加载组件" 涉及的核心技术是MyBatis的自动配置加载功能,这在开发过程中极大地提高了效率,使得开发者无需每次修改XML映射文件后手动重启服务。MyBatis是一个优秀的Java持久层框架,它简化...

    ibatis总结 ibatis ibatis ibatis ibatis

    5. Ibatis配置与加载: Ibatis的配置文件`sqlmapConfig.xml`包含了数据源、事务管理器、SqlSessionFactory等核心设置。在Java代码中,可以使用如下的方式加载配置文件: ```java String resource = ...

    iBatis资料 语法

    延迟加载(Lazy Loading)是iBatis的一种优化策略,只在真正需要时才加载关联的对象,减少了不必要的数据库交互。一对多或多对一关系的处理是对象关系映射(ORM)中的常见问题,iBatis提供了优雅的方式来管理这些...

    mybatis3--延迟加载,缓存

    在 MyBatis 中,延迟加载(Lazy Loading)和缓存是两个非常重要的特性,它们对于提升应用程序性能和减少数据库访问有着显著作用。 **延迟加载(Lazy Loading)** 延迟加载是一种设计模式,它在对象被首次请求时才...

    ibatis源码,ibatis源码 ibatis源码 ibatis源码

    iBatis的配置文件SqlMapConfig.xml是系统启动时加载的关键,它包含了数据源(DataSource)、事务管理器(TransactionManager)和SqlMap配置信息。解析这个XML文件的过程涉及到DOM或SAX解析器,源码中这部分功能通常...

    ibatisDemo 入门源码

    1. 加载配置:程序启动时,Ibatis会加载SqlMapConfig.xml,从中获取数据源和Mapper配置信息。 2. 创建SqlSessionFactory:使用`SqlSessionFactoryBuilder`根据配置信息创建`SqlSessionFactory`。 3. 获取SqlSession...

    ibatis demo,ibatis例子,ibatis示例

    Ibatis,全称为MyBatis,是一个优秀的Java持久层框架,它主要负责SQL映射,使得开发者能够将SQL语句与Java代码分离,从而更好地管理数据库操作。Ibatis的出现,解决了传统JDBC中手动编写SQL和结果集映射的繁琐工作,...

    ibatis开发指南 经典教材

    此外,ibatis还支持延迟加载,即只有在真正需要时才加载关联对象,从而避免了不必要的数据加载和内存消耗。 ### ibatis高级特性 #### 动态SQL ibatis的一个强大特性是动态SQL。它允许开发者在运行时根据不同的...

    iBatis文档\ibatis.doc

    iBatis提供了延迟加载(Lazy Loading)功能,允许在真正需要关联数据时才执行对应的SQL。在`resultMap`中开启延迟加载: ```xml ``` #### 动态映射 动态SQL让开发者可以根据条件动态构造SQL语句,使用`if`, `...

    iBATIS2.0学习总结

    总之,iBATIS2.0是一个强大的SQL Mapping框架,它简化了数据访问层的开发,允许开发者自由地编写SQL,同时提供了诸如延迟加载、事务管理、结果映射等高级特性。在项目实践中,合理利用这些特性,可以提高代码的可...

    Ibatis

    2.1 配置:在启动时,Ibatis 读取配置文件,加载 SQL 映射文件,建立 SQL 映射器工厂。 2.2 SQL 执行:通过 SqlSession 接口,开发者可以获取 SqlSession 对象,执行 SQL 映射文件中的 SQL 语句。SqlSession 提供了...

    Ibatis入门例子,Ibatis教程

    Ibatis,全称为MyBatis,是一个优秀的Java持久层框架,它主要负责SQL映射,使得开发者能够将注意力集中在编写SQL语句上,而无需关注JDBC代码的编写。Ibatis消除了几乎所有的JDBC代码和手动设置参数以及获取结果集的...

    ibatis教程,ibatis帮助文档

    iBATIS是一个由Clinton Begin创建,目前由Apache基金会支持的持久化框架,它专注于数据库查询的简化,尤其在JDBC编程方面提供了极大的便利。相对于全自动化ORM解决方案如Hibernate,iBATIS被称为“半自动化”ORM实现...

    iBATIS-DAO-2.3.4.726.rar_com.ibatis.dao_iBATIS dao 2_iBatis DAO_

    iBATIS DAO是Java开发中的一个持久层框架,它提供了数据访问对象(DAO)的实现,使得数据库操作更加简单和灵活。在这个2.3.4.726版本的源码中,我们可以深入理解iBATIS DAO的工作原理,并通过添加注释来帮助我们更好...

    iBatis入门与精通

    `ibatis 延迟加载、对多关系、缓存的测试.mht`则深入探讨了iBatis的高级特性。延迟加载(Lazy Loading)允许在需要时才加载关联对象,可以有效提高性能。对多关系(One-to-Many, Many-to-One)的处理是ORM(对象关系...

    Ibatis3手册 Ibatis3参考手册

    ### Ibatis3手册知识点概述 Ibatis3作为一款流行的持久层框架,在软件开发领域具有重要的地位。本篇文章基于“Ibatis3手册 Ibatis3参考手册”的标题及描述,深入解析Ibatis3的核心概念、架构特点以及如何进行实际...

Global site tag (gtag.js) - Google Analytics