java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > springboot集成mybatis-plus

springboot集成mybatis-plus全过程

作者:zhuang先森

本文详细介绍了如何在SpringBoot环境下集成MyBatis-Plus,包括配置maven依赖、application.yaml文件、创建数据库和Java实体类、Mapper层、Service层和Controller层的设置,同时,还涵盖了时间自动填充、分页查询、多对一和一对多的数据库映射关系设置

springboot集成mybatis-plus

环境:

一、配置

1、maven依赖

  <dependencies>
 <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
    </dependencies>
    
     <!-- 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        
   <dependencies>
        
    <dependencyManagement>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.5.14</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

2、配置文件application.yaml

#数据源配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://1.13.152.218:3306/mp?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: zhuang123
    
#数据库名称
project:
  database: mysql
  
#mybatis-plus配置
mybatis-plus:
  configuration:
    #sql日志打印
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #开启驼峰命名匹配
    map-underscore-to-camel-case: true
    #mapper文件
  mapper-locations: classpath:mapper/${project.database}/**/*.xml,classpath:mapper/*.xml
  #数据库实体类的包全路径,方便在mapper.xml中不许使用实体类的全路径,写类名就行(不区分大小写)
  type-aliases-package: com.zhuang.mp.entity
  global-config:
    db-config:
      #逻辑删除
      logic-delete-value: 0
      logic-not-delete-value: 1
      logic-delete-field: deleted

二、创建过程

1.创建数据库与java实体类

新建user表:

java实体类:

package com.zhuang.mp.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDateTime;
import java.util.Date;


@Data
@Builder
@TableName(value = "user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    @JsonAlias("user_name")
    private String name;
    @JsonAlias("user_age")
    private Integer age;
    @JsonAlias("user_email")
    private String email = "862627527@qq.com";
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    //后端传给前端的时间格式
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    //前端传给后端的时间格式
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonAlias("create_time")
    private Date createTime;
    @JsonAlias("update_time")
    @TableField(value = "update_time" ,fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

}

2.mapper或dao层

UserMapper接口:继承BaseMapper<T>, T为实体类User,需要加上@Mapper注解,如果不加注解需要在启动类上加@MapperScan注解

package com.zhuang.mp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhuang.mp.entity.User;
import com.zhuang.mp.entity.UserVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface UserMapper extends BaseMapper<User> {

    List<User> searchByAges(@Param("ages") List<Long> ages);

    List<UserVo> selectBynames(@Param("names") List<String> names);
}

3.mapper.xml文件

一般放在类路径下:src/main/resources/mapper/

设置命名空间 namespace

namespace=“com.zhuang.mp.mapper.UserMapper

<?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.zhuang.mp.mapper.UserMapper">

    <resultMap id="userResultMap" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <result property="email" column="email"/>
        <result property="createTime" column="create_time"/>
        <result property="updateTime" column="update_time"/>
    </resultMap>

    <select id="searchByAges" resultType="com.zhuang.mp.entity.User">
        select * from user where age in
        <foreach collection="ages" item="age" open="(" close=")" separator=",">
            #{age}
        </foreach>
    </select>
    <select id="selectBynames" resultType="UserVo">
        select name
        from user where
        <foreach collection="names" item="name" separator="or">
        name like "%"#{name}"%"
        </foreach>

    </select>


</mapper>

4.service层

UserService接口:需要继承IService<T>, T 为实体类User

package com.zhuang.mp.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zhuang.mp.entity.User;
import com.zhuang.mp.entity.UserVo;

import java.util.List;

/**
 * @program: mp
 * @description:
 * @author: mrzhuang
 * @create: 2022-12-15 00:48
 **/

public interface UserService extends IService<User> {

    int addUser(User user);

    int updateUser(User user);

    Page<User> searchPage(Page<User> page);

    List<User> searchByAges(List<Long> ages);

    List<UserVo> selectBynames(List<String> names);
}

UsrServiceIpml实现类:需要继承ServiceImpl<M extends BaseMapper, T>, M为接口UserMapper, T为实体类User,需要加上@Service注解

package com.zhuang.mp.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuang.mp.entity.User;
import com.zhuang.mp.entity.UserVo;
import com.zhuang.mp.mapper.UserMapper;
import com.zhuang.mp.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.util.List;

/**
 * @program: mp
 * @description:
 * @author: mrzhuang
 * @create: 2022-12-15 00:49
 **/
@DS("slave_1")
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public int addUser(User user) {
        int insert = userMapper.insert(user);
        return insert;

    }

    @Override
    public int updateUser(@RequestBody User user) {
        int update = userMapper.updateById(user);
        return update;
    }

    @Override
    public Page<User> searchPage(Page<User> page) {
        Page<User> userPage = userMapper.selectPage(page, null);
        return userPage;
    }

    @Override
    public List<User> searchByAges(List<Long> ages) {
        List<User> list = userMapper.searchByAges(ages);
        return list;
    }

    @Override
    public List<UserVo> selectBynames(List<String> names) {
        return userMapper.selectBynames(names);
    }
}

5.controller层

UserController类:

package com.zhuang.mp.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhuang.mp.entity.User;
import com.zhuang.mp.entity.UserVo;
import com.zhuang.mp.enums.CodeEnum;
import com.zhuang.mp.service.UserService;
import com.zhuang.mp.vo.PageVo;
import com.zhuang.mp.vo.ResponseVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @program: mp
 * @description:
 * @author: mrzhuang
 * @create: 2022-12-17 21:40
 **/
@Slf4j
@Api(tags = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    UserService userService;

    @ApiOperation("用户增加")
    @RequestMapping("/add")
    public ResponseVo<User> addUser(@RequestBody User user){
        log.info("user: {}", user);
        int insert = userService.addUser(user);
        if (insert > 0){
            log.info("插入成功!");
            return new ResponseVo<>(CodeEnum.SUCESS.code, CodeEnum.SUCESS.message);
        }
        log.error("插入失败!");
        return new ResponseVo<>(CodeEnum.FAILUIRE.code, CodeEnum.FAILUIRE.message);

    }

    @RequestMapping("/update")
    public ResponseVo<User> updateUser(@RequestBody User user){
        log.info("user: {}", user);
        int update = userService.updateUser(user);
        if (update > 0){
            log.info("更新成功!");
            return new ResponseVo<>(CodeEnum.SUCESS.code, CodeEnum.SUCESS.message);
        }
        log.error("更新失败!");
        return new ResponseVo<>(CodeEnum.FAILUIRE.code, CodeEnum.FAILUIRE.message);

    }

    @PostMapping("/searchPage")
    public ResponseVo<PageVo<User>> searchPage(@RequestBody Page<User> page){
        Page<User> userPage = userService.searchPage(page);
        PageVo<User> userPageVo = new PageVo<>();
        BeanUtils.copyProperties(userPage, userPageVo);
        return new ResponseVo<>(userPageVo);
    }

    @PostMapping("/searchByAges")
    public ResponseVo<List<User>> searchByAges(@RequestBody List<Long> ages){
        List<User> list = userService.searchByAges(ages);
        return new ResponseVo<>(list);

    }

    @PostMapping("/searchByNames")
    public ResponseVo<List<UserVo>> searchByNames(@RequestBody List<String> names){
        List<UserVo> list = userService.selectBynames(names);
        return new ResponseVo<>(list);
    }

}

三、设置时间自动填充

1.实体类日期类型设置

需要再实体类的日期属性上使用@TableField(fill = FieldFill.INSERT)

FiledFill为枚举类型

public enum FieldFill {
    /**
     * 默认不处理
     */
    DEFAULT,
    /**
     * 插入时填充字段
     */
    INSERT,
    /**
     * 更新时填充字段
     */
    UPDATE,
    /**
     * 插入和更新时填充字段
     */
    INSERT_UPDATE
}

实体类:

    @TableField(value = "create_time", fill = FieldFill.INSERT)
    //后端传给前端的时间格式
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    //前端传给后端的时间格式
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonAlias("create_time")
    private Date createTime;
    @JsonAlias("update_time")
    @TableField(value = "update_time" ,fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

2.自定义元对象处理器

实现 MetaObjectHandler接口

package com.zhuang.mp.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); // 起始版本 3.3.0(推荐使用)
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); // 起始版本 3.3.0(推荐使用)
//        // 或者
//        this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
//        // 或者
//       this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
//        // 或者
//        this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
//        // 或者
//        this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
    }
}

四、分页查询

1.配置类中创建bean

ackage com.zhuang.mp.config;

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

@Configuration
public class MyBatisPlusConfig {
 
   //分页查询
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

2.调用分页查询的方法

    @Resource
    private UserMapper userMapper;
    
    Page<User> userPage = userMapper.selectPage(page, null);

五、多对一映射、一对多映射

举例: 一个老师有多名学生是一对多关系,而一个学生只能有一个老师是多对一关系

1.数据库表设计

设计studen和teacher表, 两个表中的字段命名需要不一样,否则在映射过程中会有问题。

1、student表

java实体类:包含老师属性

package com.zhuang.mp.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import lombok.Data;

import java.io.Serializable;

/**
 * <p>
 * 
 * </p>
 *
 * @author mrzhuang
 * @since 2022-12-21
 */
@ApiModel(value = "Student对象", description = "")
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;
    
    @TableId(type = IdType.AUTO)
    private Integer sid;

    @TableField(value = "s_name")
    private String studentName;

    private Integer tid;

    @TableField(exist = false)
    private Teacher teacher;

}

2、teacher表:

java实体类:

package com.zhuang.mp.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * <p>
 * 
 * </p>
 *
 * @author mrzhuang
 * @since 2022-12-21
 */
@ApiModel(value = "Teacher对象", description = "教师")
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class Teacher implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty("老师id")
    @TableId(value = "t_id", type = IdType.AUTO)
    private Integer tid;

    @ApiModelProperty("老师姓名")
    @TableField(value = "t_name")
    private String teacherName;

    @ApiModelProperty("学生集合")
    @TableField(exist = false)
    private List<Student> studentList;

}

2.多对一映射:association

StudentMapper.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.zhuang.mp.mapper.StudentMapper">

    <resultMap id="stuResultMap" type="Student">
        <id property="sid" column="s_id"/>
        <result property="studentName" column="s_name"/>
        <result property="tid" column="t_id"/>
        <association property="teacher" javaType="teacher">
            <id property="tid" column="t_id"/>
            <result property="teacherName" column="t_name"/>
        </association>
    </resultMap>
    <select id="selectByMap" resultMap="stuResultMap">
        select * from student s left join teacher t on s.t_id = t.t_id

    </select>
</mapper>

StudentMapper类:

package com.zhuang.mp.mapper;

import com.zhuang.mp.entity.Student;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import java.util.List;

/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author mrzhuang
 * @since 2022-12-21
 */
public interface StudentMapper extends BaseMapper<Student> {

       /**
     * 查询所有学生
     * @return /
     */
    List<Student> selectByMap();
}

StudentController:

package com.zhuang.mp.controller;

import com.zhuang.mp.entity.Student;
import com.zhuang.mp.service.IStudentService;
import com.zhuang.mp.vo.ResponseVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author mrzhuang
 * @since 2022-12-21
 */
@RestController
@RequestMapping("/mp/student")
public class StudentController {

    @Resource
    IStudentService studentService;

    @GetMapping("/selectByMap")
    public ResponseVo<List<Student>> selsectByMap(){
        /**
         * 查询所有学生
         */
        List<Student> students = studentService.selectByMap();
        return new ResponseVo<>(students);
    }

}

结果:

3.一对多映射:collection

TeacherMapper.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.zhuang.mp.mapper.TeacherMapper">

    <resultMap id="techResultMap" type="teacher">
        <id property="tid" column="t_id"/>
        <result property="teacherName" column="t_name"/>
        <collection property="studentList" ofType="student">
            <id property="sid" column="s_id"/>
            <result property="studentName" column="s_name"/>
            <result property="tid" column="t_id"/>
        </collection>
    </resultMap>

    <select id="selectByMap" resultMap="techResultMap">
        select * from teacher t right join student s on s.t_id = t.t_id
    </select>
    
</mapper>

TeacherMapper类:

package com.zhuang.mp.mapper;

import com.zhuang.mp.entity.Teacher;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import java.util.List;

/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author mrzhuang
 * @since 2022-12-21
 */
public interface TeacherMapper extends BaseMapper<Teacher> {

    /**
     * 查询全部老师
     * @return
     */
    List<Teacher> selectByMap();
}

TeacherController:

package com.zhuang.mp.controller;

import com.zhuang.mp.entity.Teacher;
import com.zhuang.mp.service.ITeacherService;
import com.zhuang.mp.vo.ResponseVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author mrzhuang
 * @since 2022-12-21
 */
@Api(tags = "教师接口")
@RestController
@RequestMapping("/mp/teacher")
public class TeacherController {
    @Resource
    ITeacherService teacherService;

    @ApiOperation("获得全部的老师")
    @GetMapping("searchAll")
    public ResponseVo<List<Teacher>> searchAll(){
        List<Teacher> teachers = teacherService.searchAll();
        return new ResponseVo<>(teachers);
    }

    @ApiOperation("一对一多映射")
    @GetMapping("/selectByMap")
    public ResponseVo<List<Teacher>> selectByMap(){
        List<Teacher> teachers = teacherService.selectByMap();
        return new ResponseVo<>(teachers);
    }

}

结果:

六、代码生成器

1.maven依赖

        <!--逆向代码生成模版-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

2.代码编写

package com.zhuang.generator;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Collections;

/**
 * @program: mp
 * @description: 逆向代码生成器
 * @author: mrzhuang
 * @create: 2022-12-17 20:56
 **/
public class CodeGenerator {

    public static void main(String[] args) {
        String url = "jdbc:mysql://1.13.152.218:3306/mp?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
        String username = "root";
        String password = "zhuang123";
        String author = "mrzhuang";
        String outputDir = "/Users/mrzhuang/Downloads/mp/generator";
        String parent = "com.zhuang";
        String moduleName = "mp";
        String xmlPath = "/Users/mrzhuang/Downloads/mp/generator";
        //String tablename = "user";
        FastAutoGenerator.create(url, username, password)
                .globalConfig(builder -> {
                    builder.author(author) // 设置作者
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir(outputDir); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent(parent) // 设置父包名
                            .moduleName(moduleName) // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.xml, xmlPath)); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("teacher").addInclude("student"); // 设置需要生成的表名
    //                        .addTablePrefix("t_", "c_"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文