MyBatis基础知识总结

目录

1.MyBatis是什么?

2.为什么学习MyBatis?

3.MyBatis的第一个程序

   3.1MyBatis框架定位

   3.2创建数据库和表

   3.3添加MyBatis框架支持

   3.4配置连接字符串和MyBatis

   3.5添加相关代码

4.实现增,删,改,操作

5.查询操作

   5.1Select

   5.2模糊查询?

   5.3多表查询

6.动态sql使用

   6.1 <if>标签

   6.2 <trim>标签

   6.3 <where>标签

   6.4 <set>标签

   6.5 <foreach>标签


1.MyBatis是什么?

 

  • Mybatis是一款优秀的持久层框架
  • 它支持定制化SQL、存储过程以及高级映射。
  • Mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。
  • Mybatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的POJO(Plain Old Java Object,普通老式Java对象)为数据库中的记录。
  • Mybatis本是Apache的一个开源项目Ibatis,2010年这个项目由Apache software foundation迁移到了Google Code,并改名为Mybatis。

​​​​​​​2.为什么学习MyBatis?

对于后端开发来说,程序是由以下两个重要的部分组成的: 1. 后端程序 2. 数据库

而这两个重要的组成部分要通讯,就要依靠数据库连接工具,那数据库连接工具有哪些?比如之前我们学习的 JDBC,还有今天我们将要介绍 的 MyBatis,那已经有了 JDBC 了,为什么还要学习 MyBatis? 这是因为 JDBC 的操作太繁琐了

  • Mybatis就是帮助程序猿将数据存入数据库中 , 和从数据库中取数据 .
  • 传统的jdbc操作 , 有很多重复代码块 .比如 : 数据取出时的封装 , 数据库的建立连接等等… , 通过框架可以减少重复代码,提高开发效率 .
  • MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping) —>对象关系映射
  • 所有的事情,不用Mybatis依旧可以做到,只是用了它,所有实现会更加简单!技术没有高低之分,只有使用这个技术的人有高低之别
  • MyBatis的优点
    • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件就可以了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
    • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
    • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
    • 提供xml标签,支持编写动态sql。

3.MyBatis的第一个程序 

3.1MyBatis框架定位

开始搭建 MyBatis 之前,我们先来看一下 MyBatis 在整个框架中的定位,框架交互流程图:

MyBatis 也是一个 ORM 框架,ORM(Object Relational Mapping),即对象关系映射。在面向对象编程语言中,将关系型数据库中的数据 与对象建立起映射关系,进而自动的完成数据与对象的互相转换:

1. 将输入数据(即传入对象)+SQL 映射成原生 SQL

2. 将结果集映射为返回对象,即输出对象 ORM 把数据库映射为对象: 数据库表(table)--> 类(class) 记录(record,行数据)--> 对象(object) 字段(field) --> 对象的属性(attribute)

一般的 ORM 框架,会将数据库模型的每张表都映射为一个 Java 类。 也就是说使用 MyBatis 可以像操作对象一样来操作数据库中的表,可以实现对象和数据库表之间的转换,接下来我们来创建 MyBatis 的第一个实例吧。 

3.2创建数据库和表

 接下来我们要实现的功能是:使用 MyBatis 的方式来读取文章表中的所有用户,我们使用个人博客的数据库和数据包,具体 SQL 如下。

drop database if exists java23;
create database java23 DEFAULT CHARACTER SET utf8;
-- 使用数据数据
use java23;
-- 创建表[用户表]
drop table if exists userinfo;
create table userinfo(
                         id int primary key auto_increment,
                         username varchar(100) not null,
                         password varchar(32) not null,
                         photo varchar(500) default '',
                         createtime datetime default now(),
                         updatetime datetime,
                         `state` int default 1
);
-- 创建文章表
drop table if exists articleinfo;
create table articleinfo(
                            id int primary key auto_increment,
                            title varchar(100) not null,
                            content text not null,
                            createtime datetime default now(),
                            updatetime datetime ,
                            uid int not null,
                            rcount int not null default 1,
                            `state` int default 1
);
drop table if exists videoinfo;
create table videoinfo(
                          vid int primary key,
                          `title` varchar(250),
                          `url` varchar(1000),
                          createtime datetime default now(),
                          updatetime datetime ,
                          uid int
);
-- 添加一个用户信息
INSERT INTO `java23`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`,
                                   `state`) VALUES
    (1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);
-- 文章添加测试数据
insert into articleinfo(title,content,uid) values('Java','Java正文',1);
insert into articleinfo(title,content,uid) values('C++','C++正文',1);
insert into articleinfo(title,content,uid) values('#C','#C正文',1);
-- 添加视频
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);

 3.3添加MyBatis框架支持

添加 MyBatis 框架支持分为两种情况:一种情况是对自己之前的 Spring 项目进行升级,另一种情况是创建一个全新的 MyBatis 和 Spring Boot 的项目,下面我们分别来演示这两种情况的具体实现。

如果是在老项目中新增功能,添加框架支持:

<!-- 添加 MyBatis 框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- 添加 MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

在老项目中还存在一种方法:操作方式是使用EditStarters插件 

 

搜索“MyBatis”添加即可: 

 

 新项目添加MyBatis

选好依赖即可

 3.4配置连接字符串和MyBatis

此步骤需要进行两项设置,数据库连接字符串设置 MyBatis 的 XML 文件配置

1 配置连接字符串

在项目resource下的templates下的application配置文件进行配置

# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver

如果使用 MySQL 是 5.x 之前的使用的是“com.mysql.jdbc.Driver”,如果是大于 5.x 使用的是“com.mysql.cj.jdbc.Driver”

2 配置 MyBatis 中的 XML 路径

# 配置 mybatis xml 的文件路径,在 resources/下的application中 创建所有表的 xml 文件
mybatis:
mapper-locations: classpath:mapper/**Mapper.xm

3.5添加相关代码

我们按照这个流程来一步步实现功能

 

1 添加实体类

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.Date;


@Setter
@Getter
@ToString
public class Articleinfo {
    private Integer id;
    private String title;
    private String content;
    private Date createtime;
    private Date updatetime;
    private Integer uid;
    private Integer rcount;
    private Integer state;
    
}

2 添加 mapper 接口 

数据持久层的接口定义:

import com.example.mybatisstudy.model.Articleinfo;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
import java.util.Map;

@Mapper
public interface ArticleMapper {

    List<Articleinfo> all();

    Articleinfo queryById(Integer id);

    int add(Articleinfo info);

    int modify(Articleinfo content);

    int delete(Integer id);

    }

3 添加 ArticleMapper.xml

数据持久成的实现,mybatis 的固定 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="com.example.mybatisstudy.mapper.ArticleMapper">

<select id="getAll" resultType="com.example.demo.model.Articleinfo">
select * from userinfo
</select>

</mapper>

<mapper>标签:需要指定 namespace 属性,表示命名空间,值为 mapper 接口的全限定名,包括全包名.类名。

4 添加 Controlle

控制器层的实现代码如下:

package com.example.mybatisstudy.controller;

import com.example.mybatisstudy.mapper.ArticleMapper;
import com.example.mybatisstudy.model.Articleinfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/article")
public class ArticleController {
    private static final Map map=new HashMap<>();
    @Autowired
    private ArticleMapper articleMapper;

    @RequestMapping("/queryAll")
    public Object queryAll(){
        return articleMapper.all();
    }
 
}

我们编写了基本的查询Articleinfo所有信息的方法,可以借助postman来测试一下

 

 

 4.实现增,删,改,操作

接下来,我们来实现一下用户的增加、删除和修改的操作

我们以简单的操作作为演示:

ArticleMapper.xml:

    <insert id="add">
        insert into articleinfo(title,content,uid) values (#{title},#{content},#{uid})
    </insert>
    <update id="modify">
        update articleinfo set content=#{content} where id=#{id}
    </update>
    <delete id="delete">
        delete from articleinfo where id=#{id}
    </delete>

mapper interface:

import com.example.mybatisstudy.model.Articleinfo;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
import java.util.Map;

@Mapper
public interface ArticleMapper {

    List<Articleinfo> all();


    int add(Articleinfo info);

    int modify(Articleinfo content);

    int delete(Integer id);

    
}

 controller 实现代码:

import com.example.mybatisstudy.mapper.ArticleMapper;
import com.example.mybatisstudy.model.Articleinfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/article")
public class ArticleController {
    private static final Map map=new HashMap<>();
    @Autowired
    private ArticleMapper articleMapper;

    @RequestMapping("/queryAll")
    public Object queryAll(){
        return articleMapper.all();
    }
    @RequestMapping("/add")
    public Object add(Articleinfo info){
        int add = articleMapper.add(info);
        return add;
    }
    @RequestMapping("/modify")
    public Object modify(Articleinfo info){
        int modify = articleMapper.modify(info);
        return modify;
    }
    @RequestMapping("/del")
    public Object delete(Integer id){
        int delete = articleMapper.delete(id);
        return delete;
    }
}

5.查询操作

5.1Select

import java.util.List;
import java.util.Map;

@Mapper
public interface ArticleMapper {

    List<Articleinfo> all();

    Articleinfo queryById(Integer id);

    int add(Articleinfo info);

    int modify(Articleinfo content);

    int delete(Integer id);
}

controller实现方法:

@RequestMapping("/queryById")
    public Object queryById(Integer id){
        return articleMapper.queryById(id);
    }

xml文件下:

<select id="queryById" resultType="com.example.mybatisstudy.model.Articleinfo">
        select * from articleinfo where id=#{id}
    </select>

5.2模糊查询?

 

 

 

 5.3多表查询

一对一的表映射

一对一映射要使用 标签,具体实现如下:

<resultMap id="BaseMap" type="com.example.demo.model.ArticleInfo">
<id property="id" column="id"></id>
<result property="title" column="title"></result>
<result property="content" column="content"></result>
<result property="createtime" column="createtime"></result>
<result property="updatetime" column="updatetime"></result>
<result property="uid" column="uid"></result>
<result property="rcount" column="rcount"></result>
<result property="state" column="state"></result>
<association property="user"
resultMap="com.example.demo.mapper.UserMapper.BaseMap"
columnPrefix="u_">
</association>
</resultMap>
<select id="getAll" resultMap="BaseMap">
select a.*,u.username u_username from articleinfo a
left join userinfo u on a.uid=u.id
</select>

以上使用 标签,表示一对一的结果映射:

property 属性:指定 Article 中对应的属性,即用户。

resultMap 属性:指定关联的结果集映射,将基于该映射配置来组织用户数据。

columnPrefix 属性:绑定一对一对象时,是通过 columnPrefix+association.resultMap.column 来映射结果集字段。association.resultMap.column是指 标签中 resultMap属性,对应的结果集映射中,column字段。 

注意事项:column不能省略


一对多:一个用户多篇文章示例:

<resultMap id="BaseMap" type="com.example.demo.model.User">
<id column="id" property="id" />
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="photo" property="photo"></result>
<collection property="alist" resultMap="com.example.demo.mapper.ArticleInfoMapper.BaseMap"
columnPrefix="a_">
</collection>
</resultMap>
<select id="getUserById" resultMap="BaseMap">
select u.*,a.title a_title from userinfo u
left join articleinfo a on u.id=a.uid where u.id=#{id}
</select>

6.动态sql使用

6.1 <if>标签

两种字段:必填字段和非必填字段,那如果在添加的时候有不确定的字段传入,程序应该如何实现呢? 这个时候就需要使用动态标签 来判断了,比如添加的时候性别 sex 为非必填字段,具体实现如下:

<insert id="insert" parameterType="org.example.model.User" useGeneratedKeys="true" keyProperty="id">
insert into user(
username,
password,
nickname,
<if test="sex != null">
sex,
</if>
birthday,
head
) values (
#{username},
#{password},
#{nickname},
<if test="sex != null">
#{sex},
</if>
#{birthday},
#{head}
)
</insert>

注意 test 中的 sex,是传入对象中的属性,不是数据库字段 

6.2 <trim>标签

之前的插入用户功能,只是有一个 sex 字段可能是选填项,如果有多个字段,一般考虑使用标签结合标签,对多个字段都采取动态生成的方式。 标签中有如下属性:

prefix:表示整个语句块,以prefix的值作为前缀

suffix:表示整个语句块,以suffix的值作为后缀

prefixOverrides:表示整个语句块要去除掉的前缀

suffixOverrides:表示整个语句块要去除掉的后缀

例如:

<insert id="insert" parameterType="org.example.model.User" useGeneratedKeys="true" keyProperty="id">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">
username,
</if>
<if test="password != null">
password,
</if>
<if test="nickname != null">
nickname,
</if>
<if test="sex != null">
sex,
</if>
<if test="birthday != null">
birthday,
</if>
<if test="head != null">
head,
</if>
<if test="createTime != null">
create_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="username != null">
#{username},
</if>
<if test="password != null">
#{password},
</if>
<if test="nickname != null">
#{nickname},
</if>
<if test="sex != null">
#{sex},
</if>
<if test="birthday != null">
#{birthday},
</if>
<if test="head != null">
#{head},
</if>
<if test="createTime != null">
#{createTime},
</if>
</trim>
</insert>

在以上 sql 动态解析时,会将第一个 部分做如下处理:

基于 prefix 配置,开始部分加上 (

基于 suffix 配置,结束部分加上 )

多个 组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于 suffixOverrides 配置去掉最后一个 

注意 中的 createTime 是传入对象的属性  

6.3 <where>标签

传入的用户对象,根据属性做where条件查询,用户对象中属性不为 null 的,都为查询条件。如 user.username 为 "a",则查询条件为 where username="a": UserMapper 接口中新增条件查询方法:

List<User> selectByCondition(User user);

UserMapper.xml 中新增条件查询 sql:

<select id="selectByCondition" parameterType="org.example.model.User" resultMap="BaseResultMap">
select id, username, password, nickname, sex, birthday, head, create_time
from user
<where>
<if test="username != null">
and username=#{username}
</if>
<if test="password != null">
and password=#{password}
</if>
<if test="nickname != null">
and nickname=#{nickname}
</if>
<if test="sex != null">
and sex=#{sex}
</if>
<if test="birthday != null">
and birthday=#{birthday}
</if>
<if test="head != null">
and head=#{head}
</if>
<if test="createTime != null">
and create_time=#{createTime}
</if>
</where>
</select>

 以上标签也可以使用<trim prefix="where " prefixoverrides="and">替换。

6.4 <set>标签

根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容。 UserMapper 接口中修改用户方法:根据传入的用户 id 属性,修改其他不为 null 的属性:

int updateById(User user);

UserMapper.xml 中添加更新用户 sql:

<update id="updateById" parameterType="org.example.model.User">
update user
<set>
<if test="username != null">
username=#{username},
</if>
<if test="password != null">
password=#{password},
</if>
<if test="nickname != null">
nickname=#{nickname},
</if>
<if test="sex != null">
sex=#{sex},
</if>
<if test="birthday != null">
birthday=#{birthday},
</if>
<if test="head != null">
head=#{head},
</if>
<if test="createTime != null">
create_time=#{createTime},
</if>
</set>
where id=#{id}
</update>

  以上标签也可以使用<trim prefix="set " suffixoverrides="and">替换。

6.5 <foreach>标签

对集合进行遍历时可以使用该标签。标签有如下属性:

collection:绑定方法参数中的集合,如 List,Set,Map或数组对象

item:遍历时的每一个对象

open:语句块开头的字符串

close:语句块结束的字符串

separator:每次遍历之间间隔的字符串

示例:根据多个文章 id 来删除文章数据。 ArticleMapper 中新增接口方法:

int deleteByIds(List<Integer> ids);

ArticleMapper.xml 中新增删除 sql:

<delete id="deleteByIds">
delete from article
where id in
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北~笙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值