Mybatis操作数据库

MyBatis查询数据库

一.MyBatis是什么?

MyBatis是一款优秀的持久层框架,它支持自定义SQL,存储过程以及高级映射.MyBatis去除了几乎所有的JDBC代码以及设置参数和获取结果集的工作.MyBatis可以通过简单的XML注解来配置和映射原始类型,接口和Java POJO(Plain Old Java Object,普通老式Java对象)为数据库中的记录.

简单来说,MyBatis是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库工具.

支持存储过程,存储sql,但(无法调试无debug,可维护性差)

二.为什么要学习MyBatis?

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

1.后端程序

2.数据库
Mybatis操作数据库_第1张图片而这个两个重要的组成部分要通讯,就要依靠数据连接工具,那数据库连接工具有哪些?比如之前所学习的JDBC,还有现在的MyBatis.那么既然已经有JDBC 了,为什么还要用 MyBatis 呢?因为 JDBC 太繁琐了…用过都懂,写个简单的查询都要写一堆繁琐的代码.

三.MyBatis的学习

MyBatis学习只分为两部分:

● 配置MyBatis开发环境

● 使用MyBatis模式和语法操作数据库

四.第一个MyBatis查询

开始搭建MyBatis之前,先看一下MyaBatis在整个框架中的定位,

框架交互流程图:

Mybatis操作数据库_第2张图片

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

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

2.将结果集映为返回对象,即输出对象

ORM把数据库映射为对象:

  • 数据库表(table) --> 类(class)

  • 记录(record,行数据) --> 对象(object)

  • 字段(field) --> 对象的属性(attribute)

一般的ORM框架,会将数据库模型的每张表都映射为一个Java类.

也就是说使用MyBatis可以像操作对象一样来操作数据库中的表,可以实现对象和数据库表之间的转换,关于MyBatis的使用:

1.创建数据库和表

-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8;

-- 使用数据数据
use mycnblog;

-- 创建表[用户表]
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 default now(),
    `state` int default 1 -- 默认为1
);

-- 创建文章表
drop table if exists  articleinfo;
create table articleinfo(
    id int primary key auto_increment,
    title varchar(100) not null,
    content text not null,-- longtext
    createtime datetime default now(),-- 默认值now()
    updatetime datetime default now(),
    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 default now(),
  	uid int
);

-- 添加一个用户信息
INSERT INTO `mycnblog`.`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 videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);

2.MyBatis使用流程

1)添加MyBatis框架支持

有两种情况:

①老项目添加MyBatis

②创建新项目的时候直接添加MyBatis

Mybatis操作数据库_第3张图片
如果没有这个插件,setting一下就得了
Mybatis操作数据库_第4张图片

2)配置MyBatis相关的配置文件(连接字符串和MyBatis的XML文件设置)

①配置数据库连接信息
- 连接数据库服务器地址
- 数据库用户名
- 数据库密码
- 数据库的驱动(数据库的类型)
# 开发环境
spring.datasource.url=jdbc:mysql://localhost:3306/oj_databases1?characterEncoding=utf8&useSS=false
spring.datasource.username=root
spring.datasource.password=109614
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver (MySQL版本8.0以后用这个)
②MyBatis的XML文件位置

在这里插入图片描述
Mybatis操作数据库_第5张图片

③添加代码步骤:(查询)

Mybatis操作数据库_第6张图片

根据这个流程来,(以查询用户为例)

添加实体类:

Mybatis操作数据库_第7张图片Mybatis操作数据库_第8张图片

添加mapper(数据持久层)接口Interface方法定义:

Mybatis操作数据库_第9张图片

mapper(数据持久层)xxx.xml,方法实现:(此处添加UserMapper.xml)

数据持久层的实现,MyBatis的固定 xml 格式:


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <select id="getAll" resultType="com.example.demo.model.UserInfo">
        select * from userinfo
    select>
mapper>

Mybatis操作数据库_第10张图片

添加Service层(服务层):

Mybatis操作数据库_第11张图片

添加Controller(控制器层):

Mybatis操作数据库_第12张图片

查询结果:Mybatis操作数据库_第13张图片

注:pom.xml自带默认的版本,例如mysql8.x(当前我使用的是5.7,所以得自己指定下版本)

五.增,删,改操作

1.关于xml中的两种写法:

由于userInfo实体类同数据库的userInfo表中的用户名字定义的名称不同,导致我们无法访问到
Mybatis操作数据库_第14张图片


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper"> 

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

除了之前查询的时候所使用的的第一种返回类型之外(上面这种),还有另外一种方式,那就是返回字典映射,让实体类的属性和对应的数据库中的表的列名一一对应.


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">   
    
  	<resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
        
        <id column="username" property="name">id>
        
        <result column="username" property="name">result>
        <result column="password" property="password">result>
        <result column="photo" property="photo">result>
        <result column="createtime" property="createtime">result>
        <result column="updatetime" property="updatetime">result>
    resultMap>
    <select id="getAll" resultMap="BaseMap">
        select*from userinfo
    select>
mapper>

再次访问

Mybatis操作数据库_第15张图片

这样就能保证一一对应上了

Mybatis中xml查询返回类型的两种设置的比较:

  1. resultType(返回结果类型)
  2. resultMap(返回映射)

共同点:这两种设置方式的功能是相同的,都是用来指定结果类型

不同点:

  • resultType用法简单,但如果实体类中的属性名和表中的字段名不一致那么将查询不出结果(null)
  • resultMap用法相对麻烦,要实现多个列的映射,但是他可以实现属性和字段即便是名字不同,也能够进行映射,能够查询出正确的数据.

2.添加操作:

这里也不嫌麻烦,再放出逻辑图:Mybatis操作数据库_第16张图片

注意:之前新建用户表的时候,除了用户名称以及用户密码没有指定值之外,其他都有默认或者是一个自增主键.所以我们在对用户表进行插入的时候,只需要插入这两条数据即可.

Controller控制器层添加代码:

//调用是在service服务器进行调用的
//Controller会调用service
@RestController
@RequestMapping("/user")
public class UserController {
    //在controller要先注入service(下层类),这里采用属性注入
    @Autowired
    private UserService userService;
	/**
     * 添加用户(返回受影响的行数)
     * @param userInfo
     * @return
     */
    @RequestMapping("/add")
    public int add(UserInfo userInfo){
        //参数校验 - > 调用业务逻辑层
        if(userInfo == null || userInfo.getName() == null
        || userInfo.getPassword() == null
        || userInfo.getName().equals("")
        || userInfo.getPassword().equals("")){
            //非法参数
            return 0;
        }
        return userService.add(userInfo);
    }
}

Service服务层添加代码:

/**
 * 进行数据组装,调用dao层
 */
@Service
public class UserService {
    //属性注入,将下层类注入到这
    @Autowired
    private UserMapper userMapper;
    
     public int add(UserInfo userInfo) {
        //服务(方法编排)
        return userMapper.add(userInfo);
    }
}

Mapper层添加代码(接口和xml):

InterFace:

@Mapper
public interface UserMapper {
    //接口中进行声明,而实现是在xml里面的
    int add(UserInfo userInfo);
}

XML:


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper"> 
	<resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
        
        <id column="username" property="name">id>
        
        <result column="username" property="name">result>
        <result column="password" property="password">result>
        <result column="photo" property="photo">result>
        <result column="createtime" property="createtime">result>
        <result column="updatetime" property="updatetime">result>
    resultMap>
    
    <insert id="add">
        insert into userinfo(username,password)
        value(#{name},#{password})
    insert>
    
    
mapper>

注意:这里传进来的参数的 key 要和 #{} 里面的要对应,不如无法插入

到这里,代码都写完了,接下来就是进行插入测试:

Mybatis操作数据库_第17张图片
Mybatis操作数据库_第18张图片

可以看到,插入成功了.

特殊的添加:

默认情况下,返回的是受影响的行号,如果想要返回自增id

    /**
     * 添加方法2,返回用户自增id
     * @param userInfo
     * @return
     */
    @RequestMapping(value = "/add2")
    public int add2(UserInfo userInfo){
        //参数校验 - > 调用业务逻辑层
        if(userInfo == null || userInfo.getName() == null
                || userInfo.getPassword() == null
                || userInfo.getName().equals("")
                || userInfo.getPassword().equals("")){
            //非法参数
            return 0;
        }
        //调用数据库执行添加操作,执行完之后会将自增id设置到userinfo的id属性
        userService.add2(userInfo);
        return userInfo.getId();
    }

添加过程和前面可以说基本一样,在对应层改一下复制一下add,改成add2()即可.

xml的实现:

    
    <insert id="add2" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
        insert into userinfo(username,password)
        value(#{name},#{password})
    insert>

mapper.xml会将自增的id插入到当前项目对象类中指定的主键属性上.

  • useGeneratedKeys: 这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键 (比如: 像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段,默认值: false)
  • keyColumn: 设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的.如果生成列不止一个,可以用逗号分隔多个属性名称.
  • keyProperty: 指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKey 的返回值或 insert 语句的 selectKey 子元素来设置它的值,默认值:未设置(unset).如果生成列不止一个,可以用逗号分隔多个属性名称.

Mybatis操作数据库_第19张图片

3.修改操作

/**
 * 修改操作
 * @param id
 * @param password
 * @return
 */
@RequestMapping("/update")
public int update(int id,String password){
    if(id <= 0 || password == null || password.equals("")){
        return 0;
    }
    return userService.update(id,password);
}

<update id="update">
    update userinfo set password = #{password}
    where id = #{id}
update>

Mybatis操作数据库_第20张图片

4.删除操作

Controller层,剩余层直接快速生成即可.

@RequestMapping(value = "/del")
public Integer del(Integer id){
    if(id <= 0){
        return 0;
    }
    return userService.del(id);
}

<delete id="del">
    delete from userinfo where id = #{id};
delete>

测试:Mybatis操作数据库_第21张图片

Mybatis操作数据库_第22张图片

5.关于参数占位符#{}和${}

1)#{}和${}

  • #{}:预编译处理
  • ${}:字符直接替换

预编译处理是指: MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为 ? 号,使用 PreparedStatement 的 set 方法来赋值.

直接替换: 是 MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值.

我举个例子即可,username 为 varchar类型(java中String)

select * from userinfo where username = #{name};
select * from userinfo where username = ${name};

然后发送get请求http://localhost:8080/user/select?username=admin

可以看到我们传递了username 为 admin的参数

上面那两局转换为 sql 分别为:

select * from userinfo where username = ‘admin’;

select * from userinfo where username = admin;

直接替换罢了,改成 '${name}'就一样了

既然如此,那么只要#{}不就得了,为什么还要有${}呢?

别急,下面来说说 #{} 的优点,也就是说说他的使用场景

2)${}的优点

Mybatis操作数据库_第23张图片

/**
 * ${}的使用
 * @param order
 * @return
 */
@RequestMapping("/sort")
public List<UserInfo> sort(String order){
    return userService.sort(order);
}

<select id="sort" resultMap="BaseMap">
    select * from userinfo order by id ${sort}
select>

使用 ${sort} 可以实现排序查询,而使用 #{sort} 就不能实现排序查询了,因为当使用 #{sort}查询时,如果传递的值为 String 则会加单引号,就会导致sql错误

{}里的值可以随意指定

测试:Mybatis操作数据库_第24张图片

你可能感兴趣的:(笔记,数据库,mybatis,java)