IntelliJ+SpringBoot项目实战(十三)--在SpringBoot中整合Mybatis-plus

news2025/2/22 19:57:14

        mybatis-plus是基于mybatis基础上的增强的持久层框架,也是目前Java项目开发的主流框架。本文介绍在SpringBoot中集成mybtais-plus的方法以及使用mybatis-plus开发增删改查模块。

一、引入mybatis-plus

        在openjweb-core工程中引入mybatis-plus依赖:

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

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.5.2</version>
        </dependency>


        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
            <version>3.5.2</version>
            <scope>compile</scope>
        </dependency>

 在openjweb-sys的application.properties中增加mybatis-plus的配置:

 mybatis-plus.mapper-locations=classpath*:**/mapper/mapping/*.xml

 上面的配置指定mybatis-plus各种映射xml文件路径在mapper/mapping目录下。

 接下来,在openjweb-sys工程的SpringBoot Application增加mapper扫描路径:

package org.openjweb.sys;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = {"org.openjweb"})
@MapperScan(value = {"org.openjweb.b2c.mapper","org.openjweb.core.mapper"})
public class OpenjwebSysApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpenjwebSysApplication.class, args);
    }

}

注意增加@MapperScan注解,用于扫描各模块的*Mapper.xml文件。

二、 配置一个分页、乐观锁拦截器

        乐观锁拦截器用于处理实体类带@Version注解,当实体类的某个字段带@Version注解的时候,修改记录值的时候,乐观锁字段会自动加一。另外拦截器里还指定一个分页拦截器,用于处理mybatis-plus的分页(拦截器程序加到org.openjweb.core.config目录下):

package org.openjweb.core.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@Slf4j
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//如果配置多个插件,切记分页最后添加
        //增加乐观锁拦截器,对应实体类的乐观锁字段可加@Version注解
        log.info("开始增加乐观锁拦截器......................");
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

        //建议单一数据库类型的均设置 dbType
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果有多数据源可以不配具体类型 否则都建议配上具体的DbType

        return interceptor;
    }
}

三、创建数据库表

        以电商系统的区域表b2c_area为例,下面是b2c_area表的结构和示例数据:

CREATE TABLE `b2c_area` (
  `row_id` varchar(40) NOT NULL,
  `sort_no` bigint(20) DEFAULT NULL,
  `create_dt` varchar(23) DEFAULT NULL,
  `update_dt` varchar(23) DEFAULT NULL,
  `create_uid` varchar(32) DEFAULT NULL,
  `update_uid` varchar(32) DEFAULT NULL,
  `data_flg` varchar(6) DEFAULT NULL,
  `obj_name` varchar(40) DEFAULT NULL,
  `master_row_id` varchar(40) DEFAULT NULL,
  `flow_trans_id` varchar(40) DEFAULT NULL,
  `tree_code` varchar(255) DEFAULT NULL,
  `record_version` bigint(20) NOT NULL,
  `flow_status` varchar(16) DEFAULT NULL,
  `area_name` varchar(100) DEFAULT NULL,
  `com_id` varchar(40) DEFAULT NULL,
  `header_name` varchar(60) DEFAULT NULL,
  `area_code` varchar(40) NOT NULL,
  `header_login_id` varchar(40) DEFAULT NULL,
  `logo_path` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`row_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 
INSERT INTO `b2c_area` VALUES ('22391594cb9146219943357c9c072c32', null, '2016-01-08 10:09:28', '2016-01-08 10:09:28', 'admin', 'admin', null, null, null, '1452218968212001020', '001004', '0', null, '南部大区', 'C0001', null, '001004', null, null);
INSERT INTO `b2c_area` VALUES ('3f5fa12464754db2846d835731f4aab0', null, '2016-10-21 16:40:07', '2016-10-21 16:40:07', 'admin', 'admin', null, null, null, '1477039207412001044', '004001', '0', null, '北京', '1413042849626000959', null, '004001', null, null);
INSERT INTO `b2c_area` VALUES ('4d33cce8ce63467cb67f49e55fa74b3b', null, '2016-10-21 16:40:20', '2016-10-21 16:40:20', 'admin', 'admin', null, null, null, '1477039220047001045', '004001001', '0', null, '东城', '1413042849626000959', null, '004001001', null, null);
INSERT INTO `b2c_area` VALUES ('5262c687c02840fb9628d06cf78e44fd', null, '2016-10-21 16:40:29', '2016-10-21 16:40:29', 'admin', 'admin', null, null, null, '1477039229538001046', '005', '0', null, '南方大区', '1413042849626000959', null, '005', null, null);
INSERT INTO `b2c_area` VALUES ('5dce6bc17f104ca6b56d1fb035f08e50', null, '2016-01-08 10:09:39', '2016-01-08 10:09:39', 'admin', 'admin', null, null, null, '1452218979665001021', '001005', '0', null, '北部大区', 'C0001', null, '001005', null, null);
INSERT INTO `b2c_area` VALUES ('6e52918bd77241518e34f2df8fb109bc', null, '2016-01-08 10:00:52', '2016-01-12 18:20:34', 'admin', 'admin', null, null, null, '1452218452615001016', '001', '4', null, '中国', 'C0001', null, '001', null, null);
INSERT INTO `b2c_area` VALUES ('6e57faa77ace4beabddd7234a2c9e5b4', null, '2016-01-12 15:13:42', '2016-01-12 15:13:42', 'admin', 'admin', null, null, null, '1452582822645002994', '002', '0', null, '美国', 'C0001', null, '002', null, null);
INSERT INTO `b2c_area` VALUES ('71e747f78c974804a8dbecac9358a994', null, '2016-10-20 17:06:42', '2016-10-20 17:06:42', 'admin', 'admin', null, null, null, '1476954402747001044', '003', '0', null, '111', '1111', null, '111', null, null);
INSERT INTO `b2c_area` VALUES ('9584de41936246b8a091ac47877e79c7', null, '2016-01-08 10:01:30', '2016-01-12 18:22:38', 'admin', 'admin', 'N', null, null, '1452218490511001017', '001001', '5', '00', '北京大区', 'C0001', null, '001001', null, null);
INSERT INTO `b2c_area` VALUES ('9aad7aacb33f4a02b6d6c96f36e271a0', null, '2016-01-08 10:01:43', '2016-01-08 10:05:54', 'admin', 'admin', null, null, null, '1452218503519001018', '001002', '3', null, '东部大区', 'C0001', null, '001002', null, null);
INSERT INTO `b2c_area` VALUES ('9bdd148bcb7d4bb2bad8509278aa7e20', null, '2016-01-16 08:53:22', '2016-01-16 08:53:22', 'admin', 'admin', null, null, null, '1452905602220001023', '001006', '0', null, '中部大区', 'C0001', null, '001006', null, null);
INSERT INTO `b2c_area` VALUES ('a458530726f84808b043b396ac8402e5', null, '2016-01-08 10:09:15', '2016-01-08 10:09:15', 'admin', 'admin', null, null, null, '1452218955262001019', '001003', '0', null, '西部大区', 'C0001', null, '001003', null, null);
INSERT INTO `b2c_area` VALUES ('d8314ad7352c4f31b9a431706f11be87', null, '2016-10-20 17:06:52', '2016-10-21 16:39:57', 'admin', 'admin', null, null, null, '1476954412353001045', '004', '3', '00', '北方大区', '1413042849626000959', null, '004', null, '/images/b2cArea/dc684e6b62ee4c7d9e3278fe279337e4.jpg');

四、电商模块(openjweb-b2b2c)增加openjweb-core的依赖:

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.openjweb</groupId>
            <artifactId>openjweb-core</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>


    </dependencies>

五、电商模块中增加实体类、参数类、结果类

        实体类:保存数据使用。

        参数类:传递参数使用。

        结果类:返回查询结果,如果结果集和表结构不是一一对应的,可自定义结果类。

       在电商模块的org.openjweb.b2c.entity下创建实体类:

     


import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;

@Data
@TableName("b2c_area")
public class B2cArea implements Serializable {
    //销售地区实体类
    // Fields
    //@Id ---这个删除的时候没反应
    @TableId(type = IdType.ASSIGN_UUID)
    private String rowId;
    private Long sortNo;

    @TableField(fill = FieldFill.INSERT)
    private String createDt;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateDt;

    @TableField(fill = FieldFill.INSERT)
    private String createUid;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateUid;
    private String dataFlg;
    private String objName;
    private String masterRowId;
    private String flowTransId;
    private String treeCode;

    @Version
    private Long recordVersion = 0L;//因为是非空,所以试着给一个初始值
    private String flowStatus;
    private String areaName;
    private String comId;
    private String headerName;
    private String areaCode;
    private String headerLoginId;

    private String logoPath;

}

         注意在上面的代码中使用了ID生成方式、FieldFill.INSERT 用于插入时自动设置创建日期和创建人,FieldFill.INSERT_UPDATE 用于插入或修改时自动设置修改日期和修改人。这个后面会做详细介绍。

        接下来在org.openjweb.b2c.module.params下创建一个参数类,参数类主要用于API接口方法中从前端接收参数、API向Service方法中传递参数等,下面是代码:

        

package org.openjweb.b2c.module.params;

import lombok.Data;
import org.openjweb.b2c.entity.B2cArea;


@Data
public class B2cAreaParam extends B2cArea {

    private Integer page=1; //当前页
    private Integer pageSize=10;//每页行数

    public B2cAreaParam() {
        page = 1;
        pageSize = 10;
    }
}

   在参数类中除了继承B2cArea,另外增加了当前页面、每页行数。

   接下来再增加一个结果类:

package org.openjweb.b2c.module.result;

import lombok.Data;

import java.io.Serializable;

@Data
public class B2cAreaResult implements Serializable {
    private String comId;
    private String rowId;
    private String areaName;
}

         B2cAreaResult也可以从B2cArea继承并添加其他字段,本例为了演示,此类仅定义了3个字段用于演示。

六、Mapper.xml、Mapper类、Service类、API接口类

        接下来我们需要开发针对B2cArea的Mapper映射xml文件,B2cAreaMapper.xml,在前面我们指定了Mapper.xml存放路径为mapper/mapping, 所以我们在org.openjweb.b2c.mapper.mapping下创建一个B2cAreaMapper.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="org.openjweb.b2c.mapper.B2cAreaMapper">
    <select id="selectPageWithCondition" resultType="org.openjweb.b2c.entity.B2cArea"  >
        select *  from b2c_area where 1=1
        <where>
            <if test="param.comId !=null and param.comId!=''">
                and com_id = #{param.comId}
            </if>
        </where>
    </select>
    <select id="selectPageWithCondition2" resultType="org.openjweb.b2c.module.result.B2cAreaResult"  >
        select *  from b2c_area where 1=1
        <where>
            <if test="param.comId !=null and param.comId!=''">
                and com_id = #{param.comId}
            </if>
        </where>
    </select>
</mapper>

          注意上面的XML中,org.openjweb.b2c.mapper.B2cAreaMapper是对应的同名的B2cAreaMapper类,此类的代码如下:

package org.openjweb.b2c.mapper;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.openjweb.b2c.entity.B2cArea;
import org.openjweb.b2c.module.params.B2cAreaParam;
import org.openjweb.b2c.module.result.B2cAreaResult;

@Mapper
public interface B2cAreaMapper extends BaseMapper<B2cArea> {

    IPage<B2cArea> selectPageWithCondition(Page<?> page, @Param("param") B2cAreaParam condition);
    IPage<B2cAreaResult> selectPageWithCondition2(Page<?> page, @Param("param") B2cAreaParam condition);

    @Select("SELECT * FROM b2c_area WHERE row_id = #{rowId}")
    B2cArea selectByRowId(@Param("rowId") String rowId);
}

        另外xml中,<select id="xx"> id引号中的是B2cAreaMapper类的方法名。resultType是返回值的类型,在此示例中,一个返回B2cArea,一个返回B2cAreaResult。另外B2cAreaMapper中,@Param 可以传递对象类型的变量,在xml中通过param.字段名引用。@Param("param")引号中的param在xml中通过#{param.comId}引用。selectByRowId方法演示了直接在注解里使用select语句的方式。

        接下来再开发service类B2cAreaService.java:

        

package org.openjweb.b2c.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.openjweb.b2c.entity.B2cArea;
import org.openjweb.b2c.mapper.B2cAreaMapper;
import org.openjweb.b2c.module.params.B2cAreaParam;
import org.openjweb.b2c.module.result.B2cAreaResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;

@Configuration
@EnableAsync
@Service
public class B2cAreaService extends ServiceImpl<B2cAreaMapper, B2cArea> {

    @Autowired
    private B2cAreaMapper b2cAreaMapper;

    public IPage<B2cArea> list(B2cAreaParam param) {
        //http://localhost:8001/api/b2c/area?comId=C0001
        Page<B2cArea> page = new Page<>(param.getPage(), param.getPageSize());

        return b2cAreaMapper.selectPageWithCondition(page,param);

    }

    public IPage<B2cAreaResult> list2(B2cAreaParam param) {

        //http://localhost:8001/api/b2c/area?comId=C0001
        Page<B2cAreaResult> page = new Page<>(param.getPage(), param.getPageSize());

        return b2cAreaMapper.selectPageWithCondition2(page,param);
    }

    public B2cArea getObject(String rowId){
        QueryWrapper<B2cArea> wrapper = new QueryWrapper<B2cArea>();
        wrapper.eq("row_id",rowId);
        B2cArea ent = this.b2cAreaMapper.selectOne(wrapper);
        //另外一种查询方式
        B2cArea ent1  = this.b2cAreaMapper.selectByRowId(rowId);
        if(ent1!=null){
            //输出区域名称
            System.out.println(ent1.getAreaName());
        }
        return ent;
    }

    public void del(String selectedIds) throws  Exception {
        String[] ids = null;
        int delCount = 0;
        if(selectedIds!=null&&selectedIds.trim().length()>0){
            ids = selectedIds.split(",");
            //System.out.println(ids.length);
            List<String> parmList = Arrays.asList(ids);
            delCount = this.b2cAreaMapper.deleteBatchIds(parmList);
        }
        if(delCount==0){
            throw new  Exception ("删除失败!");
        }
    }



}

        在service 类中,selectPageWithCondition和selectPageWithCondition2是自定义的方法,具体sql在B2cAreaMapper.xml中定义了。另外代码里的this.b2cAreaMapper.selectOne、deleteBatchIds是BaseMapper中封装的方法。Mybatis-plus的BaseMapper还封装了很多别的方法,具体可参考mybatis-plus官方网站:MyBatis-Plus 🚀 为简化开发而生MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。icon-default.png?t=O83Ahttps://baomidou.com/

    另外注意extends ServicieImpl后面两个类,一个是Mapper,一个是实体类。 

    接下来再开发一个接口类B2cAreaApi.java:

    

package org.openjweb.b2c.api;


import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.openjweb.b2c.entity.B2cArea;
import org.openjweb.b2c.module.params.B2cAreaParam;
import org.openjweb.b2c.service.B2cAreaService;
import org.openjweb.common.response.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/b2c/b2carea/")
@Slf4j
public class B2cAreaApi {
    //http://localhost:8001/api/b2c/b2carea/edit?rowId=22391594cb9146219943357c9c072c32

    @Autowired
    B2cAreaService b2cAreaService;

    @RequestMapping("/edit")
    public ResponseResult edit(B2cAreaParam param){

        B2cArea ent = this.b2cAreaService.getObject(param.getRowId());
        return ResponseResult.okResult(ent);

    }

    /**
     * 根据页面上选择的ID批量删除
     * @param selectedIds
     * @return
     */
    @RequestMapping("/del")
    public ResponseResult del( String selectedIds){
        //http://localhost:8001/api/b2c/b2carea/del?selectedIds=12,133
        try{
            this.b2cAreaService.del(selectedIds);
            return ResponseResult.okResult(0,"删除成功!");
        }
        catch(Exception ex){
            ex.printStackTrace();
            return ResponseResult.errorResult(-1,"删除失败!");
        }
    }

    @RequestMapping("/save")
    public ResponseResult save( B2cAreaParam param){
        try {
            log.info("新增记录调用开始..........");
            //http://localhost:8001/api/b2c/b2carea/save?areaCode=8888888&areaName=9999&recordVersion=0
            //没配乐观锁插件的时候,record_version必须手工赋值
            //http://localhost:8001/api/b2c/b2carea/save?areaCode=8888888&areaName=121212
            //param.setCreateDt(StringUtil.getCurrentDateTime());
            //param.setUpdateDt(StringUtil.getCurrentDateTime());
            //param.setCreateUid("system");
            //param.setUpdateUid("system");
            this.b2cAreaService.save(param);
            log.info("新增记录调用结束..........");
            return ResponseResult.okResult(0,"新增成功!");
        }
        catch(Exception  ex){
            ex.printStackTrace();
            return ResponseResult.errorResult(-1,"新增失败!");
        }

    }
    //http://localhost:8001/api/b2c/b2carea/save2?rowId=22391594cb9146219943357c9c072c32&token=admin111
    @RequestMapping("/save2")
    public ResponseResult save2( B2cAreaParam param){
        try {
            String rowId = param.getRowId();
            log.info("根据rowId查询实体开始..........");
            B2cArea ent = this.b2cAreaService.getObject(rowId);
            log.info("根据rowId查询实体结束,开始保存..........");
            if(ent!=null) {
                log.info("修改名字.....");
                ent.setAreaName("南部大区22223333");
                ent.setUpdateUid(null);//得重置下才自动填充
                ent.setUpdateDt(null);得重置下才自动填充 2024-02-05 11:28:40


            }
            else{
                log.info("没找到实体类.....");

            }
            this.b2cAreaService.updateById(ent);
            log.info("保存完毕..........");
        }
        catch(Exception  ex){
            ex.printStackTrace();
            return ResponseResult.errorResult(-1,"新增失败!");
        }
        return ResponseResult.okResult(0,"success");

    }

    @RequestMapping("/save3")
    public ResponseResult save3( B2cAreaParam param){
        //http://localhost:8001/api/b2c/b2carea/save3?rowId=a458530726f84808b043b396ac8402e5&areaCode=new1&areaName=newname2&recordVersion=5
        try {

            this.b2cAreaService.updateById(param);
        }
        catch(Exception  ex){
            ex.printStackTrace();
            return ResponseResult.errorResult(-1,"修改失败!");
        }
        return ResponseResult.okResult(0,"success");

    }

    @RequestMapping("/area")
    public ResponseResult testArea( B2cAreaParam param){

        IPage<B2cArea> page = this.b2cAreaService.list(param);
        return ResponseResult.okResult(page.getRecords());
    }

}

上面的API接口演示了增删改查的例子。其中查询API的链接为:

http://localhost:8001/api/b2c/b2carea/edit?rowId=22391594cb9146219943357c9c072c32

界面返回:

其他链接在代码中有,大家可自行测试。

六、实体类注解

        实体类注解有自动填充、乐观锁等注解,需要配置一个mybatis的MetaObjectHandler,在org.openjweb.core.mybatisplus.handler下创建一个MyNetaObjectHandler类:

package org.openjweb.core.mybatisplus.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 org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        String dt = String.valueOf(System.currentTimeMillis());
        this.strictInsertFill(metaObject, "createDt", String.class, dt);
        this.strictInsertFill(metaObject, "updateDt", String.class, dt);
        //设置创建人
        String userId = getCreateUid();
        // 根据实际字段名填充
        log.info("插入填充............,:"+userId);
        this.strictInsertFill(metaObject, "createUid", String.class, userId);
        this.strictInsertFill(metaObject, "updateUid", String.class, userId);

    }

    @Override
    public void updateFill(MetaObject metaObject) {

        this.strictUpdateFill(metaObject, "updateDt", String.class, String.valueOf(System.currentTimeMillis()));

        String userId = getCreateUid();
        log.info(userId);
        this.strictUpdateFill(metaObject, "updateUid", String.class, userId );
    }

    private String getCreateUid() {
        // 这里获取当前登录用户的逻辑,根据实际情况实现
        //怎样才能在这里获取到用户信息
        //怎样在MyMetaObjectHandler获取当前用户
        //怎样在MyMetaObjectHandler获取认证token
        //采用下面的方式获取request,然后从request的header中获取token
        String token = "";
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            token = request.getHeader("token");
            if(StringUtils.isEmpty(token)){
                token = request.getParameter("token");
            }

            // 你可以在这里使用request对象
        }
        //log.info("token::::");
        //log.info(token);
        return "abao2222";
    }

}

在实体类注解中:

@TableId(type=IdType.ASSIGN_UUID) 是指定主键字段为32为UUID;

@TableId(type=IdType.ASSIGN_ID) 是指定主键字段为LONG型随机数字;

@Version 是乐观锁的注解,上文中有乐观锁对应的拦截器。如果乐观锁字段是非空字段,可指定一个默认值: private Long recordVersion = 0L;

FieldFill.INSERT 是插入设置默认值,FieldFill.INSERT_UPDATE是插入和修改都要设置默认值。在上面的程序代码中,插入触发默认值设置,设置创建日期和修改日期:

this.strictInsertFill(metaObject, "createDt", String.class, dt);
this.strictInsertFill(metaObject, "updateDt", String.class, dt);

插入设置创建人和修改人:

this.strictInsertFill(metaObject, "createUid", String.class, userId);
this.strictInsertFill(metaObject, "updateUid", String.class, userId);

        另外创建人和修改人可在getCreateUid()中从request中的获取,一般不管是SpringSecurity还是JWT还是Shrio都可以从request中解析到当前登录用户。具体需要在后面整合了登录框架后再完善这个地方。

        下面演示插入新记录后,检查创建人、创建日期、修改人、修改日期、row_id主键字段是否有值。修改记录看record_version是否自动加1。

http://localhost:8001/api/b2c/b2carea/save?areaCode=ABCD&areaName=beifangdaqu

 

查询数据库中新增了记录。

再检查下修改记录时是否record_version自动加1(B2cAreaApi的save2方法是根据row_id修改记录的方法),上面示例返回的row_id的值是ae7930e3f0708a523c4bd40fc7a53e9d:

http://localhost:8001/api/b2c/b2carea/save2?rowId=ae7930e3f0708a523c4bd40fc7a53e9d 

执行后再查询数据库,record_version由原来的0变为1,area_name的值也修改成功:

七、总结

       本文介绍了基于Mybatis-plus开发增删改查功能的完整示例,其中包括mybatis-plus分页的实现方式,以及使用注解实现字段的默认值填充。相信本文对刚上手学习mybatis-plus的朋友会有所帮助。另外因为基于mybatis或mybatis-plus需要开发的相关类比较多,除了必须的API和Service,还需要mapper类、Mapper.xml、实体类、参数类、结果类等,比JdbcTemplate()的开发方式可以说复杂不少,所以在实际项目开发时,最好再开发一个代码生成器,这样可以大幅度提高开发效率。

        本文的示例代码可从 github下载,下载地址:

https://github.com/openjweb/cloud/tree/mastericon-default.png?t=O83Ahttps://github.com/openjweb/cloud/tree/master

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2247121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vector底层实现详解

一、vector的介绍 vector是表示可变大小数组的序列容器 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且…

【2024 Optimal Control 16-745】【Lecture4】equality-constraints.ipynb功能分析

代码实现了一个二次优化问题的可视化解法&#xff0c;包括目标函数、约束以及优化路径。提供了两种优化方法&#xff1a;牛顿法和高斯-牛顿法&#xff0c;用于对比效果。利用了自动微分工具 ForwardDiff 来计算约束曲率。 环境初始化并导入依赖库 # 激活当前文件夹下的项目环境…

【国产MCU】-GD32F470-串行外设接口(SPI)

串行外设接口(SPI) 文章目录 串行外设接口(SPI)1、SPI介绍1.1 SPI特性1.2 SPI信号1.3 SPI 时序和数据帧格式1.4 NSS 功能1.5 SPI运行模式2、SPI控制器寄存器列表3、SPI控制器驱动API介绍4、SPI应用4.1 SPI初始化流程4.2 数据发送与接收串行外设接口(Serial Peripheral Int…

Docker安装ubuntu1604

首先pull镜像 sudo docker run -d -P m.daocloud.io/docker.io/library/ubuntu:16.04国内使用小技巧&#xff1a; https://github.com/DaoCloud/public-image-mirror pull完成之后查看 sudo docker images 运行docker sudo docker run -d -v /mnt/e:/mnt/e m.daocloud.io/…

2024 年:Kubernetes 包管理的新前沿

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;历代文学&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编程&#xff0c;高并发设计&#xf…

飞凌嵌入式T113-i开发板RISC-V核的实时应用方案

随着市场对嵌入式设备的功能需求越来越高&#xff0c;集成了嵌入式处理器和实时处理器的主控方案日益增多&#xff0c;以便更好地平衡性能与效率——实时核负责高实时性任务&#xff0c;A核处理复杂任务&#xff0c;两核间需实时交换数据。然而在数据传输方面&#xff0c;传统串…

VSCode 汉化教程【简洁易懂】

VSCode【下载】【安装】【汉化】【配置C环境&#xff08;超快&#xff09;】&#xff08;Windows环境&#xff09;-CSDN博客 我们安装完成后默认是英文界面。 找到插件选项卡&#xff0c;搜索“Chinese”&#xff0c;找到简体&#xff08;更具你的需要&#xff09;&#xff08;…

【Mac】VMware Fusion Pro 安装 CentOS 7

1、下载镜像 CentOS 官网阿里云镜像网易镜像搜狐镜像 Mac M1芯片无法直接使用上述地址下载的最新镜像&#xff08;7.9、9&#xff09;&#xff0c;会一直卡在安装界面&#xff08;在 install 界面按 enter 回车无效&#xff09;&#xff0c;想要使用需要经过一系列操作&#…

运维Tips:Docker或K8s集群拉取Harbor私有容器镜像仓库配置指南

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] Docker与Kubernetes集群拉取Harbor私有容器镜像仓库配置 描述&#xff1a;在现在微服务、云原生的环境下&#xff0c;通常我们会在企业中部署Docker和Kubernetes集群&#xff0c;并且会在企业内部…

C语言笔记(自定义类型:结构体、枚举、联合体 )

前言 本文对自定义类型的结构体创建、使用、结构体的存储方式和对齐方式&#xff0c;枚举的定义、使用方式以及联合体的定义、使用和存储方式展开叙述&#xff0c;如有错误&#xff0c;请各位指正。 目录 前言 1 结构体 1.1 结构体的声明 1.2 结构体的自引用 1.3 结构体变…

string的实际应用 -- 大数相加 、大数相乘

前言&#xff1a;哎&#xff0c;做题好难o(╥﹏╥)o&#xff0c;有时候想不到&#xff0c;而有时候则是想到了却没办法理清思路&#xff0c;转化为代码。有必要反思了┓(;_&#xff40;)┏&#xff0c;是否是做的太少了&#xff0c;或是自己的基础欠缺。 大学总是有些迷茫~ ​​…

STM32-- keil 的option for target使用

keil版本号 1.device界面 如&#xff1a;stm32f103c8t6的工程&#xff0c;可以直接在device这里修改成stm32f103vct6&#xff0c;虽然引脚不一样&#xff0c;但是很多一样的地方&#xff0c;可以直接使用&#xff0c;有些不修改也可以下载程序。 2.target xtal的设置不起作用了…

shell脚本9完结,保姆篇---春不晚

免责声明 学习视频来自 B 站up主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下代码、网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 泷羽sec官网&#xff1a;http…

【数据分享】2024年我国省市县三级的住宿服务设施数量(8类住宿设施/Excel/Shp格式)

宾馆酒店、旅馆招待所等住宿服务设施的配置情况是一个城市公共基础设施完善程度的重要体现&#xff0c;一个城市住宿服务设施种类越丰富&#xff0c;数量越多&#xff0c;通常能表示这个城市的公共服务水平越高&#xff01; 本次我们为大家带来的是我国各省份、各地级市、各区…

RabbitMQ和RocketMQ相关面试题

RabbitMQ和RocketMQ面试题 RabbitMQ1.RabbitMQ各部分角色2.如何确保RabbitMQ消息的可靠性&#xff1f;3.什么样的消息会成为死信&#xff1f;4.死信交换机的使用场景是什么&#xff1f;5.TTL6.延迟队列7.消息堆积问题8.MQ集群 RocketMQ1.RocketMQ各部分角色2.RocketMQ如何保证高…

在kali用msfpc远程控制Windows

本次实验我们将使用msfpc生成windows下的被控端&#xff0c;并使用metasploit渗透工具进行远程控制。 一、实验环境 Windows主机IP&#xff1a; 192.168.167.1 虚拟机Kali IP&#xff1a; 192.168.167.100 二、实验过程 1、安装msfpc apt-get install msfpc 2、生成windows…

SDIO WIFI模组Clock EMC问题

问题&#xff1a; 某产品采用SDIO3.0的WIFI模组&#xff0c;测试3米场地辐射出现333MHz和500MHz频点超标。 分析&#xff1a; 1、一开始分析板子上没有对应333MHz,499.5MHz的频点倍频&#xff0c;因此直接拔掉产品上所有的外部接线&#xff0c;测试还是超标。表明辐射源头出…

MCU(一) 时钟详解 —— 以 GD32E103 时钟树结构为例

微控制器 (MCU) 的时钟系统是系统运行的核心&#xff0c;它提供了各模块所需的时钟信号。本文以 GD32E103 系列 MCU 为例&#xff0c;详细讲解其 时钟树结构&#xff08;Clock Tree&#xff09;。通过理解时钟源、分配与预分频器设置&#xff0c;可以灵活配置系统时钟以实现高性…

【方案库】从单张照片快速重建3D场景:Flash3D详解

一、Flash3D是什么? Flash3D 是一项革命性的AI技术,能够从单张普通照片快速重建3D场景。简单来说,你只需要提供一张照片,Flash3D 就能帮你还原出这个场景的立体效果。这项技术在房地产、建筑设计、虚拟现实等多个领域都有着广泛的应用前景。 二、主要特点 一张就够:只需…

QT QFormLayout控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例&#xff0c;包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizonta…