MyBatis-Plus整合Druid環境搭建的詳細教程
一、簡介
Mybatis-Plus是一款 MyBatis 動態 sql 自動注入 crud 簡化 增 刪 改 查 操作中介軟體。啟動載入 XML 配置時注入 mybatis 單表 動態 SQL 操作 ,為簡化開發工作、提高生產率而生。Mybatis-Plus 啟動注入非攔截實現、效能更優。
1.1、原理
1.2、特性
- 無侵入:Mybatis-Plus 在 Mybatis 的基礎上進行擴充套件,只做增強不做改變,引入 Mybatis-Plus 不會對您現有的 Mybatis 構架產生任何影響,而且 MP 支援所有 Mybatis 原生的特性
- 依賴少:僅僅依賴 Mybatis 以及 Mybatis-Spring
- 損耗小:啟動即會自動注入基本CURD,效能基本無損耗,直接面向物件操作
- 預防Sql注入:內建Sql注入剝離器,有效預防Sql注入攻擊
- 通用CRUD操作:內建通用 Mapper、通用 Service,僅僅通過少量配置即可實現單表大部分 CRUD 操作,更有強大的條件構造器,滿足各類使用需求
- 多種主鍵策略:支援多達4種主鍵策略(內含分散式唯一ID生成器),可自由配置,完美解決主鍵問題
- 支援熱載入:Mapper 對應的 XML 支援熱載入,對於簡單的 CRUD 操作,甚至可以無 XML 啟動
- 支援ActiveRecord:支援 ActiveRecord 形式呼叫,實體類只需繼承 Model 類即可實現基本 CRUD 操作
- 支援程式碼生成:採用程式碼或者 Maven 外掛可快速生成 Mapper 、 Model 、 Service 、 Controller 層程式碼,支援模板引擎,更有超多自定義配置等您來使用(P.S. 比 Mybatis 官方的 Generator 更加強大!)
- 支援自定義全域性通用操作:支援全域性通用方法注入( Write once,use anywhere )
- 支援關鍵詞自動轉義:支援資料庫關鍵詞(order、key......)自動轉義,還可自定義關鍵詞
- 內建分頁外掛:基於Mybatis物理分頁,開發者無需關心具體操作,配置好外掛之後,寫分頁等同於普通List查詢
- 內建效能分析外掛:可輸出Sql語句以及其執行時間,建議開發測試時啟用該功能,能有效解決慢查詢
- 內建全域性攔截外掛:提供全表 delete 、 update 操作智慧分析阻斷,預防誤操作
1.3、簡化
MP簡化了MyBatis的單表基本操作,提供了兩種操作方式:
(1)、傳統模式
Mybatis-Plus 通過 EntityWrapper(簡稱 EW,MP 封裝的一個查詢條件構造器)或者 Condition(與EW類似) 來讓使用者自由的構建查詢條件,簡單便捷,沒有額外的負擔,能夠有效提高開發效率。
(2)、ActiveRecord模式
Active Record(簡稱AR)模式是軟體裡的一種架構性模式,主要概念是關係型資料庫中的資料在記憶體中以物件的形式儲存。由Martin Fowler在其2003年初版的書籍《Patterns of Enterprise Application Architecture》命名。遵循該模式的物件介面一般包括如Insert,Update,和 Delete這樣的函式,以及對應於底層資料庫表字段的相關屬性。
AR模式是一種訪問資料庫資料的方式。資料表或檢視被對映成一個類。每個物件例項則對應於表的一條記錄。物件被建立後,通過save就可以向表中新添一行記錄。當物件被更新時,表中相應記錄也被更新。這個包裹類通過屬性或方法的形式實現訪問表或檢視中的每一個欄位。
該模式主要被物件持久化工具採用,用於物件關係對映 (ORM). 典型的,外來鍵關係會以合適的物件例項屬性的形式暴露訪問。
1.4、常用實體註解
1.表名註解@TableName
2.主鍵註解@TableId
3.欄位註解@TableFieId
4.序列主鍵策略註解@KeySequence
二、搭建
環境:
IDEA
Spring Boot-2.0
MyBatis-Plus-2.2.0
MyBatisPlus-spring-boot-starter-1.0.5
druid-spring-boot-starter-1.1.9
首先建立SpringBoot Maven專案,然後加入以下依賴:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fendo.mybatis.plus</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>mybatis-plus</name> <description>mybatis-plus 示例</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <mybatisplus-spring-boot-starter.version>1.0.5</mybatisplus-spring-boot-starter.version> <mybatisplus.version>2.2.0</mybatisplus.version> <fastjson.version>1.2.39</fastjson.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- mybatis-plus begin --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatisplus-spring-boot-starter</artifactId> <version>${mybatisplus-spring-boot-starter.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>${mybatisplus.version}</version> </dependency> <!-- mybatis-plus end --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>com.jayway.restassured</groupId> <artifactId>rest-assured</artifactId> <version>2.9.0</version> </dependency> <!--Swagger UI--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.2.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
然後新建application.yml配置檔案
# Tomcat server: tomcat: uri-encoding: UTF-8 max-threads: 1000 min-spare-threads: 30 port: 8080 connection-timeout: 5000 #datasource spring: datasource: name: fendo url: jdbc:mysql://localhost:3306/fendo_plus_boot?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false username: root password: root type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 spring.datasource.filters: stat,wall,log4j connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # jackson時間格式化 jackson: time-zone: GMT+8 date-format: yyyy-MM-dd HH:mm:ss thymeleaf: cache: false prefix: classpath:/templates/ suffix: .html mode: LEGACYHTML5 encoding: UTF-8 check-template: false enabled: false resources: # 指定靜態資源的路徑 static-locations: classpath:/static/,classpath:/views/ mvc: view: prefix: /WEB-INF/ suffix: .jsp # Mybatis-Plus 配置 mybatis-plus: mapper-locations: classpath:/mapper/*Mapper.xml typeAliasesPackage: com.fendo.mybatis.plus.entity typeEnumsPackage: com.fendo.mybatis.plus.entity.enums # global-config: # id-type: 2 # field-strategy: 2 # db-column-underline: true # refresh-mapper: true # #capital-mode: true # #key-generator: com.baomidou.springboot.xxx # logic-delete-value: 0 # logic-not-delete-value: 1 # sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector # #meta-object-handler: com.baomidou.springboot.xxx # #sql-injector: com.baomidou.springboot.xxx # configuration: # map-underscore-to-camel-case: true # cache-enabled: false global-config: id-type: 3 #0:資料庫ID自增 1:使用者輸入id 2:全域性唯一id(IdWorker) 3:全域性唯一ID(uuid) db-column-underline: false refresh-mapper: true configuration: map-underscore-to-camel-case: true cache-enabled: true #配置的快取的全域性開關 lazyLoadingEnabled: true #延時載入的開關 multipleResultSetsEnabled: true #開啟的話,延時載入一個屬性時會載入該物件全部屬性,否則按需載入屬性 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #列印sql語句,除錯用
建立MyBatis-Plus配置類MybatisPlusConfig
/** * projectName: fendo-plus-boot * fileName: MybatisPlusConfig.java * packageName: com.fendo.mybatis.plus.config * date: 2018-01-12 23:13 * copyright(c) 2017-2020 xxx公司 */ package com.fendo.mybatis.plus.config; import com.baomidou.mybatisplus.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.plugins.PerformanceInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @version: V1.0 * @author: fendo * @className: MybatisPlusConfig * @packageName: com.fendo.mybatis.plus.config * @description: Mybatis-plus配置類 * @data: 2018-01-12 23:13 **/ @Configuration @MapperScan("com.fendo.mybatis.plus.mapper*") public class MybatisPlusConfig { /** * mybatis-plus SQL執行效率外掛【生產環境可以關閉】 */ @Bean public PerformanceInterceptor performanceInterceptor() { return new PerformanceInterceptor(); } /** * 分頁外掛 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }
三、測試
首先建立User表
CREATE TABLE `user` ( `id` varchar(32) NOT NULL,`name` varchar(255) DEFAULT NULL,`age` int(2) DEFAULT NULL,`sex` int(2) DEFAULT NULL,`create_by` varchar(255) DEFAULT NULL,`create_date` datetime DEFAULT NULL,`update_by` varchar(255) DEFAULT NULL,`update_date` datetime DEFAULT NULL,`remarks` varchar(255) DEFAULT NULL,`del_flag` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
然後建立controller,entity,service,mapper,專案結構如下所示:
Controller測試類如下:
/** * projectName: mybatis-plus * fileName: UserController.java * packageName: com.fendo.mybatis.plus.controller * date: 2018-03-24 19:07 * copyright(c) 2017-2020 xxx公司 */ package com.fendo.mybatis.plus.controller; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; import com.baomidou.mybatisplus.plugins.pagination.PageHelper; import com.fendo.mybatis.plus.common.utils.IdGen; import com.fendo.mybatis.plus.entity.UserEntity; import com.fendo.mybatis.plus.entity.enums.AgeEnum; import com.fendo.mybatis.plus.entity.enums.SexEnum; import com.fendo.mybatis.plus.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @version: V1.0 * @author: fendo * @className: UserController * @packageName: com.fendo.mybatis.plus.controller * @description: 使用者Controller * @data: 2018-03-24 19:07 **/ @RestController @RequestMapping("/user") @Api("使用者操作介面") public class UserController { @Autowired private UserService userService; /** * 分頁 PAGE */ @GetMapping("/page") @ApiOperation(value = "使用者分頁資料",response = UserEntity.class) @ApiResponse(code = 200,message = "success") public Page<UserEntity> test() { return userService.selectPage(new Page<UserEntity>(0,12)); } /** * AR 部分測試 */ @GetMapping("/insert") public Page<UserEntity> insert() { UserEntity user = new UserEntity(IdGen.getUUID(),"testAr",AgeEnum.ONE,SexEnum.FEMALE); System.err.println("刪除所有:" + user.delete(null)); user.insert(); System.err.println("查詢插入結果:" + user.selectById().toString()); user.setName("mybatis-plus-ar"); System.err.println("更新:" + user.updateById()); return user.selectPage(new Page<UserEntity>(0,12),null); } /** * 增刪改查 CRUD */ @GetMapping("/crud") public UserEntity crud() { System.err.println("刪除一條資料:" + userService.deleteById("85349feb19f04fa78a7a717f4dce031f")); System.err.println("deleteAll:" + userService.deleteAll()); String IdGens = IdGen.getUUID(); System.err.println("插入一條資料:" + userService.insert(new UserEntity(IdGens,"張三",AgeEnum.TWO,SexEnum.FEMALE))); UserEntity user = new UserEntity("張三",SexEnum.MALE); boolean result = userService.insert(user); // 自動回寫的ID String id = user.getId(); System.err.println("插入一條資料:" + result + ",插入資訊:" + user.toString()); System.err.println("查詢:" + userService.selectById(id).toString()); System.err.println("更新一條資料:" + userService.updateById(new UserEntity(IdGens,"三毛",SexEnum.FEMALE))); for (int i = 0; i < 5; ++i) { userService.insert(new UserEntity( IdGen.getUUID(),"張三" + i,SexEnum.FEMALE)); } Page<UserEntity> userListPage = userService.selectPage(new Page<UserEntity>(1,5),new EntityWrapper<>(new UserEntity())); System.err.println("total=" + userListPage.getTotal() + ",current list size=" + userListPage.getRecords().size()); return userService.selectById(IdGens); } /** * 插入 OR 修改 */ @GetMapping("/save") public UserEntity save() { String IdGens = IdGen.getUUID(); UserEntity user = new UserEntity(IdGens,"王五",SexEnum.FEMALE); userService.insertOrUpdate(user); return userService.selectById(IdGens); } @GetMapping("/add") public Object addUser() { UserEntity user = new UserEntity(IdGen.getUUID(),"張三'特殊`符號",SexEnum.FEMALE); JSONObject result = new JSONObject(); result.put("result",userService.insert(user)); return result; } @GetMapping("/selectsql") public Object getUserBySql() { JSONObject result = new JSONObject(); result.put("records",userService.selectListBySQL()); return result; } /** * 7、分頁 size 一頁顯示數量 current 當前頁碼 * 方式一:http://localhost:8080/user/page?size=1¤t=1 * 方式二:http://localhost:8080/user/pagehelper?size=1¤t=1 */ // 引數模式分頁 @GetMapping("/pages") public Object page(Page page) { return userService.selectPage(page); } // ThreadLocal 模式分頁 @GetMapping("/pagehelper") public Object pagehelper(Page page) { PageHelper.setPagination(page); page.setRecords(userService.selectList(null)); page.setTotal(PageHelper.freeTotal());//獲取總數並釋放資源 也可以 PageHelper.getTotal() return page; } /** * 測試事物 * http://localhost:8080/user/test_transactional<br> * 訪問如下並未發現插入資料說明事物可靠!!<br> * http://localhost:8080/user/test<br> * <br> * 啟動 Application 加上 @EnableTransactionManagement 註解其實可無預設貌似就開啟了<br> * 需要事物的方法加上 @Transactional 必須的哦!! */ @Transactional @GetMapping("/test_transactional") public void testTransactional() { String IdGens = IdGen.getUUID(); userService.insert(new UserEntity(IdGens,"測試事物",SexEnum.FEMALE)); System.out.println(" 這裡手動丟擲異常,自動回滾資料 : " + IdGens); throw new RuntimeException(); } }
四、程式碼生成
建立測試類GeneratorStart
/** * projectName: fendo-plus-boot * fileName: GeneratorStart.java * packageName: com.fendo.shiro.generator * date: 2018-01-15 19:59 * copyright(c) 2017-2020 xxx公司 */ package com.gzsys.modules.gen; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.rules.DbType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @version: V1.0 * @author: fendo * @className: GeneratorStart * @packageName: com.gzsys.modules.gen * @description: 程式碼生成器 * @data: 2018-01-15 19:59 **/ public class GeneratorStart { public static void main(String[] args) { String packageName = "com.gzsys.modules.yun"; boolean serviceNameStartWithI = false;//user -> UserService,設定成true: user -> IUserService generateByTables(serviceNameStartWithI,packageName,"USER_LOGIN"); } private static void generateByTables(boolean serviceNameStartWithI,String packageName,String... tableNames) { // 全域性配置 GlobalConfig config = new GlobalConfig(); AutoGenerator mpg = new AutoGenerator(); String dbUrl = "jdbc:oracle:thin:@//106.14.160.67:1521/test"; DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.ORACLE) .setUrl(dbUrl) .setUsername("test") .setPassword("Eru43wPo") .setDriverName("oracle.jdbc.driver.OracleDriver"); // 策略配置 StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig .setCapitalMode(true) // 全域性大寫命名 ORACLE 注意 .setEntityLombokModel(false) //實體 是否為lombok模型(預設 false) .setDbColumnUnderline(true) //表名、欄位名、是否使用下劃線命名 .setNaming(NamingStrategy.underline_to_camel) //表名生成策略 .setInclude(tableNames);//修改替換成你需要的表名,多個表名傳陣列 // strategyConfig.setExclude(new String[]{"test"}); // 排除生成的表 // 自定義實體父類 strategyConfig.setSuperEntityClass("com.gzsys.common.persistence.BaseEntity"); // 自定義實體,公共欄位 strategyConfig.setSuperEntityColumns(new String[] { "ID","CREATE_TIME","CREATE_NAME","UPDATE_TIME","UPDATE_NAME","STATE"}); // 自定義 mapper 父類 // strategyConfig.setSuperMapperClass("com.baomidou.demo.TestMapper"); // 自定義 service 父類 //strategyConfig.setSuperServiceClass("com.baomidou.demo.TestService"); // 自定義 service 實現類父類 //strategyConfig.setSuperServiceImplClass("com.baomidou.demo.TestServiceImpl"); // 自定義 controller 父類 strategyConfig.setSuperControllerClass("com.gzsys.common.base.controller.BaseController"); // 【實體】是否生成欄位常量(預設 false) // public static final String ID = "test_id"; // strategyConfig.setEntityColumnConstant(true); // 【實體】是否為構建者模型(預設 false) // public User setName(String name) {this.name = name; return this;} // strategyConfig.setEntityBuliderModel(true); config.setActiveRecord(true) //是否 開啟 ActiveRecord 模式 .setAuthor("fendo") .setOutputDir("d:\\codeGen") .setFileOverride(true) .setActiveRecord(true) .setEnableCache(false)// XML 二級快取 .setBaseResultMap(true)// XML ResultMap .setBaseColumnList(false);// XML columList if (!serviceNameStartWithI) { config.setServiceName("%sService"); //自定義Service後戳,注意 %s 會自動填充表實體屬性! } // 注入自定義配置,可以在 VM 中使用 cfg.abc 【可無】 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { Map<String,Object> map = new HashMap<String,Object>(); map.put("abc",this.getConfig().getGlobalConfig().getAuthor() + "-mp"); this.setMap(map); } }; // 自定義 xxList.jsp 生成 List<FileOutConfig> focList = new ArrayList<FileOutConfig>(); //focList.add(new FileOutConfig("/template/list.jsp.vm") { // @Override // public String outputFile(TableInfo tableInfo) { // // 自定義輸入檔名稱 // return "D://my_" + tableInfo.getEntityName() + ".jsp"; // } //}); //cfg.setFileOutConfigList(focList); //mpg.setCfg(cfg); // 調整 xml 生成目錄演示 focList.add(new FileOutConfig("/templates/mapper.xml.vm") { @Override public String outputFile(TableInfo tableInfo) { return "d:\\codeGen/resources/mapping/modules/yun/" + tableInfo.getEntityName() + ".xml"; } }); cfg.setFileOutConfigList(focList); mpg.setCfg(cfg); // 關閉預設 xml 生成,調整生成 至 根目錄 TemplateConfig tc = new TemplateConfig(); tc.setXml(null); mpg.setTemplate(tc); // 自定義模板配置,可以 copy 原始碼 mybatis-plus/src/main/resources/templates 下面內容修改, // 放置自己專案的 src/main/resources/templates 目錄下,預設名稱一下可以不配置,也可以自定義模板名稱 // TemplateConfig tc = new TemplateConfig(); // tc.setController("..."); // tc.setEntity("..."); // tc.setMapper("..."); // tc.setXml("..."); // tc.setService("..."); // tc.setServiceImpl("..."); // 如上任何一個模組如果設定 空 OR Null 將不生成該模組。 // mpg.setTemplate(tc); //生成檔案 配置 mpg.setGlobalConfig(config) //全域性 相關配置 .setDataSource(dataSourceConfig) //資料來源配置 .setStrategy(strategyConfig) //資料庫表配置 .setPackageInfo( //包 相關配置 new PackageConfig() //跟包相關的配置項 .setParent(packageName) //父包名。如果為空,將下面子包名必須寫全部, 否則就只需寫子包名 .setController("controller") //Controller包名 .setEntity("entity") //entity包名 //.setXml("/") ) .execute(); } private void generateByTables(String packageName,String... tableNames) { generateByTables(true,tableNames); } }
Spring Boot 整合mybatis 與 swagger2
到此這篇關於MyBatis-Plus整合Druid環境搭建的詳細教程的文章就介紹到這了,更多相關MyBatis-Plus環境搭建內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!