Java_SpringBoot_MybatisPlus入门

一、SpringBoot项目的创建

步骤一:注意使用idea创建springboot项目时必须在联网状态
Java_SpringBoot_MybatisPlus入门_第1张图片步骤二:
Java_SpringBoot_MybatisPlus入门_第2张图片
步骤三:
Java_SpringBoot_MybatisPlus入门_第3张图片

2.配置完成后,我将以前的小东西复制过去:

结构如下:
在springBoot中,配置类config的包已经不需要了
Java_SpringBoot_MybatisPlus入门_第4张图片

3.同时使用yml配置文件给设置数据源

注意书写格式,同级对齐,下一级比上一级多一个空格

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    password: root
    username: root
    url: jdbc:mysql://localhost:3306/db5?serverTimezone=GMT%2B8&useSSL=false
        #修改tomcat的端口号
server:
  port: 88
mybatis:
  configuration:
    map-underscore-to-camel-case: true
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
# 使用雪花算法自动填充id,当然MybatisPlus默认为雪花算法
     id-type: assign_id
# 匹配表名和实体类名,这个表示表名为“tb_xxx"开头的,其中(xxx)和实体类名一样,@TableName也可以用来映射表名和实体类
  #   table-prefix: tb_
     #配置全局逻辑删除,选定逻辑删除字段
#     logic-delete-field: tbDeleted
#     #确定逻辑删除后,表示逻辑删除的字段的用什么来表示改记录被删除
#     logic-delete-value: 1
#     #为被逻辑删除的字段应该怎样表示
#     logic-not-delete-value: 0

同时给以下druid的依赖,虽然springBoot使用了maven的继承和依赖传递特性,但是并不是所有包都能继承,有些需要选配

<dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.2.6version>
dependency>

然后就是放置静态资源的地方:
Java_SpringBoot_MybatisPlus入门_第5张图片

4.在dao层的包中添加一个注解

@Mapper:用来替代MybatisConfig中的包扫描配置

@Mapper//用来取代包扫描的动作
public interface UserDao {
    @Insert("insert into users values(null,#{tbUsername},#{tbZhanghao},#{tbPassword},#{tbAge},#{tbGender},#{tbAddress},#{tbBirthday})")
    public void save(Users user);

    @Update("update users set tb_username=#{tbUsername},tb_zhanghao=#{tbZhanghao},tb_password=#{tbPassword},tb_age=#{tbAge},tb_gender=#{tbGender},tb_address=#{tbAddress},tb_birthday=#{tbBirthday} where tb_uid=#{tbUid} ")
    public void update(Users user);

    @Delete("delete from users where tb_uid=#{tbUid}")
    public void delete(Integer id);

    @Select("select * from users where tb_uid=#{tbUid}")
    public Users selectById(Integer id);

    @Select("select * from users")
    public List<Users> selectAll();

    /*
     * 手写,分页查询
     * */
    @Select("select * from users limit #{start},#{pageSize}")
    public List<Users> findByPage(@Param("start") int start, @Param("pageSize") int pageSize);

    // 查询总的数据数量
    @Select("select count(*) from users")
    public int totalPage();

}

5.启动

如果想要启动,就在启动类中开始就行,上面有标注启动类在哪里。但是我们这个没有当初选择时没有选Mybatis,所以应该不行,
后面我会改成使用MybatisPlus。
启动类,这些都是SpringBoot自动创建的:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Day07SpringBootApplication {
//被这个主类扫描的包需要放在和这个类同级的目录下
    public static void main(String[] args) {
        SpringApplication.run(Day07SpringBootApplication.class, args);
    }

}

二、使用MybatisPlus替换Mybatis

2.1MybatisPlus的配置

在Maven中添加依赖:

<dependency>
         <groupId>com.baomidou</groupId>
         <artifactId>mybatis-plus-boot-starter</artifactId>
         <version>3.4.1</version>
</dependency>

2.2MybatisPlus的优点

1.无侵入:只做增强不做改变,对现有工程不会产生影响,可以与mybatis配合使用
2.强大的CRUD操作:内置通用的Mapper,少量配置后即可完成基础的CRUD操作
3.支持Lambda:编写条件查询无需担心字段写错
4.支持主键自动生成
5.内置分页插件
id的主键生成策略:
Java_SpringBoot_MybatisPlus入门_第6张图片

分页插件:

MybatisPlus的分页插件需要配合到spring的拦截器一起使用。所以先编写配置类:
MybatisPlusConfig.java:

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisplusConfig {
    @Bean
    public MybatisPlusInterceptor setMpInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;

    }
}
然后是业务层(Service)使用分页插件:
 @Override
    public IPage<Users> findByPage(long currentPage, long pageSize) {
        IPage<Users> Page = new Page<Users>(currentPage,pageSize);
        IPage<Users> iPage = userDao.selectPage(Page,null);
        return iPage;
    }
表现层(Controller)的使用:
@GetMapping("/{currentPage}/{pageSize}")
public Result selectByPage(@PathVariable long currentPage, @PathVariable long pageSize) {

    IPage<Users> usersList = userService.findByPage(currentPage, pageSize);
    Result result = new Result(usersList,Code.SELECT_OK,"");
    return result;
}
返回给前端的东西有点多,其中records是分页查询到的数据:

Java_SpringBoot_MybatisPlus入门_第7张图片

逻辑删除

为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中。
所以我们要在数据库中添加一个表示逻辑删除的字段,并且设置默认值。

//    这是一个用来标注逻辑删除的字段,用来表示用户是否被删除,在数据库中代表逻辑删除的字段应该有默认值
//    如果不想写@TableFiled与表中字段进行映射,就写与表中字段名称一样,我是因为开启了驼峰命名,否则也需要映射
//    value代表未被逻辑删除,delval代表已被逻辑删除
//    该注解会在mp执行删除语句时更改(update语句)数据库中的字段数据,如果是执行其他的查询操作,则会在sql中填充where条件查询,如果为tb_Deleted=1则不对该数据进行查询
    @TableLogic(value = "0",delval = "1")
    private Integer tbDeleted;

2.3小测试改为MybatisPlus

使用了MybatisPlus就可使用其内置的Mapper,所以在数据层的注解可以注释掉了,但是@Mapper注解不能去掉,还需要继承BaseMapper<>
UserDao:

import cn.itheima.pojo.Users;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper//用来取代包扫描的动作,BaseMapper中的范型,其实是MybatisPlus用来执行sql语句时查询的表名,所以务必保证:类名与表名一直或者使用了@TableName映射,否则你查不出来的
public interface UserDao extends BaseMapper<Users> {

}

实体类的变化有点大,@Data需要lombok依赖,除了构造方法没有帮忙创建,其余都有。注意,我们需要保证实体类Users的名字和数据库中表的名字一致,否则就需要用@TableName(表名)映射一下,其他注意事项在代码注解中。也处理了后端向前端发送Long型数据,前端数据溢出的问题,使用了@JsonSerialize(using= ToStringSerializer.class)注解。id的数据类型应该为Long,数据库对应修改为bigint
Users:

import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import org.springframework.stereotype.Repository;

import javax.annotation.sql.DataSourceDefinition;
import java.util.Date;

@Repository
@Data
public class Users {
//    注意:如果为设置id生成策略,但是数据库的主键设置为自增,则mybatisPlus会自动产生id生成测略,并且使用的雪花算法生成的
//    所以id的类型需要改为Long型并且,数据库中id字段的类型改为bigint
//    使用MybatisPlus则主键字段的名称必为“id”,数据库中的主键字段也为“id”。
//    使用JsonSerialize注解,后端数据在序列化时就可以转成字符串类型,解决了前端无法解析long型数据
@JsonSerialize(using= ToStringSerializer.class)
    private Long id;
    //我开启了驼峰命名表结构是tb_xxx所以可以映射,如果你的表中字段名和类中的属性名不一致且无法完成驼峰命名,请使用@TableFiled()映射一下
    private String tbUsername;
    private String tbZhanghao;
    private Integer tbPassword;
    private Integer tbAge;
    private String tbGender;
    private String tbAddress;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date tbBirthday;
//    这是一个用来标注逻辑删除的字段,用来表示用户是否被删除,在数据库中代表逻辑删除的字段应该有默认值
//    如果不想写@TableFiled与表中字段进行映射,就写与表中字段名称一样,我是因为开启了驼峰命名,否则也需要映射
//    value代表未被逻辑删除,delval代表已被逻辑删除
//    该注解会在mp执行删除语句时更改(update)数据库中的字段数据,如果是执行其他的查询操作,则会在sql中填where条件查询,如果为1则不对该数据进行查询
//    可以全局配置也可以单独配置,看自己需求,全局配置就在“.yml”配置文件中配置即可
// jackson提供的注解
    @TableLogic(value = "0",delval = "1")
    private Integer tbDeleted;

    public Users() {
    }

    public Users(Long id, String tbUsername, String tbZhanghao, Integer tbPassword, Integer tbAge, String tbGender, String tbAddress, Date tbBirthday, Integer tbDeleted) {
        this.id = id;
        this.tbUsername = tbUsername;
        this.tbZhanghao = tbZhanghao;
        this.tbPassword = tbPassword;
        this.tbAge = tbAge;
        this.tbGender = tbGender;
        this.tbAddress = tbAddress;
        this.tbBirthday = tbBirthday;
        this.tbDeleted = tbDeleted;
    }

}

这里方前端的全部,里面有修改的地方:
user.html(findByPage方法被修改了,以及按钮的传递参数名字被修改了):

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户管理title>
head>
<body>
<div id="userContains">
    <table border="1px" cellspacing="0px" width="100%">
        <tr>
            <th>编号th>
            <th>名称th>
            <th>账号th>
            <th>密码th>
            <th>年龄th>
            <th>性别th>
            <th>住址th>
            <th>生日th>
            <th>操作th>
        tr>
        <tr v-for="(user,i) in users">
            
            <td>{{i+1}}td>
            <td>{{user.tbUsername}}td>
            <td>{{user.tbZhanghao}}td>
            <td>{{user.tbPassword}}td>
            <td>{{user.tbAge}}td>
            <td v-if="user.tbGender=='0'">td>
            <td v-if="user.tbGender=='1'">td>
            <td>{{user.tbAddress}}td>
            <td>{{user.tbBirthday}}td>
            <td><a href="#" @click="updateUser(user.id)">编辑a> |<a href="#" @click="deleteUser(user.id)">删除a>td>
        tr>
    table>

    <div>
        <a href="" @click.prevent="changePage(page)" v-for="page in pageDate.totalPage">{{page}} a>
    div><br>
    <div>
        <a href="/pages/addUser.html">添加用户a>
    div>
div>


<script src="../js/vue.js">script>
<script src="../js/axios-0.18.0.js">script>
<script>
    new Vue({
        el: "#userContains",
        data() {
            return {
                users:[],
                pageDate:{
                    currentPage:1.0,
                    pageSize:2.0,
                    totalPage:0,
                    total:0,
                }
            }
        },
        methods: {
            findAll() {
                var _this = this
                axios({
                    method: "get",
                    url: "/users",
                }).then(function (resp) {

                    _this.users = resp.data.data
                })
            },

            findByPage(){
                var _this = this
                // 分页助手版,分页查询
                /*axios({
                    method: "get",
                    url: "/day05_SSM/users/"+_this.pageDate.currentPage+"/"+_this.pageDate.pageSize,
                }).then(function (resp) {
                    console.log(resp.data.data);
                    _this.users = resp.data.data.list
                    _this.pageDate.total = resp.data.data.total
                    _this.pageDate.totalPage = resp.data.data.pages
                })*/
                axios({
                    method:"get",
                    url: "/users/"+_this.pageDate.currentPage+"/"+_this.pageDate.pageSize,
                }).then(function (resp){
                    console.log(resp.data.data)
                    _this.users = resp.data.data.records
                    _this.pageDate.totalPage = resp.data.data.pages
                })
            },

            changePage(currentPage){
                  this.pageDate.currentPage = currentPage;
                  this.findByPage();
            },
            deleteUser(uid){
                _this1 = this
                alert("点击删除"+uid)
                axios({
                    method:"delete",
                    url:"/users/"+uid
                }).then(function (resp){
                   alert( resp.data.msg)
                    _this1.findByPage();
                })
            },
            updateUser(uid){
                location.href="/pages/updateUser.html?id="+uid;
            }

        },
        mounted() {
            //this.findAll();
            this.findByPage();
        }
    })
script>
<script>

script>
body>
html>

updateUser.html(只需注意实体类中tbUid字段已经被修改成id了,所以取的参数也改了):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="updateContains">
    <form id="form" action="" method="post">
        <input type="hidden" id="uid" v-model="user.id">
        用户名:<input type="text" id="username" v-model="user.tbUsername"><br>
        账号:<input type="text" id="zhanghao" v-model="user.tbZhanghao"><br>
        密码:<input type="password" id="password" v-model="user.tbPassword"><br>
        性别:<input type="radio" value="0" v-model="user.tbGender"><input type="radio" value="1" v-model="user.tbGender"><br>
        地址:<input type="text" id="address" v-model="user.tbAddress"><br>
        年龄:<input type="text" id="age" v-model="user.tbAge"><br>
        生日:<input type="date" id="birthday" v-model="user.tbBirthday"><br>
        <button type="button" id="bt" value="bt" @click="updateuser()">修改</button>
    </form>
</div>
<script src="../js/vue.js"></script>
<script src="../js/axios-0.18.0.js"></script>

<script>
    C1 = window.location.href.split("?")[1];
    uid = C1.split("=")[1];

    let vue = new Vue({
        el: "#updateContains",
        data() {
            return {
                user: {
                    tbid:"",
                    tbUsername: "",
                    tbZhanghao: "",
                    tbPassword: "",
                    tbGender: "",
                    tbAddress: "",
                    tbAge: "",
                    tbBirthday: "",
                },
                code: {
                    checkCode: ""
                }
            };
        },
        methods: {
            findById() {
                var _this = this
                axios({
                    method: "get",
                    url: "/users/" + uid
                }).then(function (resp) {
                    _this.user.id = resp.data.data.id
                    _this.user.tbUsername = resp.data.data.tbUsername
                    _this.user.tbZhanghao = resp.data.data.tbZhanghao
                    _this.user.tbPassword = resp.data.data.tbPassword
                    _this.user.tbGender = resp.data.data.tbGender
                    _this.user.tbAddress = resp.data.data.tbAddress
                    _this.user.tbAge = resp.data.data.tbAge
                    _this.user.tbBirthday = resp.data.data.tbBirthday
                })
            },
            updateuser() {
                axios({
                    method: "put",
                    url: "/users",
                    data: vue.user
                }).then(function (resp) {
                    if (resp.data.msg == "success") {
                        location.href = "/pages/user.html"
                    } else {
                        alert("这测失败");
                    }
                })
            }
        },
        mounted() {
           this.findById();
        }
    });

</script>
</body>
</html>

addUser.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加操作</title>
</head>
<body>
<div id="addContains">
    <form id="form" action="" method="post">
        用户名:<input type="text" id="username" v-model="user.tbUsername"><br>
        账号:<input type="text" id="zhanghao" v-model="user.tbZhanghao"><br>
        密码:<input type="password" id="password" v-model="user.tbPassword"><br>
        性别:<input type="radio" value="0" v-model="user.tbGender"><input type="radio" value="1" v-model="user.tbGender"><br>
        地址:<input type="text" id="address" v-model="user.tbAddress"><br>
        年龄:<input type="text" id="age" v-model="user.tbAge"><br>
        生日:<input type="date" id="birthday" v-model="user.tbBirthday"><br>
        <button type="button" id="bt" value="bt" @click="adduser()">添加</button>
    </form>
</div>
<script src="../js/vue.js"></script>
<script src="../js/axios-0.18.0.js"></script>

<script>
    let vue = new Vue({
        el: "#addContains",
        data() {
            return {
                user: {
                    tbUsername: "",
                    tbZhanghao: "",
                    tbPassword: "",
                    tbGender: "",
                    tbAddress: "",
                    tbAge: "",
                    tbBirthday: "",
                },
                code: {
                    checkCode: ""
                }
            };
        },
        methods: {
            adduser() {
                axios({
                    method:"post",
                    url:"/users",
                    data:vue.user
                }).then(function (resp){
                     if(resp.data.msg == "success"){
                         location.href="/pages/user.html"
                     }else{
                         alert("这测失败");
                     }
                })
            }
        }
    });

</script>
</body>
</html>

三、MybatisPlus的其他功能

直接在代码注释中有描述:
test:
“Users::getTbAge”,这种格式可以理解为,表示数据库中的tb_age这个字段

@SpringBootTest
class Day08MybatisPlusApplicationTests {
    @Autowired
    UserDao userDao;
    @Autowired
    Users users;

    @Test
    void findAll() {
        List<Users> usersList = userDao.selectList(null);
        System.out.println(usersList);
    }

    @Test
    void testFindByPage(){
        IPage<Users> page = new Page<>(1,2);

        IPage<Users> iPage = userDao.selectPage(page,null);

        System.out.println("一共多少页"+iPage.getPages());
        System.out.println("当前页:"+iPage.getCurrent());
        System.out.println("每页显示个数:"+iPage.getSize());
        System.out.println("数据总数:"+iPage.getTotal());
        System.out.println("数据:"+iPage.getRecords());
    }

    @Test
//    测试调剂查询,lt是小于号,gt是大于号
    public void testselectByCondition(){
//        准备数据,模拟前端页面传过来的数据
        users.setTbAge(10);

        LambdaQueryWrapper<Users> lqw = new LambdaQueryWrapper<>();

//        进行空判断以及大小判断
      //  lqw.gt(null != users.getTbAge(),Users::getTbAge,users.getTbAge());

//        表示and的条件查询,大于10岁并且小于30岁
//        users.getTbAge()表示前端页面的值
/*        lqw.gt(null != users.getTbAge(),Users::getTbAge,users.getTbAge())
             .lt(Users::getTbAge,30);
             
相当于sql语句 select * from users 
                       
                         
                           tb_age ">"(大于号当然不是这样写的^_^) users.getTbAge()
                         
                       
                */

//        表示or 的条件查询,小于10岁或者大于15
        lqw.lt(null != users.getTbAge(),Users::getTbAge,users.getTbAge())
                .or().gt(Users::getTbAge,30);
        List<Users> usersList = userDao.selectList(lqw);
        System.out.println(usersList);

    }
    @Test
    public void testSelectById(){

//        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Users::getTbUid,2);
//        Users users = userDao.selectOne(queryWrapper);
//        System.out.println(users);
        Users users = userDao.selectById(2);
        System.out.println(users);
    }

}

你可能感兴趣的:(Spring专栏,java,spring,boot,mybatis)