黑马程序员mybatis教程第二天:延迟加载

合集下载

黑马程序员mybatis教程第二天:查询缓存

黑马程序员mybatis教程第二天:查询缓存

查询缓存什么是查询缓存mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。

mybaits提供一级缓存,和二级缓存。

一级缓存是SqlSession级别的缓存。

在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。

不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

为什么要用缓存?如果缓存中有数据就不用从数据库中获取,大大提高系统性能。

一级缓存一级缓存工作原理第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。

得到用户信息,将用户信息存储到一级缓存中。

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

一级缓存测试mybatis默认支持一级缓存,不需要在配置文件去配置。

按照上边一级缓存原理步骤去测试。

@Testpublicvoid testCache1() throws Exception{SqlSession sqlSession = sqlSessionFactory.openSession();//创建代理对象UserMapper userMapper =sqlSession.getMapper(UserMapper.class);//下边查询使用一个SqlSession//第一次发起请求,查询id为1的用户User user1 = userMapper.findUserById(1);System.out.println(user1);// 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

ssh下基于junit测试出现的延迟加载的解决方案

ssh下基于junit测试出现的延迟加载的解决方案

ssh下基于junit测试出现的延迟加载的解决方案篇一:ssh框架常见错误与解决方法not Found Exception 异常.---->解决方法:在lib中加入两个jar包(与struts2- );2.使用hql语句时出现(即使用hql回调函数带参数时) 或者是()I异常---->解决方法:(()I异常XX-04-06 14:56:57| 分类: java编程 | 标签:antlr jar collections ast getline |字号大中小订阅我用的,装在 D:\\,SSH组合完成后,执行hibernate 的HQL查询时,报错:: ()I看来是antlr这个语法解析包出错因为Struts自带的,比自带的的版本要低,故要删除前一个低版本的,,和都带有 ,,,下面我要把它们都清除了,由于myeclipse 添加的struts性能不是放在工程lib下的,而是myeclipse自带的,,所以删除比较麻烦,,我觉得最简单的做法应该是这样:D:\\\configuration\\bundles 下搜索完成后能看到的,都删除掉,,(可能有些是在下面的,有些是在下面的) 然后在 D:\\Common\plugins 搜索 *struts*.jar 会发现,出来三个选中一个文件,,打开方式选择压缩包,,我的winRAR 的,_ 在lib下和data\下要删除(这个是删除里面的)而再打开 _ data\\core 下删除 (这个是里面的)好了,,这个就从和中移除了,,因为这两个jar是common目录下的,所以删除了后,再运行myeclipse后,myeclipse就不能再从这两个包中找并加载了注意:如果程序已经运行过,则同时需要删除TOMCAT 下的)3.(使用JSONObject与JSONArray时出现的问题)程序运行到 JSONObject j=(map) 这部分后就没反应了,无任何异常抛出---->解决方法:(本文来自:blog_这句话前面和后面都加上了打印信息,运行结果是前面有打印,后面没有打印,也没有任何异常抛出,就这么莫名其妙的断掉了。

关于延迟加载(lazy)和强制加载

关于延迟加载(lazy)和强制加载
信息,那么自动加载address的特性就显得多余,并且造成了极大的性能浪费。为了获得user 的性别属性,我们可能还要同时从数据库中读取数条无用的地址数据,这导致了大量无谓的系统开销。
延迟加载特性的出现,正是为了解决这个问题。所谓延迟加载,就是在需要数据的时候,才真正执行数据加载操作。
对于我们这里的user对象的加载过程,也就意味着,加载user对象时只针对其本身的属性, 而当我们需要获取user对象所关联的address信息时(如执行user.getAddresses时),才
TUser user = (TUser)session.load(TUser.class,new Integer(1));
VO经过Hibernate进行处理,就变成了PO。上面的示例代码session.save(user)中,我们把一个VO “user”传递给Hibernate的Session.save方法进行保存。在save方法中,Hibernate对其进
TUser user =(TUser)userList.get(0);
System.out.println("User name => "+user.getName());
Set hset = user.getAddresses();
session.close();//关闭Session
这里有个问题,如果我们采用了延迟加载机制,但希望在一些情况下,实现非延迟加载时的功能,也就是说,我们希望在Session关闭后,依然允许操作user的addresses
属性。如,为了向View层提供数据,我们必须提供一个完整的User对象,包含其所关联的address信息,而这个User对象必须在Session关闭之后仍然可以使用。

【黑马程序员】类加载器的解析

【黑马程序员】类加载器的解析

【黑马程序员】类加载器的解析为什么要使用类加载器类加载器作用于类加载过程中加载环节,是将.class文件加载进入内存时所使用到的技术,下文介绍类加载器类加载的机制加载: 1.取得类的二进制流, 2.转为方法区数据结构, 3.在Java堆中生成对应ng.Class对象链接1.验证:保证Class流的格式是正确的一、文件格式的验证(是否以0xCAFEBABE开头)。

二、元数据验证(是否有父类,继承了final类?非抽象类实现了所有的抽象方法。

三、字节码验证 (很复杂)。

四、符号引用验证)2.准备:分配内存,并为类的静态变量设置默认初始值(方法区中),注意:此时对象并未创建,且常量在该阶段就完成赋值3.解析:符号引用替换为直接引用1)、符号引用:Java中,一个java类将会编译成一个class文件。

在编译时,java类并不知道所引用的类的实际地址,因此只能使用符号引用来代替。

比如org.simple.People类引用了nguage类,在编译时People类并不知道Language类的实际内存地址2)、直接引用:、实际内存地址,指向了实际的内存如果有了直接引用,那引用的目标必定已经被加载入内存中了。

初始化:执行类构造器 1、static变量赋值语句 2、static{}语句 3、子类的调用前保证父类的被调用 4、是线程安全的判断什么时候需要进行初始化有6种情况称之为主动使用,在主动使用的情况下,该类会被类加载器加入内存,且进行初始化,除此以外都不会加载该类创建类的实例–访问某个类或接口的静态变量,或者对该静态变量赋值–调用类的静态方法–反射(如Class.forName(“ng.String”)–初始化一个类的子类– Java虚拟机启动时被标明为启动类的类(Java Test)类加载器的介绍BootStrap ClassLoader (启动ClassLoader,根类加载器)rt.jar ng Extension ClassLoader (扩展ClassLoader)ext包下的内容App ClassLoader (应用ClassLoader/系统ClassLoader)开发人员自己写的Custom ClassLoader(自定义ClassLoader) 根类加载器并不是由Java代码写的,且sun公司也不提供对根类加载器的任何操作,想要拿到这个一个加载器,返回的结果是null除了根类加载器以外,其他的加载器都是java代码写的,上一层是下一层的父容器,值得注意的是他们并不是一个继承关系,而是逻辑上的父子关系启动类加载器,由C++实现,没有父类。

解析Mybatis延迟加载问题

解析Mybatis延迟加载问题

解析Mybatis延迟加载问题延迟加载问题MyBatis针对关联表中的数据⽀持延迟加载。

延迟加载其实就是将数据加载时机推迟,⽐如推迟嵌套查询的执⾏时机。

延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,⼀定程度上提⾼了效率。

<settings><!-- 启⽤延迟加载特性,不配置默认关闭该特性--><setting name="lazyLoadingEnabled" value="true" /><!-- 按需加载: false:使⽤关联属性时才进⾏加载; true加载对象,则加载所有属性 --><setting name="aggressiveLazyLoading" value="false"/></settings>lazyLoadingEnabled:是否启⽤延迟加载,默认值为false,不启⽤延迟加载。

lazyLoadingEnabled属性控制全局是否使⽤延迟加载,特殊关联关系也可以通过嵌套查询中fetchType属性单独配置(fetchType属性值可以是lazy或者eager)aggressiveLazyLoading:是否按需加载属性,默认值false,lazyLoadingEnabled属性启⽤时只要加载对象,就会加载该对象的所有属性;关闭该属性则会按需加载,即使⽤到某关联属性时,实时执⾏嵌套查询加载该属性对⼀<resultMap id="ExtResultMap" type="er" extends="BaseResultMap"><association property="role" select="com.yan.dao.RoleMapper.selectByPrimaryKey" column="role_id"/></resultMap>如果不访问role属性,则不会执⾏t_roles表的查询。

Hibernate学习--hibernate延迟加载原理(动态代理)

Hibernate学习--hibernate延迟加载原理(动态代理)

Hibernate学习--hibernate延迟加载原理(动态代理)在正式说hibernate延迟加载时,先说说⼀个⽐较奇怪的现象吧:hibernate中,在many-to-one时,如果我们设置了延迟加载,会发现我们在eclipse的调试框中查看one对应对象时,它的内部成员变量全是null的(因为这个原因我还调了好久的代码!),贴张图给你们感受下:左边是设置延迟加载的调试图,右边是没设置延迟加载的⽰意图;ok,估计⼤家也理解我说什么了,下⾯就从这个现象进作为⼊⼝,阐述hibernate延迟加载背后的原理----动态代理。

⼀、hibernate的延迟加载与动态代理 1、hibernate中的延迟加载:get VS load 我们知道,在hibernate⽅法中,直接涉及到延迟加载的⽅法有get和load,使⽤get时,不会延迟加载,load则反之。

另外,在many-to-one等关系配置中,我们也可以通过lazy属性设置是否延迟加载,这是我们对hibernate最直观的认识。

2、现象解释----动态代理机制 所以,开头说到的奇怪现象的原因是什么呢?其实在hibernate设置延迟加载后,hibernate返回给我们的对象(要延迟加载的对象)是⼀个代理对象,并不是真实的对象,该对象没有真实对象的数据,只有真正需要⽤到对象数据(调⽤getter等⽅法时)时,才会触发hibernate去数据库查对应数据,⽽且查回来的数据不会存储在代理对象中,所以这些数据是⽆法在调试窗⼝查看到的。

如果在调试是要查看该数据,我们可以查看代理对象中的hadler属性中的target变量,该对象变量才是真实的对象,看下⾯截图:也就是说,我们user变量仅仅是⼀个代理类,target才是真正数据库中获取的数据。

当我们在调⽤getter⽅法式,hibernate会利⽤动态代理的⽅法,直接调⽤target中的getter⽅法发挥对应的值。

MyBatis官方中文文档

MyBatis官方中文文档

提示 命名空间的一点注释
命名空间(Namespaces)在之前版本的 MyBatis 中是可选的,容易引起混淆因此是没有益处的。现在的命名空 间则是必须的,目的是希望能比只是简单的使用更长的完全限定名来更进一步区分语句。 命名空间使得你所见到的接口绑定成为可能,尽管你觉得这些东西未必用得上,你还是应该遵循这里的规定以防哪 天你改变了主意。出于长远考虑,使用命名空间,并将它置于合适的 Java 包命名空间之下,你将拥有一份更加整 洁的代码并提高了 MyBatis 的可用性。 命名解析:为了减少输入量,MyBatis 对所有的命名配置元素(包括语句,结果映射,缓存等)使用了如下的命名 解析规则。 完全限定名(比如“com.mypackage.MyMapper.selectAllThings”)将被直接查找并且找到即用。 短名称(比如“selectAllThings”)如果全局唯一也可以作为一个单独的引用。如果不唯一,有两个或两个以上的相 同名称(比如“com.foo.selectAllThings ”和“com.bar.selectAllThings”),那么使用时就会收到错误报告说短名称 是不唯一的,这种情况下就必须使用完全限定名。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-////DTD Config 3.0//EN" "/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>

黑马程序员资料参考

黑马程序员资料参考

目录北京黑马培训简介: (2)报名流程: (2)自学课程: (2)上课时间安排:(实行指纹打卡,迟到10天以上劝退!) (3)课程设置:(四个月集训) (3)培训费用: (3)师资力量:(部分) (3)往届课程参考: (6)黑马晨读资料: (14)(ref. full specialization) (22)CCP(communication[kə,mju:ni'keiʃən]control [kən'trəul]processor ['prəusesə]) 通信控制处理机 (27)MIPS(millions of instructions per second 每秒百万条指令 (30)学习路线图: (40)北京黑马培训 JAVA Android IOS北京黑马培训简介:报名流程:1.网上填写报名信息,并进入报名系统提交一封自荐信(3000字左右)2.下载基础测试,测试基础知识掌握情况。

(3天左右做完)3.根据基础测试结果,自学相应的技术视频4.需要写10篇技术blog、在黑马论坛与志同道合的朋友交流。

(积累技术分)5.技术储备好了,就可以参加入学考试了。

(一份试卷,一天内完成)6.预约老师,进行远程面试。

(面试时间30分钟以上,主要是技术性问题)自学课程:黑马程序员JavaEE+Android——开学前自学的Java课程(提供这些课程的视频下载)◇基础好:视频学习周期建议为5—10天,具体根据学生自学能力,自行合理安排时间。

第一阶段:Java基础(1-2天)●Java高级视频_IO输入与输出●Java高级视频_网络编程第二阶段:Java基础加强(3-4天)●2016年Java高新技术第三阶段:7k月薪面试题破解(2天)●交通灯管理系统视频●银行业务调度系统◇没有基础:视频学习周期建议为20-40天,具体根据学生自学能力,自行合理安排时间。

第一阶段:Java初级(8-15天)●Java开发前奏●Java编程基础●面向对象●多线程●JavaAPI第二阶段:Java基础(6-8天)●Java高级视频_IO输入与输出●图形用户界面GU●Java高级视频_网络编程第三阶段:Java基础加强(5-7天)●2016年Java高新技术第四阶段:7k月薪面试题破解(2-3天)●交通灯管理系统视频●银行业务调度系统上课时间安排:(实行指纹打卡,迟到10天以上劝退!)作息时间:早8:30——晚8:30早8:30——9:00 英语晨读时间,掌握软件开发常用词汇早9:00——12:00 上午上课时间12:00——14:00 午餐和午休时间14:00——17:00 下午上课时间17:00——18:00 晚餐时间18:00——20:30 晚自习时间课程设置:(四个月集训)第一阶段:Html+CSS+JavaScript基础第二阶段:JavaWEB+JavaMail开发技术+网上银行交易系统+网上在线支付第三阶段:Android核心基础第四阶段:Android高级+Git版本管理+linux+Webservice技术第五阶段:Android项目实战:手机卫士+321播放器+红孩子电子商城+植物大战僵尸+智能短信分类管理+豆瓣客户端+手机彩票等等第六阶段:就业面试与指导、现场招聘一个班级有7、8个讲师,其中3个主讲班型:大班70人左右上课形式:讲师一天讲5个小时左右,讲课过程中每敲一行代码,讲解一行代码;课下学员自己找时间练习。

MyBatis的延迟加载

MyBatis的延迟加载

MyBatis 的延迟加载 问题:在⼀对多的关系中,例:有⼀个班级,其中有100个学⽣,在查询班级的时候要不要把关联的学⽣查询出来,查询学⽣的时候要不要把关联的班级查询出来? 解答:在查询班级的时候,学⽣的信息应该是什么时候使⽤什么时候去查询,在查询学⽣时,班级的信息应该是随着学⽣查询时⼀起查询出来。

⼀、延迟加载概念:MyBatis 中的延迟加载也称为懒加载,是指在进⾏表的关联查询时,按照设置延迟规则推迟对关联对象的select 查询。

在真正使⽤数据的时候才发起查询,不⽤的时候不查询关联的数据,延迟加载⼜叫做按需查询。

例如,在进⾏⼀对多查询的时候,只查询出⼀⽅,当程序中需要多⽅数据时,MyBatis 在发出sql 语句进⾏查询,这样⼦延迟加载就可以减少数据库压⼒,MyBatis 的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执⾏查询语句的。

MyBatis 中延迟加载的条件:resultMap 可以实现⾼级映射,例:使⽤association 、collection 实现⼀对⼀及⼀对多映射,association 、collection 具备延迟加载功能。

延迟加载的好处:先从单表查询,需要时再从关联表查询,⼤⼤提⾼数据库性能,因为查询单表⽐关联查询多张表速度要快。

使⽤场景:在对应的四种关系表中,⼀对多、多对多通常情况下采⽤延迟加载,多对⼀、⼀对⼀、通常采⽤⽴即加载。

延迟加载的应⽤要求:关联对象的查询与主加载对象的查询必须是分别进⾏的select 语句,不能是使⽤多表连接所进⾏的select 查询,因为多表连接查询,实质是对⼀张表的查询,对由多个表连接后形成的⼀张表的查询,会⼀次性将多张表的所有信息查询出来。

⼆、开启延迟加载功能 MyBatis中实现查询⽅法的延迟加载,在MyBatis的配置⽂件中通过设置settings的lazyLoadingEnabled属性为true进⾏开启全局的延迟加载,通过aggressiveLazyLoading属性开启⽴即加载。

Java单例模式:懒加载(延迟加载)和即时加载

Java单例模式:懒加载(延迟加载)和即时加载

Java单例模式:懒加载(延迟加载)和即时加载引⾔在开发中,如果某个实例的创建需要消耗很多系统资源,那么我们通常会使⽤惰性加载机制(或懒加载、延时加载),也就是说只有当使⽤到这个实例的时候才会创建这个实例,这个好处在单例模式中得到了⼴泛应⽤。

这个机制在单线程环境下的实现⾮常简单,然⽽在多线程环境下却存在隐患。

1、单例模式的惰性加载通常当我们设计⼀个单例类的时候,会在类的内部构造这个类(通过构造函数,或者在定义处直接创建),并对外提供⼀个static getInstance() ⽅法提供获取该单例对象的途径。

public class Singleton{private static Singleton instance = new Singleton();private Singleton(){…}public static Singleton getInstance(){return instance;}}这样的代码缺点是:第⼀次加载类的时候会连带着创建 Singleton 实例,这样的结果与我们所期望的不同,因为创建实例的时候可能并不是我们需要这个实例的时候。

同时如果这个Singleton 实例的创建⾮常消耗系统资源,⽽应⽤始终都没有使⽤ Singleton 实例,那么创建Singleton 消耗的系统资源就被⽩⽩浪费了。

为了避免这种情况,我们通常使⽤惰性加载的机制,也就是在使⽤的时候才去创建。

public class Singleton{private static Singleton instance = null;private Singleton(){…}public static Singleton getInstance(){if (instance == null)instance = new Singleton();return instance;}}2、惰性加载在多线程中的问题先将惰性加载的代码提取出来:public static Singleton getInstance(){if (instance == null)instance = new Singleton();return instance;}这是如果两个线程 A 和 B 同时执⾏了该⽅法,然后以如下⽅式执⾏:A 进⼊ if 判断,此时 foo 为 null,因此进⼊ if 内B 进⼊ if 判断,此时 A 还没有创建 foo,因此 foo 也为 null,因此 B 也进⼊ if 内A 创建了⼀个 Foo 并返回B 也创建了⼀个 Foo 并返回此时问题出现了,我们的单例被创建了两次,⽽这并不是我们所期望的。

hibernate延迟加载的原理与实现

hibernate延迟加载的原理与实现

hibernate延迟加载的原理与实现大概一年半前,我开始了Java之旅。

上来就是spring MVC + hibernate3 + spring的架构让我最头痛的就是hiberante3。

后来项目因为数据量大,被迫改成了JDBC。

现在回想当初那个hibernate3使用的相当菜了(现在似乎也算刚刚入门),而且对很多hibernate的概念原理懵懵懂懂,用的不好,招来老板对hibernate的一顿质疑。

一年半后的今天。

当我再次看待hibernate时,除了当年隐隐约约的“委屈”涌上心头,更希望让大家了解hibernate,不要仅仅从应用角度出发。

好了,咱们今天来看看hibernate关于延迟加载的原理与实现。

主要使用的就是CGLib。

首先看一段熟悉的代码:Java代码1.public void testLazy() {2.// 自己弄了一个丑陋的sessionFactory和session,主要是因为自己写的,比较容易控制。

3.SessionFactory<User, String> sessionFactory = new Sessi onFactoryImpl<User, String>(er.class);5.Session<User, String> session = sessionFactory.openSessi on();er u = session.load("1");7.// 这一句不会触发数据库查询操作,请看图18.assertEquals("1", u.getId());9.// 访问的是非主键属性,开始查询数据库,请看图210.assertNotSame("11", u.getName());11.session.close();12.}图1:通过断点,我们可以看到User对象只是一个代理,并且只有主键id有值图2:通过断点,我们可以看到原本属于代理对象的User,其targetObject一项已经有值了,表示已经发出select语句从数据库取值了。

黑马程序员mybatis教程第二天:延迟加载

黑马程序员mybatis教程第二天:延迟加载

延迟加载什么是延迟加载resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。

需求:如果查询订单并且关联查询用户信息。

如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。

把对用户信息的按需去查询就是延迟加载。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

使用association实现延迟加载需求查询订单并且关联查询用户信息mapper.xml需要定义两个mapper的方法对应的statement。

1、只查询订单信息SELECT * FROM orders在查询订单的statement中使用association去延迟加载(执行)下边的satatement(关联查询用户信息)2、关联查询用户信息通过上边查询到的订单信息中user_id去关联查询用户信息使用UserMapper.xml中的findUserById上边先去执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来。

延迟加载resultMap使用association中的select指定延迟加载去执行的statement的id。

<!-- 延迟加载的resultMap --><resultMap type= id="OrdersUserLazyLoadingResultMap"><!--对订单信息进行映射配置 --><id column="id"property="id"/><result column="user_id"property="userId"/><result column="number"property="number"/><result column="createtime"property="createtime"/><result column="note"property="note"/><!-- 实现对用户信息进行延迟加载select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)要使用userMapper.xml中findUserById完成根据用户id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespacecolumn:订单信息中关联用户信息查询的列,是user_id关联查询的sql理解为:SELECT orders.*,(SELECT username FROM USER WHERE er_id = user.id)username, (SELECT sex FROM USER WHERE er_id = user.id)sexFROM orders--><association property="user"javaType=select= column="user_id"><!-- 实现对用户信息进行延迟加载 --></association></resultMap>mapper.java测试测试思路:1、执行上边mapper方法(findOrdersUserLazyLoading),内部去调用中的findOrdersUserLazyLoading只查询orders信息(单表)。

mybatis resulttype加载原理

mybatis resulttype加载原理

mybatis resulttype加载原理MyBatis是一个开源的持久层框架,它提供了一个针对于Java程序的简化数据库访问的解决方案。

在使用MyBatis进行数据库操作时,我们需要配置返回结果的类型,这就涉及到了MyBatis的ResultType加载原理的问题。

1. MyBatis基本概念在深入探讨ResultType加载原理之前,我们先来了解一些基本的MyBatis概念。

1.1. ResultMap:ResultMap是MyBatis中的一个核心概念,它可以将查询结果映射成Java对象。

通过ResultMap,我们可以定义查询结果的映射规则,使得MyBatis可以自动将查询结果转换为Java对象。

1.2. ResultType:ResultType是MyBatis用于映射查询结果的一种方式。

通过配置ResultType,我们可以告诉MyBatis查询结果的类型是什么。

2. ResultType的使用方式在MyBatis中,我们可以通过三种方式来配置ResultType,包括基本类型、JavaBean以及Map。

2.1. 基本类型当查询结果只有一个字段时,我们可以使用基本类型来配置ResultType。

例如,如果查询结果为一个整数,我们可以将ResultType 设置为Integer。

2.2. JavaBean当查询结果包含多个字段,并且需要将这些字段映射到Java对象时,我们可以使用JavaBean来配置ResultType。

例如,如果查询结果包含id、name和age三个字段,我们可以定义一个对应的User类,并将ResultType设置为User。

2.3. Map当查询结果是一个复杂的分组结果时,我们可以使用Map来配置ResultType。

Map可以容纳任意类型的键值对,因此适合保存一组键值对形式的查询结果。

3. ResultType加载原理MyBatis加载ResultType的过程可以简单分为两步,第一步是根据配置的ResultType找到对应的Java类型,第二步是将查询结果映射到该Java类型上。

Mybatis查询延迟加载详解及实例

Mybatis查询延迟加载详解及实例

Mybatis查询延迟加载详解及实例Mybatis查询延迟加载详解及实例1.1 启⽤延迟加载Mybatis的延迟加载是针对嵌套查询⽽⾔的,是指在进⾏查询的时候先只查询最外层的SQL,对于内层SQL将在需要使⽤的时候才查询出来。

Mybatis的延迟加载默认是关闭的,即默认是⼀次就将所有的嵌套SQL⼀并查了将对象所有的信息都查询出来。

开启延迟加载有两种⽅式。

第⼀种是在对应的<collection>或<association>标签上指定fetchType属性值为“lazy”。

如下⽰例中我们在查询id为selectByPrimaryKey的查询时会返回BaseResultMap,在BaseResultMap中,我们指定了属性“nodes”是⼀个集合类型的,⽽且是需要通过id为selectNodes的查询进⾏查询的,我们指定了该查询的fetchType为lazy,即延迟加载。

<resultMap id="BaseResultMap" type="com.elim.learn.mybatis.model.SysWfProcess"><id column="id" jdbcType="INTEGER" property="id" /><result column="template_id" jdbcType="INTEGER" property="templateId" /><result column="creator" jdbcType="INTEGER" property="creator" /><result column="create_time" jdbcType="TIMESTAMP" property="createTime" /><collection property="nodes" column="id"ofType="com.elim.learn.mybatis.model.SysWfNode" select="selectNodes" fetchType="lazy"/></resultMap><resultMap id="SysWfNodeResult" type="com.elim.learn.mybatis.model.SysWfNode"><id column="id" jdbcType="INTEGER" property="nodeId" /><result column="process_id" jdbcType="INTEGER" property="processId" /><result column="node_code" jdbcType="VARCHAR" property="nodeCode" /><result column="node_name" jdbcType="VARCHAR" property="nodeName" /></resultMap><select id="selectByPrimaryKey" parameterType="ng.Integer"resultMap="BaseResultMap">select<include refid="Base_Column_List" />from sys_wf_processwhere id = #{id,jdbcType=INTEGER}</select><select id="selectNodes"resultMap="SysWfNodeResult">select id, process_id, node_code, node_name from sys_wf_nodewhere process_id=#{id}</select>第⼆种是开启全局的延迟加载。

mybatis延迟加载,及其实现原理

mybatis延迟加载,及其实现原理
mybatis支持association关联对象和collection关联集合对象的延迟加载association指的是一对一collection指的是一对多查询
mybatis延 迟 加 载 , 及 其 实 现 原 理
mybatis支持association关联对象和collection关联集合对象的延迟加载,association指的是一对一,collection指的是一对多查询
mybatis中延迟加载(lazyLoadingEnabled=true|false)的原理:
使用CGLIB创建目标对象的代理对象,调用方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是 null,就会单独发送事先保存好的查询关联B对象ห้องสมุดไป่ตู้sql,把B查询出来。然后调用a.setB(b),这样a对象的b属性就会有值了,接着完成 a.getB().getName()方法的调用,这就是延迟加载的基本原理

三、MyBatis系列:Mapper映射之关联对象属性及延迟加载

三、MyBatis系列:Mapper映射之关联对象属性及延迟加载

三、MyBatis系列:Mapper映射之关联对象属性及延迟加载在开发时,经常有这种需求,我拿到了⼀个order表单实体时,我需要知道该表单是属于哪个⽤户的。

这时访问 order.getUser() 获取⽤户信息,这时应该得到⼀个⽤户的信息实例。

解决这个问题的⽅法有三种:1、通过1条SQL语句进⾏关联查询,同时读取表单和⽤户信息;2、同时发送2条SQL,⽤于读取 order 与 user信息;3、先⽤1条SQL读取order表单信息,访问getUser()时再⽤另1个SQL读取user信息;实体定义如下:1public class User {2private Integer id;3private String username;4private Date birthday;5private String sex;6private String address;7 }8public class Order {9private int id;10private User user;11private int number;12private Date createtime;13private String note;14 }第⼀种⽅法:使⽤关联查询的 mapper 的配置1<resultMap type="cn.xleos.mybatis.po.Order" id="orderUserMap">2<id property="id" column="orders_id"/>3<result property="createtime" column="orders_createtime"/>4<result property="number" column="orders_number"/>5<result property="note" column="orders_note"/>6<association property="user" javaType="er">7<id property="id" column="user_id"/>8<result property="username" column="user_username"/>9<result property="birthday" column="user_birthday"/>10<result property="sex" column="user_sex"/>11<result property="address" column="user_address"/>12</association>13</resultMap>14<select id="getOrdersAndUser">15 SELECT16 orders.id AS orders_id,17 orders.number AS orders_number,18 orders.createtime AS orders_createtime,19 orders.note AS orders_note,20 `user`.id AS user_id,21 `user`.username AS user_username,22 `user`.birthday AS user_birthday,23 `user`.sex AS user_sex,24 `user`.address AS user_address25 FROM orders26 INNER JOIN `user` ON `user`.id = er_id27</select>第⼆种⽅法,使⽤⼆条SQL语句来完成读取表单与⽤户信息在读取order关联时 association 节使⽤了 select="getUserById" 属性,它表⽰使⽤ getUserById 这个SQL来读取⽤户信息。

Mybatis延迟加载详解

Mybatis延迟加载详解

Mybatis延迟加载详解MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。

延迟加载可以有效的减少数据库压力。

注意:MyBatis的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执行查询语句的。

一、关联对象加载时机MyBatis根据对关联对象查询的select语句的执行时机,分为三种类型:直接加载、侵入式加载与深度延迟加载•直接加载:执行完对主加载对象的select语句,马上执行对关联对象的select查询。

•侵入式延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。

但当要访问主加载对象的详情时,就会马上执行关联对象的select查询。

即对关联对象的查询执行,侵入到了主加载对象的详情访问中。

也可以这样理解:将关联对象的详情侵入到了主加载对象的详情中,即将关联对象的详情作为主加载对象的详情的一部分出现了。

•深度延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。

访问主加载对象的详情时也不会执行关联对象的select查询。

只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。

注意:延迟加载的应用要求,关联对象的查询与主加载对象的查询必须是分别进行的select语句,不能是使用多表连接所进行的select查询。

因为,多表连接查询,其实质是对一张表的查询,对由多个表连接后形成的一张表的查询。

会一次性将多张表的所有信息查询出来。

二、直接加载1.主配置文件(Mybatis.xml)全局属性lazyLoadingEnabled的值只要设置为false,那么,对于关联对象的查询,将采用直接加载。

即在查询过主加载对象后,会马上查询关联对象。

lazyLoadingEnabled的默认值为false,即直接加载。

<settings><!-- 延迟加载总开关 --><setting name="lazyLoadingEnabled" value="false"/></settings>2.mapper映射文件<mapper namespace="com.hcx.dao.IMinisterDao"><select id="selectCountryById" resultType="Country">select cid,cname from country where cid=#{cid}</select><resultMap type="Minister" id="ministerMapper"><id column="mid" property="mid"/><result column="mname" property="mname"/><association property="country"javaType="Country"select="selectCountryById"column="countryId"/></resultMap><select id="selectMinisterById"resultMap="ministerMapper">select mid,mname,countryId from minister where mid=#{mid}</select></mapper>3.测试类:当程序执行到断点处语句时,不仅对country表进行了查询,对minister表也同时进行了查询。

mybatis总结(五)(延迟加载)

mybatis总结(五)(延迟加载)

延迟加载的配置项配置项作⽤配置选项说明默认值lazyLoadingEnabled延迟加载的全局开关。

当开启时,所有关联对象都会延迟加载。

在特定关联关系中,可通过设置fetchType属性来覆盖该项的开关状态true|false falseaggressiveLazyLoading当启⽤时,对任意延迟属性的调⽤会使带有延迟加载属性的对象完整加载;反之,则每种属性按需加载。

true|false版本3.4.1(包含)之前为true,之后为falsemybatis总结(五)(延迟加载)延迟加载的含义延迟加载⼜叫按需查询(懒加载),mybatis⽀持延迟加载,我们希望⼀次性把常⽤的级联数据通过sql直接查询出来,⽽对于那些不常⽤的的级联数据不要取出,⽽是等待要⽤的时候才取出,这些不常⽤的级联数据可以采⽤延迟加载的功能。

延迟加载的配置在mybatis的settings配置中存在两个元素可以配置级联lazyLoadingEnabled表⽰延迟加载的总开关,如果将其设置为false,即使侵⼊式开关设置为true也不会⽣效。

aggressiveLazyLoading表⽰侵⼊式延迟加载开关,在3.4.1版本之前默认是true,之后默认是false。

<settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="true"/></settings>延迟加载的优缺点优点:先从单表查询,需要时再从关联表去关联查询,⼤⼤提⾼数据库的性能,因为查询单表要⽐关联查询多张表的速度快很多。

缺点:因为只有当需要⽤到数据时,才会进⾏数据库查询,这样在⼤批量数据查询时,因为查询⼯作也需要耗费时间,所以可能造成⽤户等待时间变长,造成⽤户体验下降。

Mybatis如何实现关联属性懒加载

Mybatis如何实现关联属性懒加载

Mybatis如何实现关联属性懒加载Mybatis 关联属性懒加载延迟加载配置mybatis默认没有开启延迟加载,需要在config.xml中setting配置。

lazyLoadingEnabled:true使⽤延迟加载,false禁⽤延迟加载,默认为false。

aggressiveLazyLoading:true启⽤时,当延迟加载开启时访问对象中⼀个懒对象属性时,将完全加载这个对象的所有懒对象属性。

false,当延迟加载时,按需加载对象属性(即访问对象中⼀个对象属性时,不会加载对象中的引⽤属性)。

默认为true。

修改延迟加载需要的select语句延迟加载场景分析查询订单时,需要关联查询订单明细表假设有10 个订单,每个订单有5个明细信息。

如果⽤户仅仅需要查看订单信息,不需要订单明细信息,但是查询了10+50个对象到内存(只有10个是⽤户想要的)。

显然是增加内存的负担。

如果⽤户的需求仅仅是查询订单信息,我仅仅订单信息⽤户,没有查询订单的详情,那么,内存中只有10对象(10个对象全是客户想的),这样做显然节省了内存。

业务需求特点:需要的时候在进⾏查询,不需要的时候不尽兴查询,这种情况就是延迟加载,也叫作懒加载。

配置过程去掉sql语句中对user表的查询语句对resultMap orderAndUser 进⾏修改注意:查询订单时要同时查询userid,避免查询user时没有凭据修改orderMapper.xml⽂件select语句<!-- 关联属性延迟加载 --><select id="queryOrderAndUser" resultMap="orderAndUser">selecto.id oids,o.orderid,o.createtime,o.note,eridfrom orders o,t_user uwhere erid=u.id</select><resultMap type="orders" id="orderAndUser"><id property="id" column="oids"></id><result property="orderId" column="orderid"></result><result property="createtime" column="createtime" /><result property="note" column="note" /><association property="user" javaType="users"select="erMapper.queryUserById" column="userid"><!--这⾥不查询⽤户的信息,⽽是将⽤的信息放在另外⼀个查询中column是order表中的userid字段--></association></resultMap>因为在assocication多了⼀个select元素,就要在UserMapper中多加⼀个⽅法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

延迟加载
什么是延迟加载
resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。

需求:
如果查询订单并且关联查询用户信息。

如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。

把对用户信息的按需去查询就是延迟加载。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

使用association实现延迟加载
需求
查询订单并且关联查询用户信息
mapper.xml
需要定义两个mapper的方法对应的statement。

1、只查询订单信息
SELECT * FROM orders
在查询订单的statement中使用association去延迟加载(执行)下边的satatement(关联查询用户信息)
2、关联查询用户信息
通过上边查询到的订单信息中user_id去关联查询用户信息
使用UserMapper.xml中的findUserById
上边先去执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来。

延迟加载resultMap
使用association中的select指定延迟加载去执行的statement的id。

<!-- 延迟加载的resultMap -->
<resultMap type="cn.itcast.mybatis.po.Orders"id="OrdersUserL azyLoadingResultMap">
<!--对订单信息进行映射配置 -->
<id column="id"property="id"/>
<result column="user_id"property="userId"/>
<result column="number"property="number"/>
<result column="createtime"property="createtime"/>
<result column="note"property="note"/>
<!-- 实现对用户信息进行延迟加载
select:指定延迟加载需要执行的statement的id(是根据
user_id查询用户信息的statement)
要使用userMapper.xml中findUserById完成根据用户
id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespace
column:订单信息中关联用户信息查询的列,是user_id
关联查询的sql理解为:
SELECT orders.*,
(SELECT username FROM USER WHERE er_id =
user.id)username,
(SELECT sex FROM USER WHERE er_id = user.id)sex FROM orders
-->
<association property="user"javaType="cn.itcast.mybatis.po.U ser"
select="erMapper.findUserById"co
lumn="user_id">
<!-- 实现对用户信息进行延迟加载 -->
</association>
</resultMap>
mapper.java
测试
测试思路:
1、执行上边mapper方法(findOrdersUserLazyLoading),内部去调用
cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查询orders信息(单表)。

2、在程序中去遍历上一步骤查询出的List<Orders>,当我们调用Orders中的getUser方法时,开始进行延迟加载。

3、延迟加载,去调用UserMapper.xml中findUserbyId这个方法获取用户信息。

延迟加载配置
mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。

在mybatis核心配置文件中配置:
在SqlMapConfig.xml中配置:
测试代码
延迟加载思考
不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??
实现方法如下:
定义两个mapper方法:
1、查询订单列表
2、根据用户id查询用户信息
实现思路:
先去查询第一个mapper方法,获取订单信息列表
在程序中(service),按需去调用第二个mapper方法去查询用户信息。

总之:
使用延迟加载方法,先去查询简单的sql(最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。

相关文档
最新文档