所谓的延迟加载也是就是说关系属性加载的延迟。不用不查,用的时候再查
resultMap中的association和collection标签具有延迟加载的功能。
延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息。需要关联信息时再去按需加载关联信息。这样会大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
Mybatis默认是不开启延迟加载功能的,我们需要手动开启。需要在SqlMapConfig.xml文件中,在标签中开启延迟加载功能。
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
settings>
设置项 | 描述 | 允许值 | 默认值 |
---|---|---|---|
lazyLoadingEnabled | 全局性设置懒加载。如果设为false,则所有相关联的都会被初始化加载。 | true | false | false |
aggressiveLazyLoading | 当设置为true的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 | true | false | true |
查询订单并且关联查询用户信息(对用户信息的加载要求是按需加载)
需要定义两个mapper的方法对应的statement。
1、只查询订单信息
SELECT * FROM orders
在查询订单的statement中使用association去延迟加载(执行)下边的satatement(关联查询用户信息)
<resultMap type="com.qf.mybatis.po.Orders" id="OrdersUserLazyLoadingRstMap">
<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" />
<association property="user" select="com.qf.mybatis.mapper.UserMapper.findUserById" column="user_id">association>
resultMap>
<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingRstMap">
SELECT * FROM orders
select>
2、关联查询用户信息
通过上边查询到的订单信息中user_id去关联查询用户信息
使用UserMapper.xml中的findUserById
<select id="findUserById" parameterType="int"
resultType="com.qf.mybatis.po.User">
SELECT * FROM user WHERE id = #{id}
select>
上边先去执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来。
Mybatis的缓存,包括一级缓存和二级缓存: mybatis提供查询缓存,如果缓存中有数据就不用从数据库中获取,用于减轻数据压力,提高系统性能。 测试1: 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。 第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。 正式开发,是将mybatis和spring进行整合开发,事务控制在service中。 一个service方法中包括 很多mapper方法调用。 如果是执行两次service调用查询相同 的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。 Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。 第一步:创建项目添加依赖 创建web项目名称:day05_web01 第二步:加入配置文件 Mybatis的核心配置mybatis-config.xml、log4j日志文件log4j.properties 第三步:创建POJO User.java 第四步:加入sql映射文件 在resources目录下创建com.qf.mapper文件夹,然后创建UserMapper.xml文件 第五步:加载映射文件 UserMapper接口中添加 UserMapper.xml文件中 UserService接口中添加 UserServiceImpl实现: 下载地址https://github.com/pagehelper/Mybatis-PageHelper/releases 使用步骤: 配置pageHelper插件有两种方式:(1)在mybatis-config.xml文件中(2)在Spring的配置文件中(后面学习) 在mybatis-config.xml文件中1.4、延迟加载思考
不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载?
实现方法如下:
定义两个mapper方法:
1、查询订单列表
2、根据用户id查询用户信息
实现思路:
先去查询第一个mapper方法,获取订单信息列表
在程序中(service),按需去调用第二个mapper方法去查询用户信息。
总之:
使用延迟加载方法,先去查询单表数据,再去按需要加载关联查询的其它信息。
1.2 MyBatis缓存
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
一级缓存是默认使用的。二级缓存需要手动开启。
1.2.1 一级缓存
1.2.1 mybatis缓存原理
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
@Test
public void testOneLevelCache() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 第一次查询ID为1的用户,去缓存找,找不到就去查找数据库
User user1 = mapper.findUserById(1);
System.out.println(user1);
// 第二次查询ID为1的用户
User user2 = mapper.findUserById(1);
System.out.println(user2);
sqlSession.close();
}
@Test
public void testOneLevelCache() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 第一次查询ID为1的用户,去缓存找,找不到就去查找数据库
User user1 = mapper.findUserById(1);
System.out.println(user1);
User user = new User();
user.setUsername("tom");
user.setAddress("北京");
//执行增删改操作,清空缓存
mapper.insertUser(user);
// 第二次查询ID为1的用户
User user2 = mapper.findUserById(1);
System.out.println(user2);
sqlSession.close();
}
1.2.2 应用
service方法{
//开始执行时,开启事务,创建SqlSession对象
//第一次调用mapper的方法findUserById(1)
//第二次调用mapper的方法findUserById(1),从一级缓存中取数据
//方法结束,sqlSession关闭
}
第二节:分页查询
2.1 环境准备
依赖信息如下:<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.45version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.6version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_01?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
dataSource>
environment>
environments>
configuration>
### set log levels - for more verbose logging change 'info' to 'debug' , 'off' ###
log4j.rootLogger=info, stdout,file
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
//getter和setter
}
<mapper namespace="">
MyBatis框架需要加载UserMapper.xml映射文件,将UserMapper.xml添加在mybatis-config.xml,如下:
<mappers>
<mapper resource="com/qf/mapper/UserMapper.xml"/>
mappers>
2.2 编写PageBean
package com.qf.domain;
import java.util.List;
/**
* @author wgy 2018/12/5 11:55
* @version 1.0
*/
public class PageBean<T> {
//页吗
private int pageNum;
//页大小
private int pageSize;
//总共数据个数
private long totalCount;
//总页数
private int totalPage;
//数据
private List<T> data;
//开始页码
private int startPage;
//结束页码
private int endPage;
public PageBean() {
}
public PageBean(int pageNum, int pageSize, long totalCount, List<T> data) {
this.pageNum = pageNum;
this.pageSize = pageSize;
this.totalCount = totalCount;
this.data = data;
//计算总页数
this.totalPage= (int) (totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1);
//开始页码
this.startPage=pageNum-4;
this.endPage=pageNum+5;
//特殊1
if(pageNum<5){
this.startPage=1;
this.endPage=10;
}
//特殊2
if(pageNum>totalPage-5){
this.startPage=totalPage-9;
this.endPage=totalPage;
}
//特殊3
if(totalPage<10){
this.startPage=1;
this.endPage=totalPage;
}
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public long getTotalCount() {
return totalCount;
}
public void setTotalCount(long totalCount) {
this.totalCount = totalCount;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
}
2.3 编写QueryVo
package com.qf.mybatis.pojo;
/**
* @author wgy 2018/12/14 21:43
* @version 1.0
*/
public class QueryVo<T> {
private T con;
private int pageNum;
private int pageSize;
private int offset;
private String orderBy;
public QueryVo(T con, int pageNum, int pageSize,String orderBy) {
this.con = con;
this.pageNum = pageNum;
this.pageSize = pageSize;
if(pageNum>0&&pageSize>0) {
this.offset = (pageNum - 1) * pageSize;
}
this.orderBy=orderBy;
}
public T getCon() {
return con;
}
public void setCon(T con) {
this.con = con;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public String getOrderBy() {
return orderBy;
}
public void setOrderBy(String orderBy) {
this.orderBy = orderBy;
}
}
2.4 添加Mapper方法
List<User> findByPage(QueryVo queryVo)
<select id="findUserByPage" parameterType="QueryVo" resultType="com.qf.mybatis.pojo.User">
select * from user
<if test="orderBy !=null orderBy !=''">
order by=${orderBy}
if>
limit #{offset},#{pageSize}
select>
2.5 添加Service
PageBean
2.6 编写Servlet
2.7 编写jsp页面
第三节:PageHelper的使用
在实际开发中,更多的是使用分页插件来减少代码冗杂,使编码更加清晰。
思路:分页控制的代码写在拦截器中,从而不影响本来的业务逻辑代码
第一步:添加依赖
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>4.2.1version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.1.6version>
dependency>
第二步:配置pageHelper插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
<property name="pageSizeZero" value="true"/>
<property name="reasonable" value="true"/>
plugin>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="pageSizeZero" value="true"/>
<property name="reasonable" value="true"/>
plugin>
plugins>
第三步:编写代码测试
@Test
public void queryAll(){
PageHelper.startPage(1, 3);
PageHelper.orderBy("id");
List<User> list = userMapper.queryAll();
PageInfo<User> p=new PageInfo<User>(list);
for (User user : list) {
System.out.println(user.toString());
}
System.out.println(p.getPages());
System.out.println(p.getPageSize());
System.out.println(p.getPageNum());
System.out.println(p.getOrderBy());
}
第四步:实现