美文网首页
Mybatis复习

Mybatis复习

作者: Zerek_W | 来源:发表于2021-12-07 11:58 被阅读0次

    一、Mybatis简介


    什么是Mybatis

    MyBatis 是一款优秀的持久层框架
    MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程
    MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息
    MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping) -->对象关系映射

    Mybatis环境搭建

    1.搭建数据库
    2.引入Maven依赖
    3.编写Mybatis核心配置文件

    <?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>
       <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?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                   <property name="username" value="root"/>
                   <property name="password" value="123456"/>
               </dataSource>
           </environment>
       </environments>
       <mappers>
           <mapper resource="com/kuang/dao/userMapper.xml"/>
       </mappers>
    </configuration>
    

    4.编写Mybatis工具类XML

    public class MybatisUtils {
    
       private static SqlSessionFactory sqlSessionFactory;
    
       static {
           try {
               String resource = "mybatis-config.xml";
               InputStream inputStream = Resources.getResourceAsStream(resource);
               sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
          } catch (IOException e) {
               e.printStackTrace();
          }
      }
    
       //获取SqlSession连接
       public static SqlSession getSession(){
           return sqlSessionFactory.openSession();
      }
    
    }
    

    5.创建实体类
    6.编写Mapper接口
    7.编写Mapper.xml

    二、CRUD操作


    1、在接口方法的参数前加 @Param属性

    2、Sql语句编写的时候,直接取@Param中设置的值即可,不需要单独设置参数类型
    session.commit(); //提交事务
    所有的增删改操作都需要提交事务!
    接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!
    有时候根据业务的需求,可以考虑使用map传递参数!
    为了规范操作,在SQL的配置文件中,我们尽量将Parameter参数和resultType都写上!

    三、配置解析


    核心配置文件

    mybatis-config.xml 系统核心配置文件
    MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。
    能配置的内容如下:

    configuration(配置)
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境配置)
    environment(环境变量)
    transactionManager(事务管理器)
    dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)
    <!-- 注意元素节点的顺序!顺序不对会报错 -->
    

    environment元素

    配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定)
    子元素节点:environment

    Mappers元素

    映射器 : 定义映射SQL语句文件

    Properties优化

    可以在configuration中
    //导入properties文件
    <properties resource="db.properties"/>

    typeAliases优化

    <typeAliases>
       <typeAlias type="com.kuang.pojo.User" alias="User"/>
    </typeAliases>
    

    设置Settings

    懒加载
    日志实现
    缓存开启关闭
    下划线转驼峰命名

    四、ResultMap


    解决属性名和字段名不一致问题

    <resultMap id="UserMap" type="User">
       <result column="pwd" property="password"/>
    </resultMap>
    
    <select id="selectUserById" resultMap="UserMap">
      select id , name , pwd from user where id = #{id}
    </select>
    

    五、分页的几种方式


    1、设置日志

    <settings>
           <setting name="logImpl" value="STDOUT_LOGGING(or LOG4J)"/>
    </settings>
    

    2、limit实现分页

    <select id="selectUser" parameterType="map" resultType="user">
      select * from user limit #{startIndex},#{pageSize}
    </select>
    

    3、RowBounds分页

    4、PageHelper

    六、使用注解开发


    1、面向接口编程

    在真正的开发中,很多时候我们会选择面向接口编程
    根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大家都遵守共同的标准 , 使得开发变得容易 , 规范性更好

    2、利用注解开发

    @select ()
    @update ()
    @Insert ()
    @delete ()
    注意:利用注解开发就不需要mapper.xml映射文件了

    @Select("select id,name,pwd password from user")
    public List<User> getAllUser();
    

    本质上利用了jvm的动态代理机制

    3、@Param

    @Param注解用于给方法参数起一个名字。以下是总结的使用原则:

    在方法只接受一个参数的情况下,可以不使用@Param。
    在方法接受多个参数的情况下,建议一定要使用@Param注解给参数命名。
    如果参数是 JavaBean , 则不能使用@Param。
    不使用@Param注解时,参数只能有一个,并且是Javabean。

    4、#与$的区别

    #{} 的作用主要是替换预编译语句(PrepareStatement)中的占位符
    ${} 的作用是直接进行字符串替换

    7、多对一的处理


    多对一的理解:

    多个学生对应一个老师
    如果对于学生这边,就是一个多对一的现象,即从学生这边关联一个老师!

    1、按查询嵌套处理

     <select id="getStudents" resultMap="StudentTeacher">
        select * from student
       </select>
       <resultMap id="StudentTeacher" type="Student">
           <!--association关联属性 property属性名 javaType属性类型 column在多的一方的表中的列名-->
           <association property="teacher"  column="tid" javaType="Teacher" select="getTeacher"/>
       </resultMap>
       <!--
       这里传递过来的id,只有一个属性的时候,下面可以写任何值
       association中column多参数配置:
           column="{key=value,key=value}"
           其实就是键值对的形式,key是传给下个sql的取值名称,value是片段一中sql查询的字段名。
       -->
       <select id="getTeacher" resultType="teacher">
          select * from teacher where id = #{id}
       </select>
    

    2、按结果嵌套处理

    <select id="getStudents2" resultMap="StudentTeacher2" >
      select s.id sid, s.name sname , t.name tname
      from student s,teacher t
      where s.tid = t.id
    </select>
    
    <resultMap id="StudentTeacher2" type="Student">
       <id property="id" column="sid"/>
       <result property="name" column="sname"/>
       <!--关联对象property 关联对象在Student实体类中的属性-->
       <association property="teacher" javaType="Teacher">
           <result property="name" column="tname"/>
       </association>
    </resultMap>
    

    八、一对多的处理


    1、按查询嵌套处理

    <select id="getTeacher2" resultMap="TeacherStudent2">
    select * from teacher where id = #{id}
    </select>
    <resultMap id="TeacherStudent2" type="Teacher">
       <!--column是一对多的外键 , 写的是一的主键的列名-->
       <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="getStudentByTeacherId"/>
    </resultMap>
    <select id="getStudentByTeacherId" resultType="Student">
      select * from student where tid = #{id}
    </select>
    

    2、按结果嵌套处理

    <select id="getTeacher" resultMap="TeacherStudent">
          select s.id sid, s.name sname , t.name tname, t.id tid
          from student s,teacher t
          where s.tid = t.id and t.id=#{id}
       </select>
    
       <resultMap id="TeacherStudent" type="Teacher">
           <result  property="name" column="tname"/>
           <collection property="students" ofType="Student">
               <result property="id" column="sid" />
               <result property="name" column="sname" />
               <result property="tid" column="tid" />
           </collection>
       </resultMap>
    

    1、关联-association

    2、集合-collection

    3、所以association是用于一对一和多对一,而collection是用于一对多的关系

    4、JavaType和ofType都是用来指定对象类型的

    JavaType是用来指定pojo中属性的类型
    ofType指定的是映射到list集合属性中pojo的类型。

    九、动态SQL


    动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句.

    • if
    • choose (when, otherwise)
    • trim (where, set)
    • foreach

    if

      select * from blog where
       <if test="title != null">
          title = #{title}
       </if>
       <if test="author != null">
          and author = #{author}
       </if>
    </select>
    

    where

    这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

    <select id="queryBlogIf" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <if test="title != null">
              title = #{title}
           </if>
           <if test="author != null">
              and author = #{author}
           </if>
       </where>
    </select>
    

    Set

    同理,上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词,我们怎么处理呢?

    <update id="updateBlog" parameterType="map">
      update blog
         <set>
             <if test="title != null">
                title = #{title},
             </if>
             <if test="author != null">
                author = #{author}
             </if>
         </set>
      where id = #{id};
    </update>
    

    choose

    有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

    <select id="queryBlogChoose" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <choose>
               <when test="title != null">
                    title = #{title}
               </when>
               <when test="author != null">
                  and author = #{author}
               </when>
               <otherwise>
                  and views = #{views}
               </otherwise>
           </choose>
       </where>
    </select>
    

    SQL片段

    有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
    提取SQL片段

    <sql id="if-title-author">
       <if test="title != null">
          title = #{title}
       </if>
       <if test="author != null">
          and author = #{author}
       </if>
    </sql>
    

    引用SQL片段

    <select id="queryBlogIf" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
           <include refid="if-title-author"></include>
           <!-- 在这里还可以引用其他的 sql 片段 -->
       </where>
    </select>
    

    Foreach

    需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息

    <select id="queryBlogForeach" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <!--
           collection:指定输入对象中的集合属性
           item:每次遍历生成的对象
           open:开始遍历时的拼接字符串
           close:结束时拼接的字符串
           separator:遍历对象之间需要拼接的字符串
           select * from blog where 1=1 and (id=1 or id=2 or id=3)
         -->
           <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
              id=#{id}
           </foreach>
       </where>
    </select>
    

    十、缓存


    1、什么是缓存 [ Cache ]?

    存在内存中的临时数据。
    将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
    2、为什么使用缓存?

    减少和数据库的交互次数,减少系统开销,提高系统效率。
    3、什么样的数据能使用缓存?

    经常查询并且不经常改变的数据。

    Mybatis缓存

    MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存

    默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
    二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
    为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

    一级缓存失效的4种情况:

    1、sqlSession不同
    2、sqlSession相同,查询条件不同
    3、sqlSession相同,两次查询之间执行了增删改操作!
    4、sqlSession相同,手动清除一级缓存
    session.clearCache();//手动清除缓存

    二级缓存

    二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存

    基于namespace级别的缓存,一个名称空间,对应一个二级缓存;

    工作机制

    一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
    如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
    新的会话查询信息,就可以从二级缓存中获取内容;
    不同的mapper查出的数据会放在自己对应的缓存(map)中;

    使用步骤

    1、开启全局缓存 【mybatis-config.xml】

    <setting name="cacheEnabled" value="true"/>
    2、去每个mapper.xml中配置使用二级缓存
    <cache/>

    只要开启了二级缓存,我们在同一个Mapper中的查询,可以在二级缓存中拿到数据
    查出的数据都会被默认先放在一级缓存中
    只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中

    EhCache

    Ehcache是一种广泛使用的java分布式缓存,用于通用缓存;

    要在应用程序中使用Ehcache,需要引入依赖的jar包

    相关文章

      网友评论

          本文标题:Mybatis复习

          本文链接:https://www.haomeiwen.com/subject/guioxrtx.html