Mybatis/MybatisPlus简述

一.基本概念及原理

官网地址: https://mybatis.org/mybatis-3/zh/index.html
MyBatis 是持久层框架,内部整合了JDBC,以对象的方式操作数据库.
Spring整合mybatis使用的是JDK代理

一.SpringBoot简化Mybatis操作单表

1.导入jar包文件

<!--mybatis依赖包-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!--jdbc依赖包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--添加lombok的包,需要安装lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

2.修改配置文件名称及编辑内容

application.properties改为application.yml
yml文件 0不解析 如果字母以0开头则引号包裹

#1.配置端口号  注意缩进!!!!!
server:
  port: 8090

#2.配置数据源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    #yml文件 0不解析 如果字母以0开头则引号包裹
    #password: "0123456"
    password: root

#3.配置Mybatis
mybatis:
    #定义别名包路径(简化UserMapping.xml文件的resultType的写法)
  type-aliases-package: com.jt.pojo
  #将所有的映射文件全部加载
  mapper-locations: classpath:/mappers/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

#4.打印Sql com.jt.mapper下的Sql日志
logging:
  level:
    com.jt.mapper: debug

3.准备POJO对象:

@Data //lombok需要pom文件添加依赖,安装lombok插件该注解会自动生成很多常用方法
@Accessors(chain = true) //重写了set方法. 可以实现链式加载
@NoArgsConstructer   //无参构造函数
@AllArgsConstructor   //全参数构造函数
implements Serializable对象序列化作用:
        1.保证数据按照正确的格式输出
        2.在多线程条件下,共享数据必须序列化

生成序列号

属性类型必须是引用类型,且私有化

pojo层,修饰Data类型数据

@JsonFormat(pattern=“yyyy年MM月dd日 HH:mm:ss” , timezone=“GMT+8”) 

4.将Mapper接口交给容器管理

  • @Mapper //将接口交给Mybatis管理,Mybatis再将其交给Spring容器管理Map<userMapper,JDK代理对象>,作用告诉编译器这是一个负责映射的接口 (映射指的是实体类和表之间的关系)
  • @MapperScan("包扫描路径")用于主启动类上,使用该注解可以省略重复写@Mapper注解

原则:Mybatis只支持单值传参将多值封装为单值
接收前段参数规则:  单个参数直接传
                 对象的多字段的可以使用对象封装   
                 对象的单字段的两值可以使用集合HashMap
                 
利用注解@Param("id")将数据封装为Map,在xml文件中使用的就是该注解中的该变量名,否则在写xml文件时,需要通过agr0,agr1...param1,param2....来标注sql语句中使用参数中的第几个参数

                 对象的单字段的多值可以使用Arrays / list集合 / map集合封装

mapper层使用参数的规则:
                1. 如果是单个参数,则使用#{key}  获取的参数的值

(如果只传递一个参数,则名称任意!Mybatis单值传参时,与下标有关和名称无关)
                2. 如果是对象参数,则使用#{属性} 获取的是属性值
                3.
如果传递的参数是Map, 则使用#{key}
                4.如果传递的是Arrays / list集合 / map集合,需要遍历再取值 

查询返回值: 单个对象使用对象直接接收  多个对象使用List<对象User> 

@Mapper  //将接口交给Spring容器管理 Map<userMapper,JDK代理对象>
public interface UserMapper {

    //根据ID查询数据库
    User findUserById(int id);
    
    List<User> findUserByNA(User user);
    
    //注解:@Param("key") int minAge(值)
    // 作用:将数据封装为Map
    List<User> findUserByAge2(@Param("minAge") int minAge, 
                              @Param("maxAge") int maxAge);

   	List<User> findListByIn(int[] array);

}

关于抽象方法:

  • 必须定义在某个接口中,这样的接口通常使用Mapper作为名称的后缀,例如AdminMapper
    • Mybatis框架底层将通过接口代理模式来实现
  • 方法的返回值类型:如果要执行的数据操作是增、删、改类型的,统一使用int作为返回值类型,表示“受影响的行数”,也可以使用void,但是不推荐;如果要执行的是查询操作,返回值类型只需要能够装载所需的数据即可
  • 方法的名称:自定义,不要重载,建议风格如下:
    • 插入数据使用insert作为方法名称中的前缀或关键字
    • 删除数据使用delete作为方法名称中的前缀或关键字
    • 更新数据使用update作为方法名称中的前缀或关键字
    • 查询数据时:
      • 如果是统计,使用count作为方法名称中的前缀或关键字
      • 如果是单个数据,使用getfind作为方法名称中的前缀或关键字
      • 如果是列表,使用list作为方法名称中的前缀或关键字
    • 如果操作数据时有条件,可在以上前缀或关键字右侧添加by字段名,例如deleteById
  • 方法的参数列表:取决于需要执行的SQL语句中有哪些参数,如果有多个参数,可将这些参数封装到同一个类型中,使用封装的类型作为方法的参数类型 

5.编辑UserMapper.xml映射文件

由于mybatis需要操作数据库.编辑Sql语句. 采用xml映射文件维护Sql语句.
在resource的目录中添加mappers文件创建UserMapper.xml
模糊查询 特别注意表名的大小写问题!!!
        windows系统中: 不区分大小写                         

        Linux系统中: 区分大小写问题

别名包:
                在配置文件中指定包路径: 可以自动的实现包路径的拼接
         resultType规则:
               1. 首先根据别名包匹配.设定..
               2. 如果匹配不成功,则按照路径匹配.


xml转译字符:         > &gt;           < &lt;         & &amp;   
                        万能转义:<![CDATA [ select * from user ...] ]>
注意: 新增,删除,修改没有返回值resultType


关于取值操作的说明: #{属性值},${属性值}
        1.#号取值采用占位符的方式  更加安全 防止sql注入攻击!!!
        2.$符一般的使用场景 以字段为参数时使用.
        3.使用#号时,默认会添加一对" "号

<?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">

<!-- 根节点的namespace属性用于配置此XML对应哪个接口 -->
<mapper namespace="com.baidu.mybatis.mapper.AdminMapper">

    <!-- 配置SQL的节点的id属性取值为抽象方法名称 -->
    <!-- SQL语句中的参数值使用 #{} 格式的占位符表示 -->
    <!-- 当配置完成后,Mybatis执行此插入数据的操作后,会将自动编号的id赋值到参数Admin admin
的id属性中,以上keyProperty指的就是将自动编号的值放回到参数对象的哪个属性中!-->
    <insert id="insert" useGeneratedKeys="true"  keyProperty="id">
        insert into ams_admin (
            username, password, nickname, avatar, 
            phone, email, description, is_enable, 
            last_login_ip, login_count, gmt_last_login, gmt_create, 
            gmt_modified
        ) values (
            #{username}, #{password}, #{nickname}, #{avatar}, 
            #{phone}, #{email}, #{description}, #{isEnable}, 
            #{lastLoginIp}, #{loginCount}, #{gmtLastLogin}, #{gmtCreate}, 
            #{gmtModified}
        )
    </insert>

    <update id="updateUserById">
        update demo_user set name=#{name}
        where id = #{id}
    </update>

</mapper>
<?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">

<!--namespace是mybaits映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.UserMapper">

   <!-- 语法:
            1.取值操作 #{属性名称}
            2.只有查询需要写resultType
            3.如果是"更新"操作可以自动返回影响的行数 -->

    <!--resultType 返回值结果类型,返回的P0J0对象类型全路径将结果集自动的封装为对象 -->
    <!-- 所有select节点必须配置resultType或resultMap这2个属性中的其中1个 -->
    <select id="findUserById" resultType="com.jt.pojo.User">
        select * from demo_user where id = #{id}
    </select>

    <!-- 如果查询结果集中的列名与类的属性名不匹配时,默认将放弃处理这些结果数据,则返回的对象中对
应的属性值为null,为了解决此问题,可以在查询时使用自定义的别名,使得名称保持一致,不过,更推荐配
置<resultMap>以指导Mybatis封装查询结果-->
    <select id="getById" resultMap="BaseResultMap">
    select * from ams_admin where id=#{id}
    </select>
    <!-- resultMap节点的作用是:指导Mybatis如何将结果集中的数据封装到返回的对象中 -->
    <!-- id属性:自定义名称 -->
    <!-- type属性:将结果集封装到哪种类型的对象中 -->
    <resultMap id="BaseResultMap" type="cn.tedu.mybatis.Admin">
        <!-- 使用若干个result节点配置名称不统一的对应关系 -->
        <!-- 在不是“一对多”的查询时,名称本来就一致的是不需要配置的 -->
        <!-- column属性:列名 -->
        <!-- property属性:属性名 -->
        <result column="is_enable" property="isEnable" />
        <result column="last_login_ip" property="lastLoginIp" />
        <result column="login_count" property="loginCount" />
        <result column="gmt_last_login" property="gmtLastLogin" />
        <result column="gmt_create" property="gmtCreate" />
        <result column="gmt_modified" property="gmtModified" />
    </resultMap>

    <select id="findUserByAge" resultType="User">
        <![CDATA[
             select * from demo_user
                where age  > #{minAge} and   age  < #{maxAge}
           ]]>
    </select>

    <!--模糊查询注意拼接"%"#{name}"%"-->
    <select id="findUserByLike" resultType="User">
        SELECT * FROM demo_user WHERE NAME LIKE "%"#{name}"%"
    </select>
 
</mapper>

①动态Sql

  动态SQL -- foreach

  • <foreach>标签:用于遍历集合或数组类型的参数对象
  • collection属性:被遍历的参数对象,当抽象方法的参数只有1个且没有添加@Param注解时,如果参数是List类型则此属性值为list,如果参数是数组类型(包括可变参数)则此属性值为array;当抽象方法的参数有多个或添加了@Param注解时,则此属性值为@Param注解中配置的值
  • item属性:自定义的名称,表示遍历过程中每个元素的变量名,可在<foreach>子级使用#{变量名}表示数据
  • separator属性:分隔符号,会自动添加在遍历到的各元素之间
<!--
        关于Mybatis的遍历的写法
        foreach:
            1. collection 需要遍历的集合
                   1.1 数组      关键字: array/list
                   1.2 list集合  关键字: list/array
                   1.3 Map<key,array/list>  关键字:key
            2. open/close  循环体的开始和结束 可以写到循环之外简化标签
            3. item  当前遍历数据的变量名
            4. separator 分割符
    -->
<!-- int deleteByIds(List<Long> ids); -->
<delete id="deleteByIds">
    delete from ams_admin where id in (
    	<foreach collection="list" item="id" separator=",">
          #{id}
    	</foreach>
    )
</delete>

动态Sql if-where条件:
        动态Sql: 根据对象中不为null的属性当作where条件
        语法:
               1.如果判断成立,则动态拼接条件
               <if test="id !=null ">条件</if>
               2.where标签  去除where后边多余的一个and/or
动态Sql-set条件:
根据对象中不为null的元素,充当set条件. where id=xxx
动态Sql-choose、when、otherwise

如果不想使用所有的条件可以使用choose 类似于java中的if-elseif-elseif...else 语法:

<?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.jt.mapper.UserMapper2">
    <!--根据对象中不为null的属性当作where条件-->
    <select id="findUserList" resultType="User">
        select * from demo_user
        <where>
            <if test="id !=null ">id = #{id}</if>
            <if test="name !=null">and name = #{name}</if>
            <if test="age !=null ">and age = #{age}</if>
            <if test="sex !=null ">and sex = #{sex}</if>
        </where>
    </select>

    <!--根据对象中不为null的元素,充当set条件. where id=xxx-->
    <update>
        update demo_user
            <set>
                <if test="name !=null">name = #{name},</if>
                <if test="age !=null">age = #{age},</if>
                <if test="sex !=null">sex = #{sex}</if>
            </set>
            where id = #{id}
    </update>
    <!--如果不想使用所有的条件可以使用choose 类似于java中的if-else -->
     <select id="findUserByNS" resultType="User">
        select * from demo_user  where
                <choose>
                    <when test="name !=null">name = #{name}</when> 
                    <when test="age !=null">age = #{age}</when>
                    <otherwise>sex = #{sex}</otherwise>
                </choose>
    </select>
</mapper>

 ②Sql标签用法

说明: Sql语句中经常出现重复的数据.如果每次重复的内容都自己手写.则开发的效率低.

 <!--
        语法:  "%"     这样的方式
    -->
    <select id="findUserByLike" resultType="User">
        SELECT <include refid="tableColumn"/> FROM demo_user WHERE NAME LIKE "%"#{name}"%"
    </select>

    <!--Sql标签: 抽取公共的Sql语句 -->
    <sql id="tableColumn">
        id,name,age,sex
    </sql>

③resultMap

说明: 在业务中经常出现该现象. 字段 user_id 属性:userId 属性和字段有驼峰映射规则.但是采用resultType的方式进行映射.则不能正常赋值.

解决方案:
1.resultMap 繁琐.
2.在配置文件中开启驼峰映射规则

当表中的字段与POJO中的属性名称不一致时,需要使用resultMap的方式进行映射.

        1.resultType : 单表查询&结果集字段与属性一致

        2.resultMap: 可以支持 任意类型的映射 万能的结构

 编辑Mapper 映射文件

<?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.jt.mapper.DogMapper">

    <select id="findAll" resultMap="dogRM">
        select * from dog
    </select>

    <resultMap id="dogRM" type="Dog">
        <!--ID:代表主键-->
        <id column="dog_id" property="dogId"/>
        <!--结果集-->
        <result column="dog_name" property="dogName"/>
        <!--<result column="age" property="age"/>-->
    </resultMap>
</mapper>

开启驼峰映射规则

mybatis:
  #定义别名包
  type-aliases-package: com.jt.pojo
  #将所有的映射文件全部加载
  mapper-locations: classpath:/mappers/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

二.数据封装--Mybatis操作多表

常见关联关系:

        1.一对一     一个员工对应一个部门

        2.一对多     在多的表中添加

        3.多对多     需要中间表进行关联

1.一对一数据封装

创建POJO对象

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Emp implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    //关联关系: 一个员工对应一个部门
    private Dept dept;
    //private Integer deptId;
}

 编辑Mapper 映射文件

<?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.jt.mapper.EmpMapper">

    <!--
        规则:
            1.使用关联查询时,不能出现同名字段,否则映射报错
    -->
    <select id="findEmp" resultMap="empRM">
        select emp.*,dept.dept_name
        from emp,dept
        where emp.dept_id = dept.dept_id
    </select>

    <!--
        知识点:
            1.autoMapping="true"
            如果字段名称和属性名称一致,则自动映射
            2.association 一对一对象
            3.javaType    固定搭配 封装对象的类型
            总结:Mybatis可以实现关联查询的数据封装.
                可以为主对象封装数据/同时可以为引用封装数据
    -->
    <resultMap id="empRM" type="Emp" autoMapping="true">
        <!--1.标识主键-->
        <id column="id" property="id"/>

        <!--2.一对一封装 Dept对象-->
        <association property="dept" javaType="Dept" autoMapping="true">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"/>
        </association>
    </resultMap>
</mapper>

2. 一对多数据封装

创建POJO对象

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
    private Integer deptId;
    private String deptName;
    //关联 一个部门下有多个员工
    private List<Emp> emps;
}

 编辑Mapper 映射文件

<?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.jt.mapper.DeptMapper">
    
    <select id="findAll" resultMap="deptRM">
        SELECT dept.dept_name,emp.*
	    FROM dept,emp
	    WHERE emp.dept_id = dept.dept_id
    </select>
    <resultMap id="deptRM" type="Dept" autoMapping="true">
        <!--主键必须标识-->
        <id column="dept_id" property="deptId"/>
        <!-- 一对多封装 固定搭配 ofType="" 
                                columnPrefix="" 定义结果集前缀便于映射-->
        <collection property="emps" ofType="Emp" autoMapping="true" columnPrefix="c_">
            <id column="id" property="id"></id>
        </collection>
    </resultMap>
</mapper>

 三.Mybatis注解开发

@Insert("SQL语句")  @Update("SQL语句")  @Delete("SQL语句")   @Select("SQL语句")
利用注解可以根据返回值类型,自动映射
        规则1: 注解和映射文件 二选一 映射文件为主导.
        规则2: 注解写法一般适用于简单操作.关联查询不适用

@Transactional   // 业务层需要对增删改操作进行事物的控制
                           如果程序运行出现运行时异常,则实现事务回滚

//该Mapper主要测试注解开发
@Mapper
public interface UserAnnoMapper {
   
    @Select("select * from demo_user")
    List<User> findAll();

    @Select("select * from demo_user where id=#{id}")
    //@Insert()
    //@Update()
    //@Delete()
    User findUserById(int id);

    //#{变量} 会自动查找方法参数列表中的同名变量,如果没有同名变量
    //会查找自定义对象类型里面的同名属性并调用get变量的方法
    @Insert("insert into myemp values(null,#{name},#{sal},#{job})")
    void insert(Emp emp);
}

四.Mybatis缓存

在这里插入图片描述一级缓存: 在同一个sqlSession内实现数据的共享

1.Mybatis 默认条件下一级缓存默认开启的.
2.执行重复操作时,Mybatis一级缓存生效,查询一次数据库.
3.如果查询期间执行更新操作,则一级缓存清空.保证数据都是新的
springBoot整合mybatis之后,使用Mapper.find查询时.springBoot默认会开启多个sqlSession,可以通过添加事务注解@Transactional,springBoot中如果添加了事务注解,则默认采用同一个SqlSessio

二级缓存:由同一个sqlSessionFactory,生产的SqlSession 数据共享. 默认开启 + 配置

1. 二级缓存默认开启.
2. 二级缓存需要标记. cache标签且关闭SqlSession

3. 多线程条件下如果需要实现数据共享,则要求数据必须序列化! 
要求Pojo必须序列化,配置:方案①Mapper层使用@CacheNamespace注解
                                          方案②映射文件中加<cache/>

五.常见异常:

1.未配置application.yml

由于Mybatis依赖了JDBC的jar包. 但是该jar包文件是启动项. 当主启动类运行时,开始加载主启动项. 但是JDBC需要链接数据库.所以必须有相关的配置信息.但是此时YML文件中没有数据源的配置.所以报错.配置application.yml文件中的数据源连接信息即可在这里插入图片描述

2.数据映射问题

现象及解决说明:
表中的字段名称与对象中的属性名称不一致. 结果:数据不能映射.

在这里插入图片描述
3.结果为[ ]

如果查询的结果为[ ],数据表中有数据,则有可能是:
1.动态Sql-choose、when、otherwise中,otherwise的条件为空
2.查询条件拼接错误,导致查询条件为空,数据表中该查询字段的值又没有null值,即使有null值,查询的结果跟预期也有差异.可以查看后台打印的sql语句拼接情况,再做修改.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值