1. 认识一蛤什么是懒加载
什么是懒加载?所谓懒加载,简单说就是按需加载,用于查询结果存在一对一或一对多的情况,在mybatis中体现在
2. 便于理解,来个场景
上面的介绍也是很多网上很多人的说法,这样就太笼统、抽象了,举个例子:
比如我的demo中的Teacher类中属性有
t_id(int型),
t_name(String型),
stuList(List型),
其中stuList顾名思义既是这个老师教的学生的集合。
而Student类是对应的student表,里面的属性有
id(int型),
stu_name(String型),
age(int型),
t_id(int型),
其中student表中的t_id和teacher表中的t_id是对应的。
那么懒加载就来了,如果我要查询这个老师的所有信息,但是现在我还不想看他到底教哪些学生,那么后台就会先查询这个老师的除了学生表之外的信息。当我要看这个老师到底教了哪些学生时,再向数据库发送一条sql单独查询哪些学生的属性带有这个老师的t_id。
3. 具体代码实现
要用到懒加载,就要多用到两个jar包,asm和cglib:
导了jar后,需要在总
config.xml
中进行一些配置:
其中懒加载相关的配置只有后两行,不过第一行的日志有助于跟进mabatis的执行。
然后dao中写好接口TeacherDao.java
:
package demo.cyj.dao;
import demo.cyj.pojo.Teacher;
public interface TeacherDao {
public Teacher findTeacherByTname(String tname);
}
后面就是重头了,mapperTeacherMapper.xml
中的代码:
可以看到,这个有懒加载的查询分为了两个
(如果你的表字段和类的属性名不同,可以通过取别名或在
(
在
-
ofType="Student"
指定了这个集合的存放(组装对象)类型,类似泛型; -
property="stuList"
指定了这个集合在Teacher类中的属性名; -
fetchType="lazy"
指定了哪种加载方式; -
column="t_name"
指定了上一条sql中查询出来的结果中的哪一列的值会被传递到下一条sql中作为条件值; -
select="findTeacherByTnameLazy"
指定了下一条被执行的
而在第二条
最后写测试类Test.java
:
package demo.cyj;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import demo.cyj.dao.StudentDao;
import demo.cyj.dao.TeacherDao;
import demo.cyj.pojo.Student;
import demo.cyj.pojo.Teacher;
public class Test {
public static void main(String[] args) throws IOException {
String src = "config.xml";
InputStream inputStream = Resources.getResourceAsStream(src);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sessionFactory.openSession(true);
//绑定
TeacherDao td = sqlSession.getMapper(TeacherDao.class);
Teacher t= td.findTeacherByTname("htc");
System.out.println(t.getT_id());
}
}
运行后可以看到控制台打印的结果:
这是因为这段代码
System.out.println(t.getT_id());
,我只想看这个名为htc的老师的id是多少,所以只向数据库发送了一条sql,没有去查stuList的信息。
然后修改代码:
public class Test {
public static void main(String[] args) throws IOException {
String src = "config.xml";
InputStream inputStream = Resources.getResourceAsStream(src);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sessionFactory.openSession(true);
//绑定
TeacherDao td = sqlSession.getMapper(TeacherDao.class);
Teacher t= td.findTeacherByTname("htc");
System.out.println(t);
}
}
修改的代码为System.out.println(t);
,即打印该名为htc的老师的所有信息,包括stuList.
运行后可以看到控制台打印的结果:
控制台信息太长没显示完,附一个控制台信息:
==> Preparing: select t.t_id t_id,t.t_name t_name from teacher t where t.t_name =?
==> Parameters: htc(String)
<== Columns: t_id, t_name
<== Row: 1, htc
<== Total: 1
==> Preparing: select s.id id,s.stu_name stu_name,s.stu_age age,s.t_id t_id from student s left join teacher t on t.t_id = s.t_id where t.t_name=?
==> Parameters: htc(String)
<== Columns: id, stu_name, age, t_id
<== Row: 8, 黑拐, 43, 1
<== Row: 9, 拐, 50, 1
<== Row: 10, 拐棍, 50, 1
<== Row: 11, 大黑拐, 30, 1
<== Row: 12, 小黑拐, 12, 1
<== Row: 13, 拐哥, 29, 1
<== Row: 14, 胡黑拐, 123, 1
<== Total: 7
Teacher [t_id=1, t_name=null, stuList=[Student [id=8, stu_name=黑拐, age=43, t_id=1], Student [id=9, stu_name=拐, age=50, t_id=1], Student [id=10, stu_name=拐棍, age=50, t_id=1], Student [id=11, stu_name=大黑拐, age=30, t_id=1], Student [id=12, stu_name=小黑拐, age=12, t_id=1], Student [id=13, stu_name=拐哥, age=29, t_id=1], Student [id=14, stu_name=胡黑拐, age=123, t_id=1]]]
可以看到,这次的sql语句有两条了,一次是查询该老师的基本信息,一次是查询该老师教的学生的列表。
总结一下:
- 懒加载就是按需加载,如果有的数据需要关联其他表查询,而暂时又不用展示,就可以先不查询它,等到要展示的时候才查询它
- 还是要仔细,越是不熟的东西就越要看清楚了,不然很多时间都会浪费在寻找格式等错误上