延迟加载-association来实现
resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。
需求:
如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。
延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。
接下来我们用assocation来实现延迟加载:
先给出需求:
查询订单并且关联查询用户信息
老规矩:1.sql语句,2.pojo类,3.mapper.xml和mapper.java接口
第一步:
1。我们要实现延时加载,相当于先查订单(orders)的信息,等需要用到user的信息时再去查询User表。
也就是把
<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">
Select * from orders;
</select>
<select id="finduserByid" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE ID=#{VALUE}
</select>
上面两条select语句用延迟加载的方式实现。(用resultMap来连接这两条select语句)
第二步:
2.pojo类:
package cn.itcast.mybatis.po;
import java.util.Date;
import java.util.List;
public class Orders {
private Integer id;
private Integer user_id;
private String number;
private Date createtime;
private String note;
//用户信息,新增了一个User属性,为了保存查询得到的关联的User表的信息(一对一)
private User user;
public List<Orderdetail> getOrderdetail() {
return orderdetails;
}
public void setOrderdetail(List<Orderdetail> orderdetail) {
this.orderdetails = orderdetail;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
第三步:
3.编写OrderMapperCustom.xml代码:使用association中的select指定延迟加载去执行的statement的id。
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">这句代码的作用就是用来连接上面那两条select语句来实现延迟加载。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- nanmespace:命名空间。 作用就是对sql进行分类话管理,理解Sal分离
注意:使用mapper代理方式,namespace有特殊重要的作用
-->
<mapper namespace="cn.itcast.mybatis.mapper.OrdersMapperCustom">
<!-- 延迟加载的resultMap -->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">
<!--对订单信息进行映射配置 -->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">
<id column="id" property="id"/>
<result column="user_id" property="user_id"/>
<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 orders.user_id = user.id)username,
(SELECT sex FROM USER WHERE orders.user_id = user.id)sex
FROM orders
-->
<association property="user" javaType="cn.itcast.mybatis.po.User"
select="finduserByid" column="user_id"
>
</association>
</resultMap>
<select id="finduserByid" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE ID=#{VALUE}
</select>
<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">
Select * from orders;
</select>
</mapper>
编写OrdersMapperCustom.java接口:
package cn.itcast.mybatis.mapper;
import java.util.List;
import cn.itcast.mybatis.po.Orders;
import cn.itcast.mybatis.po.OrdersCustom;
import cn.itcast.mybatis.po.User;
public interface OrdersMapperCustom {
//函数的名字OrdersMapperCustom.xml中select中的id名一样
public List<Orders> findOrdersUserLazyLoading();
}
第四步:
不要忘记修改总的配置文件,setting 加上延迟加载的功能
延迟加载配置
mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。
在mybatis核心配置文件中配置:
lazyLoadingEnabled、aggressiveLazyLoading
|
设置项 |
描述 |
允许值 |
默认值 |
|
lazyLoadingEnabled |
全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。 |
true | false |
false |
|
aggressiveLazyLoading |
当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 |
true | false |
true |
在SqlMapConfig.xml中代码为:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- properties的配置必须写在typeAliases的上面 -->
<properties resource="db.properties"></properties>
<!-- 配置懒加载设置 -->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 把映射文件(sqlmap/user.xml)加载进sqlMapConfig.xml-->
<mappers>
<!-- 把mapper.xml加载进sqlMapConfig.xml-->
<!--
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致
且在一个目录中。
当着这个规范的前提是:使用mapper代理方法。
-->
<mapper class="cn.itcast.mybatis.mapper.OrdersMapperCustom"/>
</mappers>
</configuration>
第五步:
编写测试代码:
测试思路:
1、执行上边mapper方法(findOrdersUserLazyLoading),内部去调用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查询orders信息(单表)。
2、在程序中去遍历上一步骤查询出的List<Orders>,当我们调用Orders中的getUser方法时,开始进行延迟加载。
3、延迟加载,去调用UserMapper.xml中findUserbyId这个方法获取用户信息。
测试代码Mybatis_mappertest.java如下:
package cn.itcast.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
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 org.junit.Before;
import org.junit.Test;
import cn.itcast.mybatis.mapper.OrdersMapperCustom;
import cn.itcast.mybatis.mapper.userMapper;
import cn.itcast.mybatis.po.Orders;
import cn.itcast.mybatis.po.User;
import cn.itcast.mybatis.po.UserCustom;
import cn.itcast.mybatis.po.UserQueryVo;
public class Mybatis_mappertest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setup() throws IOException
{ String resource="SqlMapConfig.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
//主要是生成SqlsessionFactory。
this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testMaper()
{
SqlSession sqlSession=null;
sqlSession=sqlSessionFactory.openSession();
//生成代理类
OrdersMapperCustom orderMapper=sqlSession.getMapper(OrdersMapperCustom.class);
//创建包装对象,设置查询条件
//orderMapper.findOrdersUser();
@SuppressWarnings("unused")
List<Orders> list=orderMapper.findOrdersUserLazyLoading();
for(Orders orders:list)
{//只有执行了这一步才会执行延迟加载。
User user=orders.getUser();
System.out.println(user);
}
}
}
运行结果如下:
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@30647e13]
DEBUG [main] - ==> Preparing: Select * from orders;
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 3
DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE ID=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
cn.itcast.mybatis.po.User@1ff90029
我们看一下上面的结果:第一条sql语句:Select * from orders;
然后才会有:SELECT * FROM USER WHERE ID=?
实现了延迟加载

不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??
实现方法如下:
定义两个mapper方法:
1、查询订单列表
2、根据用户id查询用户信息
实现思路:
先去查询第一个mapper方法,获取订单信息列表
在程序中(service),按需去调用第二个mapper方法去查询用户信息。
总之:
使用延迟加载方法,先去查询简单的sql(最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。


浙公网安备 33010602011771号