Mybatis课堂笔记

Mybatis课堂笔记,第1张

Mybatis课堂笔记

目录
  • 1、Mybatis概述
    • 1.1 Mybatis概念
    • 1.2 JDBC编程
    • 1.3 Mybatis解决的问题
  • 2、Mybatis入门案例
    • 2.1 创建数据库和表
    • 2.2 创建maven项目,添加Mybatis的jar依赖
    • 2.3 编写Mybatis的配置文件
    • 2.4 编写实体类
    • 2.5 编写ORM映射文件
      • 2.5.1 XML映射文件必须与实体类在同一个包下面
      • 2.5.2 XML映射文件名称必须是实体类名称一致
    • 2.6 将映射文件注册到mybatis的配置文件中
    • 2.7 配置映射文件的扫描位置
    • 2.8 使用Mybatis框架的核心接口测试
    • 2.9入门案例的增删改查
      • 2.9.1 根据ID查询单个对象
      • 2.9.2 增删改
  • 3、Mybatis对象分析
    • 3.1 Resources
    • 3.2 SqlSessionFactoryBuilder
    • 3.3 SqlSessionFactory
    • 3.4 SqlSession
    • 3.5 Mybatis架构
  • 4、配置日志文件
    • 4.1 添加jar依赖
    • 4.2 添加日志配置文件
    • 4.3 在mybatis配置文件中添加日志的配置
    • 4.4 结果
  • 5、使用原有的Dao方式开发
    • 5.1 创建工具类
      • 5.1.1 ThreadLocal
      • 5.1.2 工具类
    • 5.2 创建TeamDao接口和实现类
  • 6、使用Mapper的接口编写Mybatis项目
    • 6.1 什么是Mapper接口
    • 6.2 实现步骤
      • 6.2.1 编写接口TeamMapper.java
      • 6.2.2 getMapper方法获取代理对象
    • 6.3 实现原理
  • 7、增删改查中的细节
    • 7.1 插入数据的时候获取自增的id
      • 7.1.1 案例准备
        • 7.1.1.1 添加一张新表
        • 7.1.1.2 实体类
        • 7.1.1.3 mapper接口
      • 7.1.2 修改配置文件
      • 7.1.3 测试类
    • 7.2 输入映射
      • 7.2.1 parameterType
        • 7.2.3.2 通过@Param注解
        • 7.2.3.3 通过map来传递多个参数
        • 7.2.3.4 通过pojo类传递多个参数
    • 7.3 #{} 和 ${}的区别--面试中喜欢出的考题
      • 7.3.1 #{}
    • 7.3.2 ${}
    • 7.4 输出映射
      • 7.4.1 resultType
        • 7.4.1.1 输出简单类型
        • 7.4.1.2 输出pojo类型
        • 7.4.1.3 输出Map类型
      • 7.4.2 resultMap
      • 7.4.3 数据库表中列与实体类属性不一致的处理方式
        • 7.4.3.1 使用列别名和resultType
        • 7.4.3.2 使用resultMap
  • 8、Mybatis的全局配置文件
    • 8.1 配置的内容
    • 8.2 属性(properties)
    • 8.3 设置 settings
    • 8.4 类型别名 typeAliases
      • 8.4.1 Mybatis中已经支持的别名
      • 8.4.2 自定义别名
    • 8.5 映射器 Mappers
      • 8.5.1、 使用相对于类路径的资源引用
      • 8.5.2、使用映射器接口实现类的完全限定类名
      • 8.5.3、将包内的映射器接口实现全部注册为映射器--推荐
    • 8.6 dataSource标签
    • 8.7 事务
      • 8.7.1、默认是需要手动提交事务的
      • 8.7.2、自动提交事务
  • 9、Mybatis中的关系映射
    • 9.1 对一关系的映射
      • 9.1.1 实体类
      • 9.1.2 mapper接口
      • 9.1.3 对一映射方式1:通过关联对象打点调用属性的方式
      • 9.1.4 对一映射方式2:直接引用关联对象的Mapper映射
      • 9.1.5 对一映射方式3:直接引用关联对象的单独查询的方法
      • 9.1.6 测试
    • 9.2 对多关系的映射
      • 9.2.1 方式1:连接查询+引用关联对象的结果映射
      • 9.2.2 方式2:引用关联对象的单独查询的方法
      • 9.2.3测试:
  • 10、动态SQL
    • 10.1 where标签在select中的使用
    • 10.2 set标签在update中的使用
      • 10.2.1 更新的原有写法
      • 10.2.2 使用set标签构建动态的SQL语句
    • 10.3 forEach标签
      • 10.3.1 批量添加
      • 10.3.2 批量删除
  • 11 、分页插件
    • 11.1 jar依赖
    • 11.2 在Mybatis全局配置文件中添加插件配置
    • 11.3 使用插件
  • 12、Mybatis缓存
    • 12.1 缓存作用
    • 12.2 一级缓存:自动开启,SqlSession级别的缓存
      • 12.2.1 一级缓存分析
      • 12.2.2 清空缓存的方式
    • 12.3 二级缓存:Mapper级别的缓存
      • 12.3.1 使用二级缓存步骤
      • 12.3.2 二级缓存的禁用
      • 12.3.3 缓存的属性配置
  • 13、反向生成插件
    • 13.1 插件的配置
    • 13.2 使用反向生成中的多条件查询方法

1、Mybatis概述 1.1 Mybatis概念

MyBatis 本是 apache 的一个开源项目 iBatis, 2010 年这个项目由 apache software foundation 迁移到了 google code,并且改名为MyBatis 。2013 年 11 月迁移到 Github。iBATIS 一词来源于“internet”和“abatis”的组合,是一个基于 Java 的持久层框架。iBATIS 提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAO)。

Mybatis 基于java的持久层框架,它的内部封装了JDBC,让开发人员只需要关注SQL语句本身,不需要花费精力在驱动的加载、连接的创建、Statement的创建等复杂的过程。

Mybatis通过XML或注解的方式将要执行的各种的statement配置起来,并通过java对象和statement中的sql的动态参数进行映射生成最终执行的SQL语句,最后由mybatis框架执行SQL,并将结果直接映射为java对象。

采用了ORM思想解决了实体类和数据库表映射的问题。对JDBC进行了封装,屏蔽了JDBCAPI底层的访问细节,避免我们与jdbc的api打交道,就能完成对数据的持久化 *** 作。

  • O–Object java对象
  • R- Relation 关系,就是数据库中的一张表
  • M-mapping 映射
1.2 JDBC编程
public class TestJDBC {
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			//加载驱动
			Class.forName("com.mysql.cj.jdbc.Driver");
			String url="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT";
			//获取连接
			conn= DriverManager.getConnection(url,"root","root");
			//SQL语句
			String sql="select * from team;";
			ps=conn.prepareStatement(sql);
			//执行查询
			rs = ps.executeQuery();
			//遍历结果集
			List list=new ArrayList<>();
			while (rs.next()){
				Team team=new Team();
				team.setTeamName(rs.getString("teamName"));
				team.setTeamId(rs.getInt("teamId"));
				team.setCreateTime(rs.getDate("createTime"));
				team.setLocation(rs.getString("location"));
				list.add(team);
			}
			list.forEach(team -> System.out.println(team));
		} catch (Exception e){
			e.printStackTrace();
		} finally {
			try {
				//关闭资源
				if (rs != null){
					rs.close();
				}
				if (ps != null){
					ps.close();
				}
				if (conn != null){
					conn.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}	
}
1.3 Mybatis解决的问题
  1. 数据库连接的创建、释放连接的频繁 *** 作造成资源的浪费从而影响系统的性能。
  2. SQL语句编写在代码中,硬编码造成代码不容易维护,实际应用中SQL语句变化的可能性比较大,一旦变动就需要改变java类。
  3. 使用preparedStatement的时候传递参数使用占位符,也存在硬编码,因为SQL语句变化,必须修改源码。
  4. 对结果集的解析中也存在硬编码。
2、Mybatis入门案例 2.1 创建数据库和表
CREATE TABLE `team` (
	`teamId` int NOT NULL AUTO_INCREMENT COMMENT '球队ID',
	`teamName` varchar(50) DEFAULT NULL COMMENT '球队名称',
	`location` varchar(50) DEFAULT NULL COMMENT '球队位置',
	`createTime` date DEFAULT NULL COMMENT '球队建立时间',
	PRIMARY KEY (`teamId`)
) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
2.2 创建maven项目,添加Mybatis的jar依赖

        
            org.mybatis
            mybatis
            3.5.6
        
        
            mysql
            mysql-connector-java
            8.0.23
        
        
            junit
            junit
            4.12
            test
        
        
    

    
        
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.0
                
                    1.8
                    1.8
                
            
            
        
    
2.3 编写Mybatis的配置文件

一般情况下:配置文件的名称可以自定义,课程中使用mybatis.xml。配置文件放置在java/resources中。

头文件去官网中复制粘贴。在这里给大家提供一个中文的网站。Mybatis网址





    
    
        
        
            
            
            
            
                
                
                
                
               
            
        
    

2.4 编写实体类

实体类中的属性必须与表中的列名保持一致

public class Team {
    private Integer teamId;
    private String teamName;
    private String location;
    private Date createTime;
    //关系字段:一个球队可以拥有多个球员
    //一方(球队)持有多方(球员)的集合
    private List playerList1;
    private List playerList2;

    @Override
    public String toString() {
        return "Team{" +
                "teamId=" + teamId +
                ", teamName='" + teamName + ''' +
                ", location='" + location + ''' +
                ", createTime=" + createTime +
                ", playerList1=" + playerList1 +
                ", playerList2=" + playerList2 +
                '}';
    }
	//省略set get方法
}
2.5 编写ORM映射文件

我们是针对实体类Team.java和表Team进行ORM映射。

Mybatis框架中,ORM映射是针对SQL语句进行,Mybatis框架将SQL语句抽取到了XML中。所以我们需要针对每个实体类编写XML映射文件。

2.5.1 XML映射文件必须与实体类在同一个包下面 2.5.2 XML映射文件名称必须是实体类名称一致

头文件在网站复制即可。






	
	
		select * from team;
	

2.6 将映射文件注册到mybatis的配置文件中




	
    
        
        
            
            
            
            
                
                
                
                
                
            
        
    
    
    	
    

2.7 配置映射文件的扫描位置

pom.xml文件配置映射文件的扫描路径


    
        
            src/main/java
            
                ***.xml
            
            false
        
    
    
        //省略
    

2.8 使用Mybatis框架的核心接口测试
public class TestTeam {

    private String resource="mybatis.xml"; //画的图纸

    @Test
    public void test01(){
        SqlSession sqlSession=null;
        try {
            //读取配置文件
            Reader reader = Resources.getResourceAsReader(resource);
            //创建工厂
            SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);//根据图纸创建出了工厂
            //获取连接
            sqlSession= factory.openSession();
            //执行sql
            List list = sqlSession.selectList("com.kkb.pojo.Team.queryAll");
            //遍历结果
            for (Team team : list) {
                System.out.println(team);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            sqlSession.close();
        }
    }
}
2.9入门案例的增删改查 2.9.1 根据ID查询单个对象

Team.xml的映射文件中添加:


    select * from team
    where teamId>=#{param1} and teamId<=#{param2}

测试类添加方法:

public class TestTeamMapperArg {
    private TeamMapper teamMapper= MybatisUtil.getSqlSession().getMapper(TeamMapper.class);

    @Test
    public void test01(){
        List teams = teamMapper.queryByRange1(1004, 1010);
        teams.forEach(team -> System.out.println(team));
    }
}
7.2.3.2 通过@Param注解

在方法的形参前面加入@Param(“自定义参数名称”),mapper文件中使用#{自定义参数名称}的方式传参。

TeamMapper接口添加如下内容:

List queryByRange2(@Param("min") Integer min, @Param("max") Integer max);

TeamMapper.xml配置文件中添加如下:


    select * from team
    where teamId>=#{min} and teamId<=#{max}

测试类添加方法:

@Test
public void test03(){
    Map map=new HashMap<>();
    map.put("min",1010);
    map.put("max",1015);
    List teams = teamMapper.queryByRange3(map);
    teams.forEach(team -> System.out.println(team));
}
7.2.3.4 通过pojo类传递多个参数

与map传递多个参数类似,要求映射文件中的参数占位符必须和pojo类中的属性完全一致。

实体类:

public class QueryVO {
    private String name;
    private Integer min;
    private Integer max;
    private String location;
    //省略set get
}

TeamMapper接口添加如下内容:

List queryByCondition(QueryVO vo);

TeamMapper.xml配置文件中添加如下:


    select * from team where teamId=#{id}


7.3.2 ${}

表示字符串原样替换,通知Mybatis 使用美元符号包含的“字符串”替换所在位置。使用 Statement或者PreparedStatement 把 sql 语句和${}的内容连接起来。一般用在替换表名,列名,不同列排序等 *** 作。

例如:根据球队名称,球队位置查询球队列表

方式1:

TeamMapper接口添加如下内容:

List queryByName(String teamName);
List queryByLocation(String location);

TeamMapper.xml配置文件中添加如下:


    select * from team where teamName=#{teamName}


    select * from team where ${column}=#{columnValue}

测试类添加方法:

@Test
public void test06(){
    System.out.println("根据球队名称查询:");
    List teams = teamMapper.queryByFiled("teamName","lina的球队");
    teams.forEach(team -> System.out.println(team));
    System.out.println("根据球队位置查询:");
    List teams2 = teamMapper.queryByFiled("location","洛杉矶");
    teams2.forEach(team -> System.out.println(team));
}
7.4 输出映射 7.4.1 resultType

resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。如果返回的是集合,设置的是集合元素的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。

7.4.1.1 输出简单类型

案例:返回球队的总记录数

TeamMapper接口添加如下内容:

int getCount();

TeamMapper.xml配置文件中添加如下:


    select * from team

7.4.1.3 输出Map类型

当我们只需要查询表中几列数据的时候可以将sql的查询结果作为Map的key和value。一般使用的是Map

Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录会抛出TooManyResultsException异常。

如果有多行,使用List>。

案例:根据id查询球队名称和位置。

TeamMapper接口添加如下内容:

Map queryTwoColumn(int teamId);
List> queryTwoColumnList();

TeamMapper.xml配置文件中添加如下:


    select count(teamId) as 'sum',max(teamId) as 'max' from team group by location;

测试类添加方法:

@Test
public void test08(){
    Map map = teamMapper.getTwoColumn();
    System.out.println(map);
}
@Test
public void test09(){
    List> list = teamMapper.getTwoColumnList();
    for (Map map : list) {
        System.out.println(map);
    }
}
7.4.2 resultMap

resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。
常用在列名和 java 对象属性名不一样的情况。
使用方式:

  1. 先定义 resultMap,指定列名和属性的对应关系。
  2. 在TeamMapper接口中添加:
List queryAll2();

TeamMapper.xml映射文件添加:


        select user_id as userId,user_name as userName,user_age as userAge from users where user_id=#{id};
    

测试类TestUsersMapper.java

public class TestUsersMapper {
    private UsersMapper mapper= MybatisUtil.getSqlSession().getMapper(UsersMapper.class);
    @Test
    public void test1(){
        Users user = mapper.queryById(1);
        System.out.println(user);
    }
}
7.4.3.2 使用resultMap

接口UsersMapper.java添加方法

Users queryByID2(int userId);

映射文件UsersMapper.xml添加如下内容:


        select * from player where teamId=#{id}
    
    
        SELECT * FROM `player` p INNER JOIN team t
        on t.teamId=p.teamId
         where playerid=#{id}
    
    
        
        
        
        
    

    
    
        select * from player where playerId=#{id}
    
    
            
    


9.1.6 测试
public class TestPlayerMapper {
    private PlayerMapper playerMapper= MybatisUtil.getSqlSession().getMapper(PlayerMapper.class);
    private TeamMapper teamMapper=MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
    @Test
    public void test1(){
        Player player = playerMapper.queryById(1);
        System.out.println(player);
    }
    @Test
    public void test2(){
        Player player = playerMapper.queryById1(1);
        System.out.println(player);
    }
    @Test
    public void test3(){
        Player player = playerMapper.queryById2(1);
        System.out.println(player);
    }
}
9.2 对多关系的映射

修改实体类Team.java:

public class Team implements Serializable {
    private Integer teamId;
    private String teamName;
    private String location;
    private Date createTime;
    //关系字段:一个球队可以拥有多个球员
    //一方(球队)持有多方(球员)的集合
    private List playerList1;
    private List playerList2;
}

TeamMapper.java接口中添加方法:

public interface TeamMapper {
	Team queryById1(Integer teamId);
	Team queryById2(Integer teamId);
}

PlayerMapper.java接口中添加方法:

public interface PlayerMapper {
    List queryByTeamId(int teamId);
}
9.2.1 方式1:连接查询+引用关联对象的结果映射 9.2.2 方式2:引用关联对象的单独查询的方法

TeamMapper.xml添加


    select * from team where teamId=#{id}


    

PlayerMapper.xml添加如下内容:


    select * from team
    
        
        
            and teamName like concat(concat('%',#{name}),'%')
        
        
            and createTime>=#{beginTime}
        
        
            and createTime<=#{endTime}
        
        
            and location=#{location}
        
    

测试:

public class TestSQL {
    private TeamMapper teamMapper= MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
    
    @Test
    public void test1(){
        QueryTeamVO vo=new QueryTeamVO();
        vo.setName("人");
        vo.setEndTime(new Date());
        vo.setLocation("加利福尼亚州洛杉矶");
        List teams = teamMapper.queryByVO(vo);
        for (Team team : teams) {
            System.out.println(team);
        }
    }
}

10.2 set标签在update中的使用 10.2.1 更新的原有写法

TeamMapper.java接口中的方法:

int update(Team team);

TeamMapper.xml映射文件对应的内容:


    update team set teamName=#{teamName},location=#{location},createTime=#{createTime}
    where teamId=#{teamId}

测试类中添加测试方法:

@Test
public void test2(){
    Team team=new Team();
    team.setTeamId(1055);
    team.setTeamName("zeyang");
    int update = teamMapper.update1(team);
    MybatisUtil.getSqlSession().commit();
    System.out.println(update);
}

10.2.2 使用set标签构建动态的SQL语句

TeamMapper.java接口中添加方法:

int update1(Team team);

TeamMapper.xml映射文件对应的内容:


    update team
    
        
            teamName=#{teamName},
        
        
            location=#{location},
        
        
            createTime=#{createTime},
        
    
    where teamId=#{teamId}

测试类:

@Test
public void test2(){
    Team team=new Team();
    team.setTeamId(1055);
    team.setTeamName("zeyang");
    int update = teamMapper.update1(team);
    MybatisUtil.getSqlSession().commit();
    System.out.println(update);
}

10.3 forEach标签 10.3.1 批量添加

TeamMapper.java接口中添加方法:

void addList(List list);

TeamMapper.xml映射文件对应的内容:


    INSERT INTO team (teamName,location) VALUES
    
    
        (#{t.teamName},#{t.location})
    

测试类:

@Test
public void test3(){
    List list=new ArrayList<>();
    for(int i=1;i<=3;i++){
        Team team=new Team();
        team.setTeamName("zeyang"+i);
        team.setLocation("bj"+i);
        list.add(team);
    }
    teamMapper.addList(list);
    MybatisUtil.getSqlSession().commit();
}
10.3.2 批量删除

TeamMapper.java接口中添加方法:

void delList(List list);

TeamMapper.xml映射文件对应的内容:


    delete from team where teamId  in
    
    
        #{teamId}
    

测试类:

@Test
public void test4() {
    List list = new ArrayList<>();
    list.add(1109);
    list.add(1110);
    list.add(1111);
    teamMapper.delList(list);
    MybatisUtil.getSqlSession().commit();
}
11 、分页插件 11.1 jar依赖

    com.github.pagehelper
    pagehelper
    5.1.10

11.2 在Mybatis全局配置文件中添加插件配置

    
    
        
    

11.3 使用插件
@Test
public void test5() {
    // PageHelper.startPage 必须紧邻查询语句,而且只对第一条查询语句生效
    PageHelper.startPage(2,5);
    List teams = teamMapper.queryAll();//查询语句结尾不能有分号
    teams.forEach(team-> System.out.println(team));
    PageInfo info=new PageInfo<>(teams);
    System.out.println("分页信息如下:");
    System.out.println("当前页:"+info.getPageNum());
    System.out.println("总页数:"+info.getPages());
    System.out.println("前一页:"+info.getPrePage());
    System.out.println("后一页:"+info.getNextPage());
    System.out.println("navigatepageNums:"+info.getNavigatepageNums());
    for (int num : info.getNavigatepageNums()) {
        System.out.println(num);
    }
}

PageInfo.java的部分源码:

public class PageInfo extends PageSerializable {
	//当前页
    private int pageNum;
    //每页的数量
    private int pageSize;
    //当前页的数量
    private int size;
    //由于startRow和endRow不常用,这里说个具体的用法
    //可以在页面中"显示startRow到endRow 共size条数据"

	//当前页面第一个元素在数据库中的行号
    private int startRow;
    //当前页面最后一个元素在数据库中的行号
    private int endRow;
    //总页数
    private int pages;
    //前一页
    private int prePage;
    //下一页
    private int nextPage;
    //是否为第一页
    private boolean isFirstPage;
    //是否为最后一页
    private boolean isLastPage;
    //是否有前一页
    private boolean hasPreviousPage;
    //是否有下一页
    private boolean hasNextPage;
    //导航页码数
    private int navigatePages;
    //所有导航页号
    private int[] navigatepageNums;
    //导航条上的第一页
    private int navigateFirstPage;
    //导航条上的最后一页
    private int navigateLastPage;
}
12、Mybatis缓存 12.1 缓存作用

缓存是一般的ORM 框架都会提供的功能,目的就是提升查询的效率和减少数据库的压力。将经常查询的数据存在缓存(内存)中,用户查询该数据的时候不需要从磁盘(关系型数据库文件)上查询,而是直接从缓存中查询,提高查询效率,解决高并发问题。

MyBatis 也有一级缓存和二级缓存,并且预留了集成第三方缓存的接口。

Mybatis的缓存结构体系:

12.2 一级缓存:自动开启,SqlSession级别的缓存

在 *** 作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。

当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。

Mybatis默认开启一级缓存,存在内存中(本地缓存)不能被关闭,可以调用clearCache()来清空本地缓存,或者改变缓存的作用域。

12.2.1 一级缓存分析

工作原理图:


当用户发起第一次查询team=1001的时候,先去缓存中查找是否有team=1001的对象;如果没有,继续向数据中发送查询语句,查询成功之后会将teamId=1001的结果存入缓存中;

当用户发起第2次查询team=1001的时候,先去缓存中查找是否有team=1001的对象,因为第一次查询成功之后已经存储到缓存中,此时可以直接从缓存中获取到该数据,意味着不需要再去向数据库发送查询语句。

如果SqlSession执行了commit(有增删改的 *** 作),此时该SqlSession对应的缓存区域被整个清空,目的避免脏读。

前提:SqlSession未关闭。

测试类:

public class TestCache {
    private SqlSession sqlSession= MybatisUtil.getSqlSession();
    //测试一级缓存:自动开启,sqlSession级别的缓存
    @Test
    public void test1() {
        Team t1=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//第一次查询,先查缓存,此时缓存中没有,继续向数据库发送查询语句
        System.out.println(t1);//查询完毕之后数据被自动存入缓存区域
        Team t2=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//第二次查询,因为缓存中已经有了该数据,可以直接获取,不需要发送查询语句
        System.out.println(t2);
        MybatisUtil.closeSqlSession();//关闭连接,缓存清空
        sqlSession=MybatisUtil.getSqlSession();//再次获取连接,此时缓存为空
        Team t3=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//新连接下第一次查询,肯定发送查询语句
        System.out.println(t3);//查询完毕之后数据被自动存入缓存区域
        int num=sqlSession.delete("com.kkb.mapper.TeamMapper.del",10000);
        sqlSession.commit();//提交之后缓存被整个清空
        System.out.println("删除结果:"+num);
        Team t4=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//第二次查询,因为缓存已经被上一次的提交清空了,所以还是需要发送查询语句
        System.out.println(t4);
        sqlSession.close();
    }
}
12.2.2 清空缓存的方式
  1. session.clearCache( ) ;
  2. execute update(增删改) ;
  3. session.close( );
  4. xml配置 flushCache=“true” ;
  5. rollback;
  6. commit。
12.3 二级缓存:Mapper级别的缓存

多个SqlSession去 *** 作同一个Mapper的sql语句,多个SqlSession去 *** 作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace。

不同的sqlSession两次执行相同namespace下的sql语句参数相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。

Mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。

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

二级缓存原理图:

12.3.1 使用二级缓存步骤

二级缓存是mapper范围级别的,默认不启用。

  1. 在Mybatis框架的全局配置文件中开启二级缓存

  1. 在需要二级缓存的Mapper中添加缓存标志
  2. 实体类必须实现Serializable接口
  3. 测试二级缓存
    如果两个session不是从同一个Factory获取,那么二级缓存将不起作用。
    @Test
    public void test2() {
        SqlSession sqlSession1 = MybatisUtil.getSqlSession();
        Team t1 = sqlSession1.selectOne("com.kkb.mapper.TeamMapper.queryById", 1001);//先查缓存,没有,先数据库,查询完毕写入二级缓存
        System.out.println(t1);
        MybatisUtil.closeSqlSession();//关闭连接,一级缓存清空,二级缓存存在

        SqlSession sqlSession2 = MybatisUtil.getSqlSession();
        Team t2 = sqlSession2.selectOne("com.kkb.mapper.TeamMapper.queryById", 1001);//先查缓存,有,直接获取,不需要查询数据库
        System.out.println(t2);
        MybatisUtil.closeSqlSession();//关闭连接,一级缓存清空,二级缓存存在

        SqlSession sqlSession3 = MybatisUtil.getSqlSession();
        int num = sqlSession3.delete("com.kkb.mapper.TeamMapper.del", 10000);//删除成功
        System.out.println("删除的结果:" + num);
        sqlSession3.commit();//提交之后清空二级缓存
        MybatisUtil.closeSqlSession();//关闭连接,缓存清空

        SqlSession sqlSession4 = MybatisUtil.getSqlSession();
        Team t3 = sqlSession4.selectOne("com.kkb.mapper.TeamMapper.queryById", 1001);先查缓存,曾经有,但是上一个提交已经清空了缓存,所以只能去数据库中查询,查询完毕写入二级缓存
        System.out.println(t3);
        MybatisUtil.closeSqlSession();//关闭连接,缓存清空
    }

12.3.2 二级缓存的禁用

对于变化比较频繁的SQL,可以禁用二级缓存。

在开始了二级缓存的XML中对应的statement中设置useCache=false禁用当前Select语句的二级缓存,意味着该SQL语句每次只需都去查询数据库,不会查询缓存。

useCache默认值是true。对于一些很重要的数据尽不放在二级缓存中。

12.3.3 缓存的属性配置

    
    
    
    

源码:

如果想在命名空间中共享相同的缓存配置和实例,可以使用cache-ref 元素来引用另外一个缓存。


//引用TeamMapper命名空间中的cache。
13、反向生成插件 13.1 插件的配置

在pom.xml文件中的中中添加如下插件配置


    org.mybatis.generator
    mybatis-generator-maven-plugin
    1.3.5
    
        
        src/main/resources/generatorConfig.xml
        true
    
    
        
            org.mybatis.generator
            mybatis-generator-core
            1.3.5
        
    

generatorConfig.xml内容






    
    

    

        
        
            
        

        
        
        

        
        
            
        

        
        
            
        
        
        
        
        
        
        

        
        
        
            
        
        
            
        
        
            
        
        
    

注意只能运行一次,运行完毕显示BUILD SUCCESS即为成功。

13.2 使用反向生成中的多条件查询方法
public class TestGenerator {
    private TeamMapper mapper= MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
    @Test
    public void test1(){
        Team team = mapper.selectByPrimaryKey(1001);
        System.out.println(team);
    }
    @Test
    public void test2(){
        Team team=new Team();
        team.setTeamName("lina-test");
        team.setLocation("bj");
        int i = mapper.insert(team);
        MybatisUtil.getSqlSession().commit();
        System.out.println(i);
    }
    @Test
    public void test3(){
        //可以理解为为多条件、排序等服务的类
        TeamExample example=new TeamExample();
        //理解为盛放条件的容器
        TeamExample.Criteria criteria = example.createCriteria();
        //向容器中添加条件
        criteria.andTeamNameLike("人");
        criteria.andTeamIdBetween(1001,1100);
        //排序
        example.setOrderByClause("teamName desc");
        List teams = mapper.selectByExample(example);
        for (Team team : teams) {
            System.out.println(team);
        }
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4658586.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-06
下一篇 2022-11-06

发表评论

登录后才能评论

评论列表(0条)

保存