mybatis的知识点总结

0 阅读5分钟

Mybatis 是一个对数据库进行操作的 ORM 框架,主要是封装提供灵活的增删改查sql,开发中,service层能够通过mybatis组件查询和修改数据库中表的数据;作为查询工具,mybatis有使用缓存,当我们从数据库中查询过的数据,会存入缓存,当我们进行二次查询时,就不需要重新链接数据库进行二次查询,缓存的生命周期创建的会话。

什么是ORM框架

  1. 首先ORM是对象关系映射,作用是实现java对象和数据库表的自动转换,屏蔽原生SQL,用面向对象的方式操作数据库。
  2. 核心映射关系
  • 实体类(emp)<->数据库表
  • 类的成员属性<->表的字段(列)
  • 类的对象实例<->表的一行数据
  1. 核心思想
  • 不用大量手写sql,通过操作对象,由框架自动生成,执行sql,完成增删改查。

Mybatis的环境搭建

  1. 导入maven依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.19</version>
</dependency>

  1. 编写实体类(实体类的属性名要和数据库的字段名对应)
  2. 编写Mapper接口,例如
@Select("select * from emp where empno=#{id}")
emp findAll(int id);

  1. 编写Mybatis核心配置文件(config.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>
    <settings>
        <!--输出日志到控制台中-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--分别书写驱动类、网址、账号和密码 注意网址中&使用&amp;代替-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/book_21"/>
                <property name="username" value="root"/>
                <property name="password" value="LQYOW2580"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--引入的资源文件-->
        <package name="org.example.mybatis.m5.mapper"/>

    </mappers>
</configuration>

5.编写Mapper Xml映射文件


<?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="org.example.mybatis.m1.mapper.informationMapper">//这个是你当前映射文件的路径

<!--
代表一个查询方法
 id:方法名(必须和Mapper接口全类名完全一致)
 resultType:返回类型路径
 parameterType:参数类型,没有就删掉
-->
<select id="findAll" resultType="org.example.mybatis.m1.bean.information">
<!--这里是Sql-->
    select * from information
</select>


利用注解的方式

  1. 依赖,实体类,配置文件这些和XML完全一样,不用改,只有一处要改,config.xml的,改成扫包注册接口:
<package name="org.example.mybatis.m2.mapper"/>

2。注解版Mapper接口,举个全查询例子

@Select("select * from emp")//注解
List<emp> findAll();

3.最常考,最常用的一个:主键回填,新增时想插入后自动把数据库生成id赋给java对象

  @Options(useGeneratedKeys=ture,keyProperty="id")  
    直接加在@insert下面就行
  1. 测试类,直接复制粘贴
    
//加载配置文件
InputStream resourceAsStream = Main.class.getClassLoader().getResourceAsStream("config.xml");
//创建会话工厂
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
//创建会话
SqlSession sqlSession = build.openSession();
// 获取到对象
empMapper mapper = sqlSession.getMapper(empMapper.class);

mybatis的参数问题

在mybatis中,接口传递参数到xml或者注解的形式,主要分为单参数,多参数,特殊参数(Map)三种情况

1.单参数
  • mybatis对单参数没有限制,直接通过#{}或${}(这个时拼接具体区别请看别的文章)
//单个参数问题
@Select("select * from emp where empno=#{id}")//#{}输出对应占位符
emp findEmpById(int id);
@Select("select * from emp where empno=${id}")//${}直接把参数拼接上去
emp findEmpById1(int id);
//单个参数时,名称可以不对应
@Select("select * from emp where empno=#{abc}")
emp findEmpById2(int id);   
2多参数问题.
  • 当方法传入多个参数的时候,mybatis会自动进行封装,不能注解使用参数名,必须使用指定别名
    
  • 解决方案:使用@Param注解--这是最优雅的方式,通过注解给参数起别名
@Select("select * from emp where ename like #{name} and job=#{job}")
List<emp> findEmp3(@Param("name") String name, @Param("job") String job);

  1. 数据库表中的列和对象的属性名不一致时
  2. 方案1:给数据库字段起个别名,让其和java属性相等
@Select("select e.*,job as 'job1'from emp e where empno=#{id}")
emp find1(int id);

3方案二. //解决方案2--让数据库名等于Java名

    
@Select("select * from emp where empno=#{id}")
    ```
@Results(
        @Result(column = "job",property = "job1")
)
emp find2(int id);
映射
  • 映射是指将数据库查询的结果集转换成java对象的过程
  1. 自动映射
  • 前提条件:数据库字段名和java实体类属性名一致
  • 使用场景:简单的单表查询,字段名差异不大

2.手动映射

  • 当字段名与属性完全不一致,或者需要多表查询,例多表查询:
@Select("select * from emp where empno=#{empno}")
  @Results(
          /*
          column:将数据库查出来的列赋给property
          propery:代表bean包中的某一个属性
           */
          value = {
                  @Result(column = "empno", property = "empNo", id = true),
                  //非主键
                  @Result(column = "ename", property = "ename", javaType = String.class),
                  @Result(column = "deptno",
                  property = "dept",javaType = dept.class,
                          one = @One(select = "org.example.mybatis.m3.mapper.DeptMapper.findDeptById")
                  )
          }
  )
emp findEmpById(int empno);

  • 在另一个类中写查找dept的方法

@Select("select * from dept where deptno=#{deptNo}")
dept findDeptById(int deptNo)

   

这就是多表查询,多对一的例子,一对多同理,将One改成Many

mysql动态sql--用xml方便,利用注解很麻烦

  • 动态sql核心作用是根据不同条件动态生成不同的sql语句
  • 核心标签详解:
  1. <if 标签:条件判断--这里id必须和接口中方法名一致
 <select id="find1" resultType="org.example.mybatis.m4.bean.emp">
    select * from emp
    <if test="ename!=null">
        where ename like #{ename}
    </if>
</select>

2.类似if-else标签《choose>《when>《otherwise>

   
<choose>
    <when test="sal>3000">
        where job='程序员'
    </when>
    <when test="sal>6000">
        where job='网页设计'
    </when>
    <otherwise>
        where job='歌手'
    </otherwise>
</choose>

3.《where>标签:自动处理where子句:

  
select * from emp
    <where>
        <if test="job!=null">
            job=#{job}
        </if>
        <if test="sal!=null">
            and sal>#{sal}
        </if>
    </where>
    <!--第二种方式-->
    <trim prefix="where" suffixOverrides="and|or">
        <if test="job!=null">
            job=#{job}
        </if>
        <if test="sal!=null">
            and sal>#{sal}
        </if>
    </trim>

</select>

4.《foreach>标签:遍历集合

   
//集合必须加Pararm,起名字,或者用默认名”collection“
List<emp> find5( @Param("job") List<String> job);

select * from emp
    <where>
        <if test="job!=null">
            job in
            <!--
           for(String ab:job)
            -->
            <foreach collection=" job" open="(" close=")" separator="," item="ab">
                #{ab}
            </foreach>
        </if>
    </where>
</select>

5.《set>标签,动态更新

 update emp
    <set>
        <if test="ename!=null">
            ename=#{ename},
        </if>

        <if test="job!=null">
            job=#{job},
        </if>

        <if test="mgr!=null">
            mgr=#{mgr},
        </if>
    </set>
    where empno=#{empNo}
</update>

5.《bind> 模糊查询

<bind name="abc" value="'%' + _parameter.getEname() + '%'"/>
select *
from emp
where ename like #{abc}

缓存问题

  • 缓存是将频繁查询,不常修改的数据存储到数据存储在内存的技术 第一次查询:从数据库中查询数据,存入缓存
  • 后续查询相同内容,直接从缓存中取数据,无需访问数据库

1.一级缓存(sqlsession级别,默认开启)

  • 作用域也可以说缓存的生命周期:同一个sqlSession内有效,sqlsession关闭后清空
缓存失效场景:

1.执行insert,delete,update操作(会清空当前sqlsession的一级缓存)
2.手动调用sqlsession.clearCache()清空缓存 3.不同sqlsession之间不共享

    // 同一个SqlSession,两次查询,第二次命中一级缓存
try (SqlSession sqlSession = MyBatisUtils.getSqlSession(true)) {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user1 = mapper.selectUserById(1); // 第一次:查数据库
    User user2 = mapper.selectUserById(1); // 第二次:命中缓存,不查数据库
    System.out.println(user1 == user2); // true(同一个对象)
}

二级缓存

-作用域:全局共享

-默认关闭,要手动开启

  • 开启缓存的步骤在config.xml中配置
 <!--开启全局二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>