【SpringBoot框架篇】14.mybatis-plus實戰

簡介

Mybatis-Plus(簡稱MP)是一個 Mybatis 的增強工具,在 Mybatis 的基礎上只做增強不做改變,爲簡化開發、提高效率而生。這是官方給的定義,關於mybatis-plus的更多介紹及特性,可以參考mybatis-plus官網。那麼它是怎麼增強的呢?其實就是它已經封裝好了一些crud方法,我們不需要再寫xml了,直接調用這些方法就行,就類似於JPA。

官網地址: https://mybatis.plus/guide/

版本

  • springboot版本是: 2.3.0.RELEASE
  • mybatis-plus-boot-starter的使用的 3.3.2

使用模板生成器生成模板代碼

添加依賴

   <properties>
        <java.version>1.8</java.version>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
    </properties>
    
     <dependencies> 
       <!--MyBatis-Plus 核心依賴 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!-- MyBatis-Plus 從 3.0.3 之後移除了代碼生成器與模板引擎的默認依賴,需要手動添加相關依賴 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!--模板引擎-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        
        <!--生成的模板實體類用到了lombok註解-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
   
    </dependencies>

創建表

CREATE TABLE sys_user (
id int  AUTO_INCREMENT,
username varchar(20) COMMENT '用戶名',
password varchar(20) COMMENT '密碼',
create_time datetime COMMENT '創建時間',
grade   int COMMENT '年紀',
 PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

創建模板實體類的超類

通常會把一些通用的字段放入到超類中

@Data
public class BaseEntity {

    private Integer id;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

}

添加模板生成器代碼

public class MysqlGenerator {

    //生成類的作者描述
    private final static String AUTHOR="LeeJunMing";
    private final static String DATASOURCE_URL="jdbc:mysql://localhost:3306/boot_master?useSSL=false&serverTimezone=GMT%2b8&characterEncoding=utf8&connectTimeout=10000&socketTimeout=3000&autoReconnect=true";
    private final static String DATASOURCE_DRIVER_NAME="com.mysql.cj.jdbc.Driver";
    private final static String DATASOURCE_USERNAME="root";
    private final static String DATASOURCE_PASSWORD="123456";
    //基礎包名
    private final static String BASE_PACKAGE="com.ljm.boot";
    //生成的模塊名稱
    private final static String MODEL_NAME="mybatisplus";
    //超類的字段(不會出現在自動生成的表中)
    private final static String[] SUERP_COLUMN=new String[]{"id","create_time"};
    //要把哪些表生成模板代碼
    private final static String [] GENERATOR_TABLES=new String[]{"sys_user"};

    public static void main(String[] args) {
        // 代碼生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        //聚合工程需要寫工程的名字,普通工程寫 '' 就行
        String parantPath="/14_mybatis-plus";
        gc.setOutputDir(projectPath + parantPath+"/src/main/java");
        gc.setAuthor(AUTHOR);
        gc.setOpen(false);
        mpg.setGlobalConfig(gc);

        // 數據源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(DATASOURCE_URL);
        dsc.setDriverName(DATASOURCE_DRIVER_NAME);
        dsc.setUsername(DATASOURCE_USERNAME);
        dsc.setPassword(DATASOURCE_PASSWORD);
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(MODEL_NAME);
        pc.setParent(BASE_PACKAGE);
        mpg.setPackageInfo(pc);

        // 自定義配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定義輸入文件名稱
                return projectPath + parantPath+"/src/main/java/"+BASE_PACKAGE.replaceAll("\\.","/")+"/" + pc.getModuleName()
                        + "/mapper/xml/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        mpg.setTemplate(new TemplateConfig().setXml(null));

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);

        //設置控制器的超類
        //strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController");

        //設置實體類的超類
        strategy.setSuperEntityClass(BaseEntity.class);
        //設置
        strategy.setInclude(GENERATOR_TABLES);
        strategy.setSuperEntityColumns(SUERP_COLUMN);
        strategy.setControllerMappingHyphenStyle(true);
        mpg.setStrategy(strategy);

        // 選擇 freemarker 引擎需要指定如下加,注意 pom 依賴必須有!
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

}

運行main函數

看到下面的日誌就代表模板文件生成成功了.
在這裏插入圖片描述
會把每個表生成一個controller->service->mapper>xml>entity
生成的結構如下
在這裏插入圖片描述

使用mybatis-plus實現基本的CRUD功能

通用代碼層

下面的代碼會在模板生成器生成模板的時候會自動添加上

service代碼詳解

此處繼承了ServiceImpl通用代碼實現類

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

}

查看ServiceImpl 源碼能看到已經定義了一些通用的代碼

//新增  這個有點迷,我以爲會和Jpa一樣自動判斷添加和修改,這個save只能添加
boolean save(T entity);

//根據id獲取
T getById(Serializable id)

//根據條件查詢
List<T> list(Wrapper<T> queryWrapper)

//分頁查詢
<E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper);

//批量新增 (默認是1000條,可以調用saveBatch(Collection<T> entityList, int batchSize)指定批量操作數量)
boolean saveBatch(Collection<T> entityList)

//添加或者修改
boolean saveOrUpdate(T entity);

//批量添加或者修改
boolean saveOrUpdateBatch(Collection<T> entityList)

//根據ID刪除
removeById(Serializable id)

//根據Id批量刪除
boolean removeByIds(Collection<? extends Serializable> idList)


mapper

此處繼承BaseMappe 接口

public interface SysUserMapper extends BaseMapper<SysUser> {

}

控制器層調用接口

接口採用了RESTful風格

@Controller
@RequestMapping("/user")
public class SysUserController {

    @Autowired
    ISysUserService userService;

    /**
     * 分頁查詢
     */
    @GetMapping("/")
    public String getUserBypage(PageParam<SysUser> pageParam, Model model) {
        pageParam.initialization();
        IPage<SysUser> iPage = userService.page(pageParam.getPage(), pageParam.getQueryWrapper());
        System.out.printf("總頁數:{%d},總記錄數:{%d}", iPage.getPages(), iPage.getTotal());
        model.addAttribute("page", new PageResult<>(iPage));
        return "user/index";
    }

    /**
     * ajax 分頁查詢
     */
    @PostMapping(value = "/json")
    @ResponseBody
    public PageResult getUserJsonDataBypage(@RequestBody PageParam<SysUser> pageParam, Model model) {
        pageParam.initialization();
        IPage<SysUser> iPage = userService.page(pageParam.getPage(), pageParam.getQueryWrapper());
        model.addAttribute("page", new PageResult<>(iPage));
        return new PageResult<>(iPage);
    }


    /**
     * 根據id獲取user,並且跳轉到數據修改頁面
     */
    @GetMapping("/{id}")
    public String getUserById(@PathVariable Integer id, Model model) {
        //id=-1的時候代表着是重添加用戶按鈕進來的請求
        if (id != -1) {
            SysUser user = userService.getById(id);
            model.addAttribute("user", user);
        }
        return "user/save";
    }


    /**
     * 添加用戶
     */
    @PostMapping("/")
    @ResponseBody
    public boolean addUser(SysUser user) {
        return userService.save(user);
    }

    /**
     * 修改用戶
     */
    @PutMapping("/")
    @ResponseBody
    public boolean modifyUser(SysUser user) {
        return userService.saveOrUpdate(user);
    }

    /**
     * 刪除
     */
    @DeleteMapping("/{ids}")
    @ResponseBody
    public boolean deleteUserById(@PathVariable String ids) {
        String idarr[] = ids.split(",");
        if (idarr.length == 1) {
            return  userService.removeById(idarr[0]);
        } else {
            return userService.removeByIds(Arrays.asList(idarr));
        }
    }

}

自定義分頁條件注入器

@Data
public class PageParam<T>  {

    private Integer DEFAULT_PAGE_SIZE=10;

    private Page<T> page;

    //查詢條件構造器
    private QueryWrapper<T> queryWrapper;

    private Integer currentPage;

    private Integer pageSize;

    @JsonFormat(pattern="yyyy-MM-dd",timezone="Asia/Shanghai")
    private Date beginDate;

    @JsonFormat(pattern="yyyy-MM-dd",timezone="Asia/Shanghai")
    private Date endDate;

    private Map<String, Object> eq = new HashMap<>();

    private Map<String, String> like = new HashMap<>();

    /**
     * 構建jpa需要的分頁對象 初始化
     */
    public  void initialization() {
        if(this.currentPage==null){
            this.currentPage=1;
        }
        if(this.pageSize==null){
            this.pageSize=this.DEFAULT_PAGE_SIZE;
        }
        this.page= new Page<>(this.currentPage, this.pageSize);
        this.setCompare();
    }


    /**
     * 注入查詢條件參數
     */
    private void setCompare() {
        this.queryWrapper=new QueryWrapper<>();
        if (!StringUtils.isEmpty(beginDate)) {
            //大於或等於傳入時間
            queryWrapper.ge("create_time",beginDate);
        }
        if (!StringUtils.isEmpty(endDate)) {
            //小於或等於傳入時間
            queryWrapper.le("create_time",beginDate);
        }

        String value = "";
        //注入文本框的模糊查詢參數
        for (Map.Entry<String, String> entry : like.entrySet()) {
            value = entry.getValue().trim();
            if (StringUtils.isEmpty(value)) {
                continue;
            }
            //過濾掉非法的符號,不然會影響模糊查詢
            value = value.replaceAll("%", "////%").replaceAll("_", "////_");
            queryWrapper.like(entry.getKey(),  value );
        }

        //注入下拉框或單選框的等值查詢參數
        for (Map.Entry<String, Object> entry : eq.entrySet()) {
            if (StringUtils.isEmpty(entry.getValue())) {
                continue;
            }
            queryWrapper.eq(entry.getKey(),entry.getValue());
        }
    }
}

頁面查詢條件注入代碼

util.getFromData=function(form) {
    var root={}
    var like={};
    var eq={};

    //注入頁碼和當前頁
    root["currentPage"]=$("[name='currentPage']").val();
    root["pageSize"]=$("[name='pageSize']").val();

    //文本框都用模糊查詢
    form.find("[type='text']").each(function(){
        var value= $(this).val();      //input 值
        var name= $(this).attr('name');
        if(name.indexOf("Date")!=-1){
            //日期字段用root注入
            root[name]=value;
        }else{
            //其它文本字段注入到like參數中
            like[name]=value;
        }
    });

    //單選框 等值匹配
    form.find("[type='radio']:checked").each(function(){
        var value= $(this).val();      //input 值
        var name= $(this).attr('name');
        eq[name]=value;
    });

    //等值匹配
    form.find("select").each(function(){
        var value= $(this).val();
        var name= $(this).attr('name');
        //頁碼信息是用select裝的,所有排除掉
        if(name!="pageSize"){
            eq[name]=value;
        }
    });

    root['eq']=eq;
    root['like']=like;
    return root;
}

var $form=$("form");
$.ajax({
        type: 'post',
        url: url,
        data: JSON.stringify(util.getFromData($form)),
        contentType: "application/json",
        success: function (page){
        
		}, 
        error:function () {
            layer.msg("網絡異常!", {icon: 2, time: 2000});
        }
    });

配套代碼已上傳到github上

github地址: https://github.com/Dominick-Li/springboot-master

該demo已經實現了簡單的CRUD+分頁查詢功能
由於生成模板需要用的freemarker模板引擎,所以頁面的數據渲染也使用的freemarker模板引擎渲染
頁面的ui庫使用的h-ui,官網地址:http://www.h-ui.net/
在這裏插入圖片描述

項目配套代碼

github地址
要是覺得我寫的對你有點幫助的話,麻煩在github上幫我點 Star

【SpringBoot框架篇】其它文章如下,後續會繼續更新。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章