MyBatis-Plus入門,看這一篇就足夠了

文章設計源代碼和筆記:gitee

一、MyBatis-Plus

簡介

MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,爲簡化開發、提高效率而生。

我們的願景是成爲 MyBatis 最好的搭檔,就像 魂鬥羅 中的 1P、2P,基友搭配,效率翻倍。

特性

  • 無侵入:只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑
  • 損耗小:啓動即會自動注入基本 CURD,性能基本無損耗,直接面向對象操作
  • 強大的 CRUD 操作:內置通用 Mapper、通用 Service,僅僅通過少量配置即可實現單表大部分 CRUD 操作,更有強大的條件構造器,滿足各類使用需求
  • 支持 Lambda 形式調用:通過 Lambda 表達式,方便的編寫各類查詢條件,無需再擔心字段寫錯
  • 支持主鍵自動生成:支持多達 4 種主鍵策略(內含分佈式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問題
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式調用,實體類只需繼承 Model 類即可進行強大的 CRUD 操作
  • 支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 內置代碼生成器:採用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用
  • 內置分頁插件:基於 MyBatis 物理分頁,開發者無需關心具體操作,配置好插件之後,寫分頁等同於普通 List 查詢
  • 分頁插件支持多種數據庫:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種數據庫
  • 內置性能分析插件:可輸出 Sql 語句以及其執行時間,建議開發測試時啓用該功能,能快速揪出慢查詢
  • 內置全局攔截插件:提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規則,預防誤操作

支持數據庫

  • mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver 、 presto
  • 達夢數據庫 、 虛谷數據庫 、 人大金倉數據庫

框架結構

代碼託管

Gitee | Github

二、快速入門

地址:https://mp.baomidou.com/guide/quick-start.html#初始化工程

使用第三方組件

  1. 導入對應依賴
  2. 研究依賴配置
  3. 代碼如何編寫
  4. 提高擴展技術能力!

步驟

  1. 創建數據庫mybatis_plus
  2. 創建user表,插入數據
DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主鍵ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年齡',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '郵箱',
	PRIMARY KEY (id)
);

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
  1. 編寫項目,初始化項目! 使用SpringBoot初始化!
  2. 導入依賴
<dependency>
    <groupId>org.springframework.boot</groupI
    <artifactId>spring-boot-starter-web</arti
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupI
    <artifactId>spring-boot-starter-test</art
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</group
            <artifactId>junit-vintage-engine<
        </exclusion>
    </exclusions>
</dependency>
<!--數據庫驅動-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifac
    <version>8.0.20</version>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>
<!--mybatis-plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</ar
    <version>3.3.1</version>
</dependency>

說明:我們使用mybatis-plus可以節省大量代碼,儘量不要同時導入mybatis和mybatis-plus!版本差異!

  1. 配置數據庫,和mybatis一樣
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?userSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.username=mybatis_plus
spring.datasource.password=mybatis_plus123
  1. 在 Spring Boot 啓動類中添加 @MapperScan 註解,掃描 Mapper 文件夾:
@MapperScan("com.godfrey.mapper")
@SpringBootApplication
public class MybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }

}
  1. 編碼

編寫實體類 User.java

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

編寫Mapper類 UserMapper.java

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

8.使用

添加測試類,進行功能測試:

@SpringBootTest
class MybatisPlusApplicationTests {

    @Resource
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        //查詢全部用戶
        //參數是一個Wrapper,條件構造器
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

控制檯輸出:

User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)

小結

通過以上幾個簡單的步驟,我們就實現了 User 表的 CRUD 功能,甚至連 XML 文件都不用編寫!

從以上步驟中,我們可以看到集成MyBatis-Plus非常的簡單,只需要引入 starter 工程,並配置 mapper 掃描路徑即可。

三、配置日誌

# 配置日誌
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

四、CRUD擴展

插入操作

//測試插入
@Test
public void testInsert(){
    User user = new User();
    user.setName("淮城一隻貓");
    user.setAge(5);
    user.setEmail("[email protected]");
    int result = userMapper.insert(user); //自動生成id
    System.out.println(result); //受影響的行數
    System.out.println(user); //發現id自動回填
}

數據庫插入的id默認是全局唯一id

主鍵生成策略

默認ID_WORKER,全局唯一id

分佈式系統唯一id生成方案彙總

雪花算法:

snowflake是Twitter開源的分佈式ID生成算法,結果是一個long型的ID。其核心思想是:使用41bit作爲毫秒數,10bit作爲機器的ID(5個bit是數據中心,5個bit的機器ID),12bit作爲毫秒內的流水號(意味着每個節點在每毫秒可以產生 4096 個 ID),最後還有一個符號位,永遠是0。可以保證幾乎全球唯一!

主鍵自增

我們需要配置註解自增:

  1. 實體類字段上:@TableId(type = IdType.AUTUO)
  2. 數據庫字段一定要自增

3.再次測試插入即可!

其餘的策略解釋

public enum IdType {
    AUTO(0), //id自增
    NONE(1), //未設置主鍵
    INPUT(2), //手動輸入
    ID_WORKER(3), //默認值,全局唯一id
    UUID(4), //全局唯一id,uuid
    ID_WORKER_STR(5); //ID_WORKER的字符串表示法
}

更新操作

//測試更新
@Test
public void testUpdate(){
    User user = new User();
    user.setId(6L);
    user.setName("我的博客叫:淮城一隻貓");
    user.setAge(6);
    user.setEmail("[email protected]");
    //注意:updateById參數是一個對象
    int result = userMapper.updateById(user); //自動生成id
    System.out.println(result); //受影響的行數
}

自動填充

創建時間、修改時間!這些操作一般自動化完成的,我們不希望手動更新!

阿里巴巴開發手冊:所有的數據庫表:gmt_create、gmt_modified幾乎所有表都要配置上!而且需要自動化!

方式一:數據庫級別(工作中不建議這麼做)

  1. 在表中新增字段create_time、update_time

  1. 再次測試插入方法,需要先把實體類同步!
private Date creteTime;
private Date updateTime;

方式二:代碼級別

  1. 輸出數據庫中的默認值、更新操作

  1. 在實體類字段屬性上需要註釋
//字段添加填充內容
@TableField(fill = FieldFill.INSERT)
private Date creteTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
  1. 編寫處理器處理註解!
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler{
    //插入時填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //更新時填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}
  1. 測試插入
  2. 測試更新、觀察時間即可!

樂觀鎖

樂觀鎖:顧名思義樂觀,它總是認爲不會出現問題,無論幹什麼都不去上鎖!如果出現問題,再次更新值測試

悲觀鎖:顧名思義悲觀,它總是認爲會出現問題,無論幹什麼都會加上鎖!再去操作

樂觀鎖實現方式:

  • 取出記錄時,獲取當前version
  • 更新時,帶上這個version
  • 執行更新時, set version = newVersion where version = oldVersion
  • 如果version不對,就更新失敗

測試MP樂觀鎖插件

  1. 數據庫中添加version字段!

  1. 實體類添加對應字段
@Version  //樂觀鎖註解
private Integer version;
  1. 註冊組件
@MapperScan("com.godfrey.mapper")
@EnableTransactionManagement  //自動管理事務(默認也是開啓的)
@Configuration  //配置類
public class MybaitsPlusConfig {

    //註冊樂觀鎖插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
  1. 測試一下
//測試樂觀鎖成功!
@Test
public void testOptimisticLocker1() {
    //1.查詢用戶信息
    User user = userMapper.selectById(1L);
    //2.修改用戶信息
    user.setName("godfrey");
    user.setEmail("[email protected]");
    //3.執行更新操作
    userMapper.updateById(user);
}


//測試樂觀鎖失敗!多線程下
@Test
public void testOptimisticLocker2() {
    //線程1
    User user1 = userMapper.selectById(1L);
    user1.setName("godfrey111");
    user1.setEmail("[email protected]");

    //模擬另外一個線程執行插隊操作
    User user2 = userMapper.selectById(1L);
    user2.setName("godfrey222");
    user2.setEmail("[email protected]");
    userMapper.updateById(user2);

    //自旋鎖多次操作嘗試提交
    userMapper.updateById(user1);
}

查詢操作

//測試查詢
@Test
public void testSelectById() {
    User user = userMapper.selectById(1L);
    System.out.println(user);
}

//測試批量查詢
@Test
public void testSelectByBatchId() {
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
    users.forEach(System.out::println);
}

//條件查詢之一 使用map操作
@Test
public void testSelectBatchIds() {
    HashMap<String, Object> map = new HashMap<>();
    //自定義查詢
    map.put("name","Tom");
    map.put("age",28);

    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

分頁查詢

分頁在網站中使用非常多!

  1. 原始limit進行分頁
  2. pageHelper第三方插件
  3. MP其實也內置了分頁插件

如何使用?

  1. 配置分頁插件
//分頁插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}
  1. 直接使用Page對象即可!
//測試分頁查詢
@Test
public void testPage() {
    //參數一:當前頁
    //參數二:頁面大小
    //使用了分頁插件之後,所有的分頁操作頁變得簡單了
    Page<User> page = new Page<>(1,5);
    userMapper.selectPage(page,null);

    page.getRecords().forEach(System.out::println);
    System.out.println(page.getTotal());
}

刪除操作

基本的刪除操作

//通過id刪除
@Test
public void testDeleteById() {
    userMapper.deleteById(8L);
}

//通過id批量刪除
@Test
public void testDeleteBatchId() {
    userMapper.deleteBatchIds(Arrays.asList(6L, 7L));
}

//通過map刪除
@Test
public void testDeleteMap() {
    HashMap<String, Object> map = new HashMap<>();
    map.put("name", "godfrey");
    userMapper.deleteByMap(map);
}

我們在工作中會遇到一些問題:邏輯刪除!

邏輯刪除

物理刪除:從數據庫中直接移除

邏輯刪除:在數據庫中沒有被移除,而是通過一個變量來讓他失效!delete=0 => delete=1

管理員可以查看被刪除的記錄!防止數據的丟失,類似於回收站!

測試一下:

  1. 在數據表中增加deleted字段

  1. 實體類中同步屬性
//邏輯刪除字段
private Integer deleted;
  1. 配置
# 配置邏輯刪除
mybatis-plus.global-config.db-config.logic-delete-field=deleted # 全局邏輯刪除的實體字段名
mybatis-plus.global-config.db-config.logic-delete-value=1 # 邏輯已刪除值(默認爲 1)
mybatis-plus.global-config.db-config.logic-not-delete-value=0 # 邏輯未刪除值(默認爲 0)
  1. 測試一下刪除

以上的所有CRUD操作及其擴展操作,我們都必須精通掌握!會大大提高工作和寫項目效率

性能分析插件

我們在開發中,會遇到一些慢sql,我們有必要把它揪出來 。測試!druid…

MP也提供性能分析插件,如果超過這個時間就停止運行!官方3.1.0以上版本推薦使用p6spy!

  1. 導入依賴
<!--p6spy性能分析插件-->
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.0</version>
</dependency>
  1. 修改數據庫連接配置
# 數據庫連接配置
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/mybatis_plus?userSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
  1. 新建spy.properties 並設置參數
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定義日誌打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日誌輸出到控制檯
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日誌系統記錄 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 設置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前綴
useprefix=true
# 配置記錄 Log 例外,可去掉的結果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式gui
dateformat=yyyy-MM-dd HH:mm:ss
# 實際驅動可多個
#driverlist=org.h2.Driver
# 是否開啓慢SQL記錄
outagedetection=true
# 慢SQL記錄標準 2 秒
outagedetectioninterval=2
  1. 測試使用!(只要超過了規定時間就會拋出異常)

注意,插件會影響性能,建議開發和測試環境下使用

條件構造器

  1. 測試一
@Test
void test1() {
    //查詢name不爲空的用戶,並且郵箱不爲空的,年齡大於等於12
    QueryWrapper<User> wapper = new QueryWrapper<>();
    wapper.isNotNull("name")
            .isNotNull("email")
            .ge("age", 12);
    userMapper.selectList(wapper).forEach(System.out::println);
}
  1. 測試二
@Test
void test2() {
    //查詢名字爲Tom
    QueryWrapper<User> wapper = new QueryWrapper<>();
    wapper.eq("name","Tom");
    User user = userMapper.selectOne(wapper);
    System.out.println(user);
}
  1. 測試三
//範圍查詢
@Test
void test3() {
    //查詢年齡在20~30歲之間的用戶
    QueryWrapper<User> wapper = new QueryWrapper<>();
    wapper.between("age", 20, 30);//區間
    System.out.println(userMapper.selectCount(wapper));//查詢結果數
}
  1. 測試四
//模糊查詢
@Test
void test4() {
    //查詢名字有
    QueryWrapper<User> wapper = new QueryWrapper<>();
    wapper.notLike("name","e")//%e%
            .likeRight("email","t");//t%
    List<Map<String, Object>> maps = userMapper.selectMaps(wapper);
    maps.forEach(System.out::println);
}
  1. 測試五
//子查詢
@Test
void test5() {
    QueryWrapper<User> wapper = new QueryWrapper<>();
    //id在子查詢中查出來
    wapper.inSql("id","select id from user where id<3");
    List<Object> objects = userMapper.selectObjs(wapper);
    objects.forEach(System.out::println);
}
  1. 測試六
//排序
@Test
void test6() {
    QueryWrapper<User> wapper = new QueryWrapper<>();
    //通過id進行排序
    wapper.orderByDesc("id");
    userMapper.selectList(wapper).forEach(System.out::println);
}

代碼生成器

mapper、pojo、service、controller都給我自己去編寫完成!

AutoGenerator 是 MyBatis-Plus 的代碼生成器,通過 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各個模塊的代碼,極大的提升了開發效率。

1.EasyCode介紹


1.1 EasyCode是一個什麼東西?


EasyCode是基於IntelliJ IDEA Ultimate版開發的一個代碼生成插件,主要通過自定義模板(基於velocity)來生成各種你想要的代碼。通常用於生成Entity、Dao、Service、Controller。如果你動手能力強還可以用於生成HTML、JS、PHP等代碼。理論上來說只要是與數據有關的代碼都是可以生成的。


1.2 原理

基於Mybatis底層強大的逆向工程能力和良好的項目架構


1.3 使用環境

IntelliJ IDEA Ultimate版


1.4 支持的數據庫類型

因爲是基於Database Tool開發,所有Database Tool支持的數據庫都是支持的。

包括如下數據庫:

  1. MySQL
  2. SQL Server
  3. Oracle
  4. PostgreSQL
  5. Sqlite
  6. Sybase
  7. Derby
  8. DB2
  9. HSQLDB
  10. H2

當然支持的數據庫類型也會隨着Database Tool插件的更新同步更新。


1.5 功能說明:

  • 支持多表同時操作
  • 支持同時生成多個模板
  • 支持自定義模板
  • 支持自定義類型映射(支持正則)
  • 支持自定義附加列
  • 支持列附加屬性
  • 所有配置項目支持分組模式,在不同項目(或選擇不同數據庫時),只需要切換對應的分組,所有配置統一變化

1.6 功能對比:

功能 Easy Code 其他工具
自定義模板 支持 支持
多表生成 支持 支持
生成方式 無縫集成在項目中 部分工具需要複製粘貼
附加列 支持 不支持
附加列屬性 支持 不支持
動態調試模板 支持 不支持
圖形化界面 支持 部分支持
使用環境 僅限IDEA 支持各種形式
在線支持 後期擴展 不支持
自定義類型映射 支持 部分支持
全局變量 支持 不支持

2.EasyCode使用


2.1 下載Easy Code插件


2.2 創建一個SpringBoot項目

2.3 配置數據源

使用Easy Code一定要使用IDEA自帶的數據庫工具來配置數據源

.


打開側邊的Database,查看效果

,


提前準備的數據表

,


2.4 自定義生成模板


第一次安裝EasyCode的時候默認的模板(服務於MyBatis)可以生成下面類型的代碼

  1. entity.java
  2. dao.java
  3. service.java
  4. serviceImpl.java
  5. controller.java
  6. mapper.xml
  7. debug.json

2.5 以user表爲例,根據你定義的模板生成代碼,文章的最後貼出我使用的自定義的模板

,


選擇模板

,


點擊OK之後,就可以看到生成了這些代碼

,


2.6 代碼展示

實體類層:User.java
package com.godfrey.easycode.entity;

import java.io.Serializable;

/**
 * (User)實體類
 *
 * @author godfrey
 * @since 2020-04-20 19:21:17
 */
public class User implements Serializable {
    private static final long serialVersionUID = 502672392114472688L;
    /**
     * 主鍵ID
     */
    private Integer id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 年齡
     */
    private Integer age;
    /**
     * 郵箱
     */
    private String email;

        
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
        
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
        
    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
        
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                "name=" + name +
                "age=" + age +
                "email=" + email +
                '}';
    }
}

Dao數據庫訪問層:UserDao.java
package com.godfrey.easycode.dao;

import com.godfrey.easycode.entity.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * description : (User)表數據庫訪問層
 *
 * @author godfrey
 * @since  2020-04-20 19:21:17
 */
@Mapper
public interface UserDao {

    /**
     * description : 添加User
     *
     * @param user 實例對象
     * @return 影響行數
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    int insert(User user);

    /**
     * description : 刪除User
     *
     * @param  id 主鍵
     * @return 影響行數
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    int deleteById(Integer id);

    /**
     * description : 通過ID查詢單條數據
     *
     * @param  id 主鍵
     * @return 實例對象
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    User queryById(Integer id);

    /**
     * description : 查詢全部數據(分頁使用MyBatis的插件實現)
     *
     * @return 對象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List<User> queryAll();

    /**
     * description : 實體作爲篩選條件查詢數據
     *
     * @param  user 實例對象
     * @return 對象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List<User> queryAll(User user);

    /**
     * description : 修改User
     *
     * @param  user 根據user的主鍵修改數據
     * @return 影響行數
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    int update(User user);
}

Service服務接口層:UserService.java
package com.godfrey.easycode.service;

import com.godfrey.easycode.entity.User;
import java.util.List;

/**
 * description : (User)表服務接口
 *
 * @author godfrey
 * @since  2020-04-20 19:21:17
 */
public interface UserService {

    /**
     * description : 添加User
     *
     * @param  user 實例對象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    boolean insert(User user);

    /**
     * description : 刪除User
     *
     * @param  id 主鍵
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    boolean deleteById(Integer id);

    /**
     * description : 查詢單條數據
     * @param  id 主鍵
     * @return 實例對象
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    User queryById(Integer id);

    /**
     * description : 查詢全部數據(分頁使用MyBatis的插件實現)
     *
     * @return 對象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List<User> queryAll();

    /**
     * description : 實體作爲篩選條件查詢數據
     *
     * @param  user 實例對象
     * @return 對象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    List<User> queryAll(User user);

    /**
     * description : 修改數據,哪個屬性不爲空就修改哪個屬性
     *
     * @param  user 實例對象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    boolean update(User user);
}

ServiceImpl服務接口實現層:UserServiceImpl.java
package com.godfrey.easycode.service.impl;

import com.godfrey.easycode.entity.User;
import com.godfrey.easycode.dao.UserDao;
import com.godfrey.easycode.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

 /**
  * description : (User)表服務實現類
  *
  * @author godfrey
  * @since  2020-04-20 19:21:17
  **/
@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    protected UserDao userDao;

    /**
     * description : 添加User
     *
     * @param  user 實例對象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public boolean insert(User user) {
        return userDao.insert(user) == 1;
    }

    /**
     * description : 刪除User
     *
     * @param  id 主鍵
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public boolean deleteById(Integer id) {
        return userDao.deleteById(id) == 1;
    }

    /**
     * description : 查詢單條數據
     *
     * @param  id 主鍵
     * @return 實例對象
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public User queryById(Integer id) {
        return userDao.queryById(id);
    }

    /**
     * description : 查詢全部數據(分頁使用MyBatis的插件實現)
     *
     * @return 對象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public List<User> queryAll() {
        return userDao.queryAll();
    }

    /**
     * description : 實體作爲篩選條件查詢數據
     *
     * @param user 實例對象
     * @return 對象列表
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public List<User> queryAll(User user) {
        return userDao.queryAll(user);
    }

    /**
     * description : 修改數據,哪個屬性不爲空就修改哪個屬性
     *
     * @param user 實例對象
     * @return 是否成功
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @Override
    public boolean update(User user) {
        return userDao.update(user) == 1;
    }
}

前端控制器:UserController.java
package com.godfrey.easycode.controller;

import com.godfrey.easycode.entity.User;
import com.godfrey.easycode.service.UserService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * description : (User)表控制層
 *
 * @author godfrey
 * @since  2020-04-20 19:21:17
 */
@RestController
@RequestMapping("user")
public class UserController {
    /**
     * 服務對象
     */
    @Resource
    private UserService userService;

    /**
     * description : 通過主鍵查詢單條數據
     *
     * @param  id 主鍵
     * @return 單條數據
     * @author godfrey
     * @since  2020-04-20 19:21:17
     */
    @GetMapping("selectOne")
    public User selectOne(Integer id) {
        return this.userService.queryById(id);
    }
}

Mapper映射文件:UserMapper.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.godfrey.easycode.dao.UserDao">

    <!--user的映射結果集-->
    <resultMap type="com.godfrey.easycode.entity.User" id="UserMap">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="age" column="age" jdbcType="INTEGER"/>
        <result property="email" column="email" jdbcType="VARCHAR"/>
    </resultMap>

    <!--全部字段-->
    <sql id="allColumn"> id, name, age, email </sql>

    <!--添加語句的字段列表-->
    <sql id="insertColumn">
        <if test="name != null and name != ''">
            name,
        </if>
        <if test="age != null">
            age,
        </if>
        <if test="email != null and email != ''">
            email,
        </if>
    </sql>

    <!--添加語句的值列表-->
    <sql id="insertValue">
        <if test="name != null and name != ''">
            #{name},
        </if>
        <if test="age != null">
            #{age},
        </if>
        <if test="email != null and email != ''">
            #{email},
        </if>
    </sql>

    <!--通用對User各個屬性的值的非空判斷-->
    <sql id="commonsValue">
        <if test="name != null and name != ''">
            name = #{name},
        </if>
        <if test="age != null">
            age = #{age},
        </if>
        <if test="email != null and email != ''">
            email = #{email},
        </if>
    </sql>

    <!--新增user:哪個字段不爲空就添加哪列數據,返回自增主鍵-->
    <insert id="insert" keyProperty="id" useGeneratedKeys="true">
        insert into user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <include refid="insertColumn"/>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <include refid="insertValue"/>
        </trim>
    </insert>

    <!--刪除user:通過主鍵-->
    <delete id="deleteById">
        delete from user
        <where>
            id = #{id}
        </where>
    </delete>

    <!--查詢單個user-->
    <select id="queryById" resultMap="UserMap">
        select
        <include refid="allColumn"></include>
        from user
        <where>
            id = #{id}
        </where>
    </select>

    <!--通過實體作爲篩選條件查詢-->
    <select id="queryAll" resultMap="UserMap">
        select
        <include refid="allColumn"></include>
        from user
        <trim prefix="where" prefixOverrides="and" suffixOverrides=",">
            <include refid="commonsValue"></include>
        </trim>
    </select>

    <!--通過主鍵修改數據-->
    <update id="update">
        update user
        <set>
            <include refid="commonsValue"></include>
        </set>
        <where>
            id = #{id}
        </where>
    </update>
</mapper>

以上代碼完全是生成出來了,從頭到尾只需要點幾下鼠標,是不是很神奇!


3.我的默認定製模板


entity.java

##引入宏定義
$!define

##使用宏定義設置回調(保存位置與文件後綴)
#save("/entity", ".java")

##使用宏定義設置包後綴
#setPackageSuffix("entity")

##使用全局變量實現默認包導入
$!autoImport
import java.io.Serializable;

##使用宏定義實現類註釋信息
#tableComment("實體類")
public class $!{tableInfo.name} implements Serializable {
    private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
    #if(${column.comment})/**
     * ${column.comment}
     */#end

    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end

#foreach($column in $tableInfo.fullColumn)
    ##使用宏定義實現get,set方法
    #getSetMethod($column)
#end

    @Override
    public String toString() {
        return "$!{tableInfo.name}{" +
    #foreach($column in $tableInfo.fullColumn)
            "$!{column.name}=" + $!{column.name} +
    #end
            '}';
    }
}

dao.java

##定義初始變量
#set($tableName = $tool.append($tableInfo.name, "Dao"))
##設置回調
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/dao"))

##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}dao;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * description : $!{tableInfo.comment}($!{tableInfo.name})表數據庫訪問層
 *
 * @author $!author
 * @since  $!time.currTime()
 */
@Mapper
public interface $!{tableName} {

    /**
     * description : 添加$!{tableInfo.name}
     *
     * @param $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 影響行數
     * @author $!author
     * @since  $!time.currTime()
     */
    int insert($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 刪除$!{tableInfo.name}
     *
     * @param  $!pk.name 主鍵
     * @return 影響行數
     * @author $!author
     * @since  $!time.currTime()
     */
    int deleteById($!pk.shortType $!pk.name);

    /**
     * description : 通過ID查詢單條數據
     *
     * @param  $!pk.name 主鍵
     * @return 實例對象
     * @author $!author
     * @since  $!time.currTime()
     */
    $!{tableInfo.name} queryById($!pk.shortType $!pk.name);

    /**
     * description : 查詢全部數據(分頁使用MyBatis的插件實現)
     *
     * @return 對象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll();

    /**
     * description : 實體作爲篩選條件查詢數據
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 對象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 修改$!{tableInfo.name}
     *
     * @param  user 根據$!tool.firstLowerCase($!{tableInfo.name})的主鍵修改數據
     * @return 影響行數
     * @author $!author
     * @since  $!time.currTime()
     */
    int update($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
}

service.java

##定義初始變量
#set($tableName = $tool.append($tableInfo.name, "Service"))
##設置回調
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/service"))

##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import java.util.List;

/**
 * description : $!{tableInfo.comment}($!{tableInfo.name})表服務接口
 *
 * @author $!author
 * @since  $!time.currTime()
 */
public interface $!{tableName} {

    /**
     * description : 添加$!{tableInfo.name}
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    boolean insert($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 刪除$!{tableInfo.name}
     *
     * @param  $!pk.name 主鍵
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    boolean deleteById($!pk.shortType $!pk.name);

    /**
     * description : 查詢單條數據
     * @param  $!pk.name 主鍵
     * @return 實例對象
     * @author $!author
     * @since  $!time.currTime()
     */
    $!{tableInfo.name} queryById($!pk.shortType $!pk.name);

    /**
     * description : 查詢全部數據(分頁使用MyBatis的插件實現)
     *
     * @return 對象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll();

    /**
     * description : 實體作爲篩選條件查詢數據
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 對象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    List<$!{tableInfo.name}> queryAll($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));

    /**
     * description : 修改數據,哪個屬性不爲空就修改哪個屬性
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    boolean update($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name}));
}

serviceImpl.java

##定義初始變量
#set($tableName = $tool.append($tableInfo.name, "ServiceImpl"))
##設置回調
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/service/impl"))

##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service.impl;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.dao.$!{tableInfo.name}Dao;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

 /**
  * description : $!{tableInfo.comment}($!{tableInfo.name})表服務實現類
  *
  * @author $!author
  * @since  $!time.currTime()
  **/
@Service("$!tool.firstLowerCase($!{tableInfo.name})Service")
public class $!{tableName} implements $!{tableInfo.name}Service {

    @Autowired
    protected $!{tableInfo.name}Dao $!tool.firstLowerCase($!{tableInfo.name})Dao;

    /**
     * description : 添加$!{tableInfo.name}
     *
     * @param  $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public boolean insert($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.insert($!tool.firstLowerCase($!{tableInfo.name})) == 1;
    }

    /**
     * description : 刪除$!{tableInfo.name}
     *
     * @param  $!pk.name 主鍵
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public boolean deleteById($!pk.shortType $!pk.name) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.deleteById($!pk.name) == 1;
    }

    /**
     * description : 查詢單條數據
     *
     * @param  $!pk.name 主鍵
     * @return 實例對象
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public $!{tableInfo.name} queryById($!pk.shortType $!pk.name) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.queryById($!pk.name);
    }

    /**
     * description : 查詢全部數據(分頁使用MyBatis的插件實現)
     *
     * @return 對象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public List<$!{tableInfo.name}> queryAll() {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.queryAll();
    }

    /**
     * description : 實體作爲篩選條件查詢數據
     *
     * @param $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 對象列表
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public List<$!{tableInfo.name}> queryAll($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.queryAll($!tool.firstLowerCase($!{tableInfo.name}));
    }

    /**
     * description : 修改數據,哪個屬性不爲空就修改哪個屬性
     *
     * @param $!tool.firstLowerCase($!{tableInfo.name}) 實例對象
     * @return 是否成功
     * @author $!author
     * @since  $!time.currTime()
     */
    @Override
    public boolean update($!{tableInfo.name} $!tool.firstLowerCase($!{tableInfo.name})) {
        return $!{tool.firstLowerCase($!{tableInfo.name})}Dao.update($!tool.firstLowerCase($!{tableInfo.name})) == 1;
    }
}

controller.java

##定義初始變量
#set($tableName = $tool.append($tableInfo.name, "Controller"))
##設置回調
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/controller"))
##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}controller;

import $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * description : $!{tableInfo.comment}($!{tableInfo.name})表控制層
 *
 * @author $!author
 * @since  $!time.currTime()
 */
@RestController
@RequestMapping("$!tool.firstLowerCase($tableInfo.name)")
public class $!{tableName} {
    /**
     * 服務對象
     */
    @Resource
    private $!{tableInfo.name}Service $!tool.firstLowerCase($tableInfo.name)Service;

    /**
     * description : 通過主鍵查詢單條數據
     *
     * @param  id 主鍵
     * @return 單條數據
     * @author $!author
     * @since  $!time.currTime()
     */
    @GetMapping("selectOne")
    public $!{tableInfo.name} selectOne($!pk.shortType id) {
        return this.$!{tool.firstLowerCase($tableInfo.name)}Service.queryById(id);
    }
}

mapper.xml

##引入mybatis支持
$!mybatisSupport

##設置保存名稱與保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Dao.xml"))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mybatis/mapper"))

##拿到主鍵
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

<?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="$!{tableInfo.savePackageName}.dao.$!{tableInfo.name}Dao">

    <!--$!{tableInfo.obj.name}的映射結果集-->
    <resultMap type="$!{tableInfo.savePackageName}.entity.$!{tableInfo.name}" id="$!{tableInfo.name}Map">
#foreach($column in $tableInfo.fullColumn)
        <result property="$!column.name" column="$!column.obj.name" jdbcType="$!column.ext.jdbcType"/>
#end
    </resultMap>

    <!--全部字段-->
    <sql id="allColumn"> #allSqlColumn() </sql>

    <!--添加語句的字段列表-->
    <sql id="insertColumn">
#foreach($column in $tableInfo.otherColumn)
        <if test="$!column.name != null#if($column.type.equals("java.lang.String")) and $!column.name != ''#end">
            $!column.obj.name,
        </if>
#end
    </sql>

    <!--添加語句的值列表-->
    <sql id="insertValue">
#foreach($column in $tableInfo.otherColumn)
        <if test="$!column.name != null#if($column.type.equals("java.lang.String")) and $!column.name != ''#end">
            #{$!column.name},
        </if>
#end
    </sql>

    <!--通用對$!{tableInfo.name}各個屬性的值的非空判斷-->
    <sql id="commonsValue">
#foreach($column in $tableInfo.otherColumn)
        <if test="$!column.name != null#if($column.type.equals("java.lang.String")) and $!column.name != ''#end">
            $!column.obj.name = #{$!column.name},
        </if>
#end
    </sql>

    <!--新增$!{tableInfo.obj.name}:哪個字段不爲空就添加哪列數據,返回自增主鍵-->
    <insert id="insert" keyProperty="$!pk.name" useGeneratedKeys="true">
        insert into $!{tableInfo.obj.name}
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <include refid="insertColumn"/>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <include refid="insertValue"/>
        </trim>
    </insert>

    <!--刪除$!{tableInfo.obj.name}:通過主鍵-->
    <delete id="deleteById">
        delete from $!{tableInfo.obj.name}
        <where>
            $!pk.obj.name = #{$!pk.name}
        </where>
    </delete>

    <!--查詢單個$!{tableInfo.obj.name}-->
    <select id="queryById" resultMap="$!{tableInfo.name}Map">
        select
        <include refid="allColumn"></include>
        from $!tableInfo.obj.name
        <where>
            $!pk.obj.name = #{$!pk.name}
        </where>
    </select>

    <!--通過實體作爲篩選條件查詢-->
    <select id="queryAll" resultMap="$!{tableInfo.name}Map">
        select
        <include refid="allColumn"></include>
        from $!tableInfo.obj.name
        <trim prefix="where" prefixOverrides="and" suffixOverrides=",">
            <include refid="commonsValue"></include>
        </trim>
    </select>

    <!--通過主鍵修改數據-->
    <update id="update">
        update $!{tableInfo.obj.name}
        <set>
            <include refid="commonsValue"></include>
        </set>
        <where>
            $!pk.obj.name = #{$!pk.name}
        </where>
    </update>
</mapper>

新創建一個分組Lombok,可以在生成實體類的時候使用Lombok註解

,

實體類層:entity.java

##引入宏定義
$!define

##使用宏定義設置回調(保存位置與文件後綴)
#save("/entity", ".java")

##使用宏定義設置包後綴
#setPackageSuffix("entity")

##使用全局變量實現默認包導入
$!autoImport
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

##使用宏定義實現類註釋信息
#tableComment("實體類")
@AllArgsConstructor
@Data
@Builder
public class $!{tableInfo.name} implements Serializable {
    private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)
    #if(${column.comment})/**
    * ${column.comment}
    */#end

    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
}

多個分組的切換

選擇好分組後,點擊OK,之後在Datebase視圖的數據表右鍵選擇EasyCode生成的時候會讓你選擇當前分組的模板

,

,

,

.

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