1)条件准备:构建基于Mybatis的SpringBoot项目

【1】创建SpringBoot工程

  • 文件
  • 新建
  • 新模块
    在这里插入图片描述
  • 语言-java
  • 类型-Maven
  • 工件-项目名
  • 选择自己版本的jdk
  • 打包-默认选择jar
    在这里插入图片描述
  • 选择依赖
  • 依赖①-Mybatis Framework

Mybatis Framework:Mybatis框架是一款持久层框架,它通过XML映射文件或者注解方式将Java对象和SQL语句进行映射,从而简化了Java程序访问关系型数据库的操作。

  • 依赖②-MySQL Driver

MySQL Driver:MySQL Driver是MySQL数据库的Java驱动程序,它提供了Java程序与MySQL数据库之间的连接和交互能力。Java程序需要使用MySQL数据库时,需要先加载MySQL Driver,然后通过DriverManager获取数据库连接。

在这里插入图片描述

【2】连接数据库

连接数据库看我的这篇博文:IDEA连接MySQL数据库

【3】创建员工表emp

SQL脚本如下:

-- 员工管理
create table emp (
                     id int unsigned primary key auto_increment comment 'ID',
                     username varchar(20) not null unique comment '用户名',
                     password varchar(32) default '123456' comment '密码',
                     name varchar(10) not null comment '姓名',
                     gender tinyint unsigned not null comment '性别, 说明: 1, 2 女',
                     image varchar(300) comment '图像',
                     job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师',
                     entrydate date comment '入职时间',
                     dept_id int unsigned comment '部门ID',
                     create_time datetime not null comment '创建时间',
                     update_time datetime not null comment '修改时间'
) comment '员工表';

INSERT INTO emp
(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) VALUES


(1,'jinyong','123456','金庸',1,'1.jpg',4,'2000-01-01',2,now(),now()),
(2,'zhangwuji','123456','张无忌',1,'2.jpg',2,'2015-01-01',2,now(),now()),
(3,'yangxiao','123456','杨逍',1,'3.jpg',2,'2008-05-01',2,now(),now()),
(4,'weiyixiao','123456','韦一笑',1,'4.jpg',2,'2007-01-01',2,now(),now()),
(5,'changyuchun','123456','常遇春',1,'5.jpg',2,'2012-12-05',2,now(),now()),
(6,'xiaozhao','123456','小昭',2,'6.jpg',3,'2013-09-05',1,now(),now()),
(7,'jixiaofu','123456','纪晓芙',2,'7.jpg',1,'2005-08-01',1,now(),now()),
(8,'zhouzhiruo','123456','周芷若',2,'8.jpg',1,'2014-11-09',1,now(),now()),
(9,'dingminjun','123456','丁敏君',2,'9.jpg',1,'2011-03-11',1,now(),now()),
(10,'zhaomin','123456','赵敏',2,'10.jpg',1,'2013-09-05',1,now(),now()),
(11,'luzhangke','123456','鹿杖客',1,'11.jpg',5,'2007-02-01',3,now(),now()),
(12,'hebiweng','123456','鹤笔翁',1,'12.jpg',5,'2008-08-18',3,now(),now()),
(13,'fangdongbai','123456','方东白',1,'13.jpg',5,'2012-11-01',3,now(),now()),
(14,'zhangsanfeng','123456','张三丰',1,'14.jpg',2,'2002-08-01',2,now(),now()),
(15,'yulianzhou','123456','俞莲舟',1,'15.jpg',2,'2011-05-01',2,now(),now()),
(16,'songyuanqiao','123456','宋远桥',1,'16.jpg',2,'2010-01-01',2,now(),now()),
(17,'chenyouliang','123456','陈友谅',1,'17.jpg',NULL,'2015-03-21',NULL,now(),now());

【4】创建实体类Emp

import java.time.LocalDate;
import java.time.LocalDateTime;


public class Emp {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Short gender;
    private String image;
    private Short job;
    private LocalDate entrydate;
    private Integer deptId;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;

    public Emp() {
    }

    public Emp(Integer id, String username, String password, String name, Short gender, String image, Short job, LocalDate entrydate, Integer deptId, LocalDateTime createTime, LocalDateTime updateTime) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.name = name;
        this.gender = gender;
        this.image = image;
        this.job = job;
        this.entrydate = entrydate;
        this.deptId = deptId;
        this.createTime = createTime;
        this.updateTime = updateTime;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Short getGender() {
        return gender;
    }

    public void setGender(Short gender) {
        this.gender = gender;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public Short getJob() {
        return job;
    }

    public void setJob(Short job) {
        this.job = job;
    }

    public LocalDate getEntrydate() {
        return entrydate;
    }

    public void setEntrydate(LocalDate entrydate) {
        this.entrydate = entrydate;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public LocalDateTime getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(LocalDateTime updateTime) {
        this.updateTime = updateTime;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", gender=" + gender +
                ", image='" + image + '\'' +
                ", job=" + job +
                ", entrydate=" + entrydate +
                ", deptId=" + deptId +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                '}';
    }
}

【5】项目结果

在这里插入图片描述

【6】前提知识点了解

参数占位符【1】说明和【2】使用时机
#{…}【1】执行SQL时,会将#{…}替换成?,生成预编译SQL,会自动设置参数值。【2】参数传递,都使用==#{…}==
${…}【1】拼接SQL,直接将参数拼接在SQL语句中,存在SQL注入问题。【2】如果对表名、列表进行动态设置时使用

2)增加操作

  • ①在Mapper接口里面定义的增加操作的方法需要用到 @Insert 注解
  • @Insert 基本语法:@Insert(“insert into 表名(字段1,字段2…)”+“values(#{变量1},#{变量2})”)
  • ③如果插入的数据数据项比较多,需要利用对象存储对象传参

【1】在Mapper接口里面【增加数据】的方法代码

 //新增数据
    @Options(keyProperty = "id",useGeneratedKeys = true)//会自动将生成的主键值,赋值给emp对象的id属性
    @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
            "values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
    public void insert(Emp emp);

解释部分代码:

@Options(keyProperty = "id",useGeneratedKeys = true)

这段代码使用了@Options注解,并提供了两个参数:keyProperty和useGeneratedKeys。

  • keyProperty = “id”:
    这个参数指定了生成的主键值要赋值给emp对象的id属性。也就是说,当插入一条记录后,自动生成的主键值将被赋值给id属性。
  • useGeneratedKeys = true:
    这个参数表示要获取数据库自动生成的主键。当插入一条记录时,数据库会自动生成一个主键值,并将其赋值给id属性。
  • 综合来看,这段代码的作用是在执行数据库插入操作后,自动将数据库生成的主键值赋值给emp对象的id属性。这样,程序员就无需手动获取和设置主键值,节省了开发的时间和精力。

注意:对于自增的主键,如果只是通过emp.getId(),获取出来的值只能是 null.需要在EmpMapper接口实现方法那里加上@Option注解来获取自增的主键值。这样才能获取成功!

【2】代码测试部分:

@Test
    public void testInsert(){
        //构造员工对象
        Emp  emp=new Emp();

        emp.setUsername("华1");
        emp.setName("Mike");
        emp.setImage("1.jpg");
        emp.setGender((short)1);
        emp.setJob((short)1);
        emp.setEntrydate((LocalDate.of(2000,1,1)));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);

        //执行新增员工信息的操作
        empMapper.insert(emp);
        //通过 @Options注解获取到的id,并输出验证
        System.out.println(emp.getId());
    }

3)删除操作

【1】在Mapper接口里面【删除数据】的方法代码

 //根据id删除员工数据
    @Delete("delete from emp where id=#{id}")
    public int del(int id);

【2】代码测试部分:


    @Test
    public void testDel() {
        int count = empMapper.del(17);
        System.out.println(count+"记录条已删除!");
    }

注意:empMapper.del()返回值是该操作影响的记录数,也就是删除了几条数据。

4)修改操作

  • ①根据主键修改更新,下面以id为例子
  • @Update基本语法@Update(“update 表名 set 待更新字段1=#{存放更新值的变量1}… where 主键字段 = #{存入的变量}”),实现动态更新数据。
  • ③如果插入的数据数据项比较多,需要利用对象存储对象传参

【1】在Mapper接口里面【修改数据】的方法代码

//根据id更新员工数据
    @Update("update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},"+
    "job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id = #{id}")
    public void update(Emp emp);

【2】代码测试部分:

@Test
    public void testUpdate(){
        //构造员工对象
        Emp emp=new Emp();
        emp.setId(18);//要更新的是ID为18的员工数据


        //要更新的数据项
        emp.setUsername("华");
        emp.setName("汤姆1");
        emp.setImage("2.jpg");
        emp.setGender((short)1);
        emp.setJob(((short)2));
        emp.setEntrydate((LocalDate.of(2000,1,1)));

        emp.setUpdateTime(LocalDateTime.now());//更新的时间
        emp.setDeptId(1);

        //执行新增员工信息的操作
        empMapper.update(emp);
    }

5)查找操作

(1)基本查询

【1】在Mapper接口里面【查找数据】的方法代码


    //根据id查询员工数据
    @Select("select * from emp where id=#{id}")
    public Emp getById(Integer id);//把查询的结果封装到emp对象中再返回

【2】代码测试部分:

    @Test
    public void testGetById(){
        Emp emp=empMapper.getById(22);//查询id为22的员工数据
        System.out.println(emp);
    }

【3】查询结果

在这里插入图片描述

【4】结果分析

问题:为什么最后的三个字段查询出来的值是null

分析:

  • ①实体类属性名 和 数据库表查询返回的字段名一致,mybatis会自动封装
  • ②如果实体类属性名 和 数据库表查询返回的字段名不一致,不能自动封装
    在这里插入图片描述

【5】解决方案

  1. 方案一,给字段起别名,让别名和实体类属性一致

修改在Mapper接口里面【查找数据】的方法代码

 @Select("select id, username, password, name, gender, image, job, entrydate, "+
            "dept_id as deptId, create_time as reateTime , update_time  as updateTime from emp where id=#{id}")
    public Emp getById(Integer id);//把查询的结果封装到emp对象中再返回

测试成功!
在这里插入图片描述

  1. 通过@Results,@Result注解手动映射封装【比较繁琐,了解】

修改在Mapper接口里面【查找数据】的方法代码


    //方案二,通过@Results,@Result注解手动映射封装
    @Results({
            @Result(column = "dept_id",property = "deptId"),
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "update_time",property = "updateTime"),
    })
    @Select("select * from emp where id=#{id}")
    public Emp getById(Integer id);//把查询的结果封装到emp对象中再返回

测试成功!
在这里插入图片描述

  1. #开启Mybatis的驼峰命名自动映射的开关【推荐】

在application.properties配置文件中,添加以下代码。使用之间的在Mapper接口里面【查找数据】的方法代码即可。

#开启Mybatis的驼峰命名自动映射的开关
mybatis.configuration.map-underscore-to-camel-case=true

测试成功!
在这里插入图片描述

(2)条件查询

查询满足这三个条件的员工信息:名字带有“张”,性别是“男”,入职时间在"2010-01-01"-------“2020-01-01”

【1】在Mapper接口里面【条件查询数据】的方法代码

注意:字符串里面不能使用 #{} 的,因此要使用 $ 符号【字符串拼接符号】来代替。但是这样的话,该SQL语句就没有预编译这一步骤,可能存在SQL注入的问题

//条件查询员工,查询的结果可能多个
    @Select("select * from emp where name like '%${name}%' and gender=#{gender} and "+
            "entrydate between #{begin} and #{end} order by update_time desc")
    public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);

解决上述存在的SQL注入问题,利用SQL的concat拼接字符串函数。

//条件查询员工,查询的结果可能多个
    @Select("select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and "+
            "entrydate between #{begin} and #{end} order by update_time desc")
    public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);

【2】代码测试部分:

//条件查询
    @Test
    public void testList(){
        List<Emp> empList=empMapper.list("张",(short)1,LocalDate.of(2010,1,1),LocalDate.of(2020,1,1));
        System.out.println(empList);
    }

【3】测试结果

使用 $ 符号的查询结果
在这里插入图片描述
使用 concat() 函数的查询结果
在这里插入图片描述

6)总结

其实创建Emp实体类不需要如此繁杂的代码,可以引入lombok依赖减少代码量,但是我引入之后就报错,如果有哪位大佬知道的嘀嘀嘀一下~~。2023版的IDEA是已经集成了lombok,并不需要下载插件,但是我引入如下就会出现不存在该依赖

<dependency>  
		<groupId>org.projectlombok</groupId>  
		<artifactId>lombok</artifactId>  
</dependency>

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐