Mybatis入门

本文概述了四天Mybatis教程内容,涵盖环境搭建、基础操作、深入多表查询、缓存与注解开发,带你快速掌握框架、SQL动态配置和高级技巧。

四天课程内容简介

视频链接:SSM框架合集
资料链接:Mybatis资料 提取码:xue9

  1. mybatis入门

    1. mybatis的概述
    2. mybatis环境搭建
    3. mybatis入门案例
    4. 自定义mybatis框架
  2. mybatis基本使用

    1. mybatis的单表crud操作
    2. mybatis的参数和返回值
    3. mybatis的dao编写(了解)
    4. mybatis配置的细节(几个标签的使用)
  3. mybatis的深入和多表

    1. mybatis的连接池以及事务控制
    2. mybatis基于XML配置动态SQL语句的使用
    3. mybatis的多表查询(一对多、一对一、多对多)
  4. mybatis的缓存和注解开发

    1. mybatis中的加载时机(查询的时机)
    2. mybatis中的一级缓存和二级缓存
    3. mybatis的注解开发(单表CRUD、多表查询)

第一天 mybatis入门

1 什么是框架?

  • 它是我们软件开发中的一套解决方案,不同的框架解决不同的问题
  • 使用框架的好处:框架封装了很多细节,开发者可以使用极简的方式实现功能,大大提高开发效率。

2 三层架构

avatar

  1. 表现层:用于展现数据
  2. 业务层:处理业务需求
  3. 持久层:与数据库交互

3 持久层技术解决方案

  1. JDBC技术

    1. Connection
    2. PreparedStatement
    3. ResultSet
  2. spring的JdbcTemplate:spring中对JDBC简单的封装

  3. Apache的DBUtils:也是对JDBC的简单封装

  • 以上这些都不是框架,JDBC是规范,其他两个只是工具类
  1. mybatis框架概述
    1. mybatis是一个持久层框架,使用java编写
    2. 它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动、创建连接等繁杂的过程
    3. 它使用ORM思想实现了对结果集的封装
    • ORM
      1. Object Relational Mapping 对象关系映射
      2. 简单来说,就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就实现操作数据库表

4 mybatis环境搭建

  1. 创建maven工程,导入坐标坐标
  2. 创建实体类和dao的接口
  3. 创建mybatis的主配置文件SqlMapConfig.xml
  4. 创建映射配置文件IUserDao.xml
  • 环境搭建注意事项
    1. 创建IUserDao.xml和IUserDao.java时,名称是为了和之前的知识保持一致。在Mybatis中持久层的操作接口名称和映射文件也叫作:Mapper。即:IUserDao的意思与IUserMapper的意思是一样的。
    2. idea中,创建目录与创建包不同
      • 创建包时,com.huangheng.dao是三级目录
      • 创建目录时,com.huangheng.dao是一级目录
    3. mybatis的映射配置文件位置必须和dao接口的包结构相同
    4. 映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
    5. 映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名
    • namespace + id才能定位到sql语句

5 mybatis入门案例

  1. 读取配置文件
  2. 创建SqlSessionFactory工厂
  3. 创建SqlSession
  4. 创建Dao接口的代理对象
  5. 执行dao中的方法
  6. 释放资源
  • 注意事项

    • 记得在映射配置中告知mybatis要封装到哪个实体类中
    • 配置方式:指定实体类的全限定类名resultType="com.huangheng.domain.User"
  • 步骤中的知识点解析

    1. 读取配置文件时,既不使用绝对路径,也不使用相对路径,使用这两种路径都有问题。会使用两种方法:
      1. 使用类加载器,它只能读取类路径的配置文件;
      2. 使用ServletContext对象的getRealPath()方法。
    2. 创建工厂,mybatis使用了构建者模式。
      • 构建者模式的优势:把对象创建细节隐藏,使用者直接调用方法即可拿到对象。
    3. 生产SqlSession使用了工厂模式。
      • 工厂模式的优势:解耦,降低类之间的依赖关系。
    4. 创建dao接口实现类使用了代理模式。
      • 代理模式的优势:不修改源码的基础上,对已有方法增强。

【源码】mybatis入门案例

6 mybatis注解开发

  1. 把IUserDao.xml移除,在dao接口的方法上使用@select注解,并指定sql语句
  2. 还需在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名。

【源码】mybatis注解开发

7 编写dao实现类

  • 注:实际开发中,越简单越好,一般可以不写dao实现类。但是mybatis支持写dao实现类。

8 mybatis使用配置文件进行工作的原理

avatar

视频中P11-P17讲解了如何自定义mybatis,某种意义上的自己仿照mybatis原理写一个mybatis

avatar

【源码】自定义mybatis源码

第二天 mybatis基本使用

1 mybatis的单表crud操作

  1. 新增
  2. 修改
  3. 删除
  4. 查询
  5. 新增之后,得到最后一个id
  6. 模糊查询
  7. 查找表的记录数
  8. 更复杂的sql单表操作

【源码】mybatis的单表CRUD源码

2 mybatis参数深入

  1. parameterType(输入类型)
    1. 传递简单类型
      • 比如:java.lang.Integer,INT,string
    2. 传递pojo对象
      • mybatis使用OGNL表达式解析对象字段的值,#{}${}括号中的值为pojo属性名称

      • OGNL表达式(object graphic navigation language,对象图导航语言)
        它是通过对象的取值方法来获取数据。在写法上把get省略了。

        比如:获取用户的用户名

        • 类中的写法:user.getUsername()
        • OGNL表达式写法:user.username

        mybatis中可以直接写属性名,不用使用点运算符,是因为:parameterType已经提供了属性所属的类。如果parameterType没有提供属性所属的类,则需要使用点运算符。

    3. 传递pojo包装对象(将多个查询条件封装到一个对象中)
      • 开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件,这时可以使用包装对象传递输入参数。
  2. resultType(输出类型)
    1. 输出简单类型

    2. 输出pojo对象

    3. 输出pojo列表

  • 解决实体类属性和数据库列名不对应的两种解决方案
    1. SQL语句层面,使用别名查询,效率更高

    2. java程序层面,配置查询结果的列名和类实体的属性名的对应关系,开发效率变高。此时需要涉及到resultmap属性

  1. resultmap
    resultMap标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。
    1. resultMap的配置规则
    <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
    <resultMap id="userMap" type="com.huangheng.domain.User">
        <!-- 主键字段的对应 -->
        <id property="userId" column="id"></id>
        <!--非主键字段的对应-->
        <result property="userName" column="username"></result>
        <result property="userAddress" column="address"></result>
        <result property="userSex" column="sex"></result>
        <result property="userBirthday" column="birthday"></result>
    </resultMap>
    
    1. resultMap的使用方法(标签中去掉resultType属性,添加resultMap属性)
    <select id="findAll" resultMap="userMap">
        <!--select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;-->
        select * from user;
    </select>
    

3 mybatis编写Dao实现类(了解)

【源码】mybatis编写Dao实现类

4 SqlMapConfig.xml配置文件

  1. properties标签
    • 可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息。
    1. resource属性
      • 用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
    2. url属性
      • URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
  2. typeAliases标签
    • 使用typeAliases配置别名,它只能配置domain中类的别名
    1. typeAlias标签
      • typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就再区分大小写。
    2. package标签
      • 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写
    <?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
        可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
        resource属性: 常用的
            用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
        url属性:
            是要求按照Url的写法来写地址
            URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
            它的写法:
                http://localhost:8080/mybatisserver/demo1Servlet
                协议      主机     端口       URI
    
            URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
    -->
    <properties url="file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.properties">
    <!-- <property name="driver" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"></property>
        <property name="username" value="root"></property>
        <property name="password" value="1234"></property>-->
    </properties>
    
    <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
    <typeAliases>
        <!--typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就再区分大小写 
        <typeAlias type="com.itheima.domain.User" alias="user"></typeAlias>-->
    
        <!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
        <package name="com.itheima.domain"></package>
    </typeAliases>
    
    <!--配置环境-->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>
    
            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射文件的位置 -->
    <mappers>
        <!--<mapper resource="com/itheima/dao/IUserDao.xml"></mapper>-->
        <!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了 -->
        <package name="com.itheima.dao"></package>
    </mappers>
    </configuration>
    

第三天 mybatis的深入和多表

1 mybatis中的连接池以及事务控制(原理部分了解,应用部分会用)

  1. mybatis连接池的使用及分析

    1. 连接池
      • 实际开发中都会使用到连接池,连接池可以减少获取连接所消耗的时间
      • 连接池就是用于存储连接的一个容器,容器其实就是一个集合对象,该集合必须是线程安全的,不能两个线程拿到同一连接。该集合还必须实现队列的特性:先进先出
    2. mybatis中的连接池
      • mybatis连接池配置的位置:主配置文件SqlMapConfig.xml中的dataSource标签,改标签的type属性就是表示采用何种连接池方式
      • type属性的取值
        1. POOLED(实际开发中使用)
          • 采用传统的javax.sql.DataSource规范中的连接池
          • 每次从连接池中获取一个连接来用,使用完之后,将连接返回连接池。
          • POOLED方式原理分析
            • idleConnections:空闲池
            • activeConnections:活动池
              avatar
        2. UNPOOLED
          • 采用传统获取连接的方式,没有使用池的思想
          • 每次创建一个新的连接,每次使用完之后,销毁连接。
        3. JNDI
          • 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到的DataSource是不一样的。
          • 注意:只有web或者maven的war工程才能使用
          • 本课程中使用的是tomcat服务器,采用的连接池是dbcp连接池
  2. mybatis事务控制的分析

    1. 事务的常见问题
      1. 什么是事务?
        • 访问并可能更新数据库中各种数据项的一个程序执行单元。
        • 一个事务可以是一条SQL语句,一组SQL语句或整个程序。
      2. 事务的四大特性ACID
        1. 原子性(atomicity):一个事务是一个不可分割的工作单位
        2. 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。
        3. 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
        4. 持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
      3. 不考虑隔离性的会产生的3个问题
        1. 脏读
          • 脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
        2. 不可重复读:
          • 一个事务两次读取同一行的数据,结果得到不同状态的结果,中间正好另一个事务更新了该数据,两次结果相异,不可被信任。
          • 通俗来讲就是:事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。
        3. 幻读(虚读)
          • 一个事务执行两次查询,第二次结果集包含第一次中没有或某些行已经被删除的数据,造成两次结果不一致,只是另一个事务在这两次查询中间插入或删除了数据造成的。
          • 通俗来讲就是:例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
      4. 实现隔离性的解决办法:四种隔离级别
        1. Read Uncommited(读取未提交内容)
          • 读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。
          • 但是,读未提交产生了脏读,采用读提交可以解决脏读问题。
        2. Read Commited(读取提交内容)-- 解决脏读
          • 读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。
          • 但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。但是,读提交两次查询会产生不同的查询结果,就会造成不可重复读问题,采用重复读可以解决此问题。
        3. Repeatable Read(重复读)-- 解决不可重复读
          • 重复读,就是在开始读取数据(事务开启)时,不再允许修改操作。重复读可以解决不可重复读问题。应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。
          • 但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。采用Serializable可以解决幻读问题
        4. Serializable(可串行化)–解决幻读
          • Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
    2. mybatis中的事务通过SqlSession对象的commit方法和rollback方法实现事务的提交和回滚。
      • mybatis中自动提交事务的设置:sqlSession = factory.openSession(true);

2 mybatis基于XML配置动态SQL语句的使用(会用即可)

  • mapper配置文件中的几个标签
    1. <if>
    2. <where>
    3. <foreach
    4. <sql>
      • 使用此标签可以抽取重复的sql语句,配合使用include标签重用sql语句
  • 实例代码
<?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">
<mapper namespace="com.itheima.dao.IUserDao">

    <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
    <resultMap id="userMap" type="uSeR">
        <!-- 主键字段的对应 -->
        <id property="userId" column="id"></id>
        <!--非主键字段的对应-->
        <result property="userName" column="username"></result>
        <result property="userAddress" column="address"></result>
        <result property="userSex" column="sex"></result>
        <result property="userBirthday" column="birthday"></result>
    </resultMap>

    <!-- 了解的内容:抽取重复的sql语句-->
    <sql id="defaultUser">
        select * from user
    </sql>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userMap">
        <include refid="defaultUser"></include>
    </select>

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultMap="userMap">
        select * from user where id = #{uid}
    </select>

    <!-- 根据名称模糊查询 -->
    <select id="findByName" parameterType="string" resultMap="userMap">
        select * from user where username like #{name}
</select>

    <!-- 根据queryVo的条件查询用户 -->
    <select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultMap="userMap">
        select * from user where username like #{user.userName}
    </select>

    <!-- 根据条件查询 -->
    <select id="findUserByCondition" resultMap="userMap" parameterType="user">
        select * from user where 1=1
        <if test="userName != null">
        and username = #{userName}
        </if>
        <if test="userSex != null">
            and sex = #{userSex}
        </if>
    </select>

    <select id="findUserByCondition" resultMap="userMap" parameterType="user">
        select * from user
        <where>
            <if test="userName != null">
                and username = #{userName}
            </if>
            <if test="userSex != null">
                and sex = #{userSex}
            </if>
        </where>
    </select>

    <!-- 根据queryvo中的Id集合实现查询用户列表 -->
    <select id="findUserInIds" resultMap="userMap" parameterType="queryvo">
        <include refid="defaultUser"></include>
        <where>
            <if test="ids != null and ids.size()>0">
                <foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
                    #{uid}
                </foreach>
            </if>
        </where>
    </select>
</mapper>

3 mybatis中的多表操作(掌握应用)

  • 表之间的关系有4种:一对多、多对一、一对一和多对多

    1. 一对多
      • 用户和订单是一对多
      • 一个用户可以下多个订单
    2. 多对一
      • 订单和用户是多对一
      • 多个订单属于一个用户
    3. 一对一
      • 人和身份证号是一对一
      • 一个人只能有一个身份证号
    4. 多对多
      • 老师和学生之间是多对多
      • 一个老师可以教多个学生,一个学生可以被多个老师教过
  • 注意:如果拿出每一个订单,它都只能属于一个用户,所以mybatis把多对一看成一对一

  • mybatis中一对多、一对一、多对一查询:

    • 问题示例:用户和账户
      1. 一个用户可以有多个账户
      2. 一个账户只能属于一个用户,多个账户可以属于一个用户
    • 步骤
      1. 建立两张表,用户表、账户表
        • 让用户表和账户表之间具备一对多的关系:在账户表中添加外键
      2. 建立两个实体类:用户实体类和账户实体类
        • 让用户实体类和账户实体类之间体现出一对多的关系
      3. 建立两个配置文件
        • 用户的配置文件
        • 账户的配置文件
      4. 实现配置
        • 当查询用户时,可以同时得到用户下所包的账户信息
        • 当查询账户时,可以同时得到账户的所属用户信息
    • 【源码】mybatis多表查询–一对多
  • mybatis中多对多查询:

    • 问题示例:用户和角色
      • 一个用户可以有多个角色
      • 一个角色可以赋予多个用户
    • 步骤
      1. 建立两张表:用户表、角色表
        • 让用户表和角色表具有多对多关系。
        • 需要使用中间表,中间表中包含用户表和角色表的主键,它们在中间表中是外键
      2. 建立两个实体:用户实体类和角色实体类
        • 让用户和角色的实体类能体现出多对多的关系
        • 各自包含对方的一个集合引用
      3. 建立两个配置文件
        • 用户的配置文件
        • 角色的配置文件
      4. 实现配置
        • 查询用户时,可以同时得到用户下所包含的角色信息
        • 查询角色时,可以同时得到角色的所赋予的用户信息
    • 【源码】mybatis多表查询–多对多
  • 补充 深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接

    1. 内连接(inner join)

      • 满足条件的记录才会出现在结果集中
        avatar

      【示例代码】

      -- 隐式内连接:
      select first_name, last_name, order_date, order_amount
      from customers, orders 
      where customers.customer_id = orders.customer_id
      
      -- 显示内连接:
      select first_name, last_name, order_date, order_amount
      from customers c
      inner join orders o
      on c.customer_id = o.customer_id
      
    2. 左外连接(left outer join,outer可省略)

      • 左表全部出现在结果集中,若右表无对应记录,则相应字段为NULL
        avatar

      【示例代码】

      select first_name, last_name, order_date, order_amount
      from customers c
      left join orders o
      on c.customer_id = o.customer_id
      
    3. 右外连接(right outer join,outer可省略)

      • 右表全部出现在结果集中,若左表无对应记录,则相应字段为NULL
        avatar

      【示例代码】

      select first_name, last_name, order_date, order_amount
      from customers c
      right join orders o
      on c.customer_id = o.customer_id
      
    4. 全连接(full outer join,outer可省略)

      • 全外连接=左外连接+右外连接
        avatar

      【示例代码】

      select first_name, last_name, order_date, order_amount
      from customers c
      full join orders o
      on c.customer_id = o.customer_id
      

4 补充:JNDI

  1. JNDI概述和原理
  2. JNDI搭建maven的war工程
  3. 测试JND数据源的使用以及使用细节

第四天 mybatis的缓存和注解开发

1 mybatis中的延迟加载

  • 问题的提出

    • 在一对多中,当我们有一个用户,它有100个账户。
    • 在查询用户的时候,要不要把关联的账户查出来?
    • 在查询账户的时候,要不要把关联的用户查出来?
  • 问题的解决

    • 在查询用户(一对多)时,用户下的账户信息应该是:什么时候用,什么时候查询
    • 在查询账户(多对一)时,账户所属的用户应该是随着账户查询一起查询出来。
  1. 什么是延迟加载

    • 在真正使用数据时,才发起查询,不用的时候不查询。
    • 按需加载(懒加载)
  2. 什么是立即加载

    • 不管用不用,只要一调用方法,马上发起查询。
  3. 对应的四种表关系中:一对多、多对一、一对一、多对多

    • 一对多、多对多:通常情况下采用延迟加载
    • 多对一、一对一:通常情况下采用立即加载
  4. mybatis开启延迟加载

    • 在主配置文件的configuration标签下添加以下内容
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>
    
    • 参数解释
      1. lazyLoadingEnabled
        avatar

      2. aggressiveLazyLoading
        avatar

  5. 一对一实现延迟加载

    1. 修改SQL语句
    2. 在association标签中的添加select属性和column属性
    • 对应的映射配置文件示例
      <?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">
      <mapper namespace="com.itheima.dao.IAccountDao">
      
          <!-- 定义封装account和user的resultMap -->
          <resultMap id="accountUserMap" type="account">
              <id property="id" column="id"></id>
              <result property="uid" column="uid"></result>
              <result property="money" column="money"></result>
              <!-- 一对一的关系映射:配置封装user的内容
              select属性指定的内容:查询用户的唯一标识:
              column属性指定的内容:用户根据id查询时,所需要的参数的值
              -->
              <association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById"></association>
          </resultMap>
      
          <!-- 查询所有 -->
          <select id="findAll" resultMap="accountUserMap">
              select * from account
          </select>
      
          <!-- 根据用户id查询账户列表 -->
          <select id="findAccountByUid" resultType="account">
              select * from account where uid = #{uid}
          </select>
      
      </mapper>
      
  6. 一对多实现延迟加载

    1. 修改SQL语句
    2. 在collection标签中的添加select属性和column属性
    • 对应的映射配置文件示例
    <?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">
    <mapper namespace="com.itheima.dao.IUserDao">
    
        <!-- 定义User的resultMap-->
        <resultMap id="userAccountMap" type="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
            <!-- 配置user对象中accounts集合的映射 -->
            <collection property="accounts" ofType="account" select="com.itheima.dao.IAccountDao.findAccountByUid" column="id"></collection>
        </resultMap>
    
        <!-- 查询所有 -->
        <select id="findAll" resultMap="userAccountMap">
            select * from user
        </select>
    
        <!-- 根据id查询用户 -->
        <select id="findById" parameterType="INT" resultType="user">
            select * from user where id = #{uid}
        </select>
    
    </mapper>
    

【源码】延迟加载

2 mybatis中的缓存

  1. 什么是缓存

    • 存在于内存中的临时数据
  2. 为什么使用缓存

    • 减少I/O次数(减少和数据库的交互次数,提高执行效率)
  3. 什么样的数据能使用缓存,什么样的数据不能使用缓存

    1. 适用于缓存

      1. 经常查询
      2. 不经常改变
      3. 数据的正确与否对最终结果影响不大
    2. 不适用于缓存

      1. 经常改变的数据
      2. 数据的正确与否对最终的结果影响很大
      • 例如:商品的库存、银行的汇率、股票的牌价
  4. mybatis中的一级缓存和二级缓存

    1. 一级缓存

      • 指的是:mybatis中SqlSession对象的缓存
      1. 当执行查询操作之后,查询的结果会同时存入SqlSession为我们提供的一块区域。
        • 该区域的结构是Map(映射表)
      2. 当查询的数据时,mybatis会先去SqlSession中查询是否有,有的话直接从一级缓存中拿出。
      3. 当SqlSession对象消失时,mybatis的一级缓存也就消失了。
      • sqlSession.clearCache() //此方法也可以清空sqlSession对象中的一级缓存
      1. 当调用sqlSession的修改、添加、删除、commit、close等方法时,就会清空sqlSession的一级缓存
    2. 二级缓存

      • 指的是:mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

      • 二级缓存开启步骤

        1. 让mybatis框架支持二级缓存(在主配置文件中配置)

          • 在主配置文件的configuration标签中添加settings标签
          <settings>
              <setting name="cacheEnabled" value="true"/>
          </settings>
          
        2. 让当前的映射文件支持二级缓存(在映射配置文件中配置)

          • 在映射配置文件的mapper标签中添加cache标签
          <cache/>
          
        3. 让当前的操作支持二级缓存(在select标签中配置)

          • 在当前操作的标签中添加useCache属性
          <select id="findById" parameterType="INT" resultType="user" useCache="true">
              select * from user where id = #{uid}
          </select>
          
      • 二级缓存中存放的是数据,当SqlSession对象查询数据的时候,会从二级缓存中找数据,然后再根据数据创建对象。

    【源码】一级缓存和二级缓存

3 mybatis中的注解开发

  1. 环境搭建
  2. 单表CRUD操作(代理Dao方式)
  3. 多表查询操作
  4. 缓存的配置
  • 注解开发不需要映射配置文件,只需要主配置文件

  • 此部分观看视频的P68-P75

【源码】mybatis的注解开发–一对一

【源码】mybatis的注解开发–一对多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值