[toc]java
MyBatis
是一個java的半自動化ORM
框架,而MyBatis-Plus是對它的二次封裝,簡化MyBatais的使用,簡單的說, 能夠儘量少的手寫增刪改查的sql
語句 。mysql
官方文檔地址:mp.baomidou.com/guidegit
文檔是中文的, 喜歡本身看文檔的同窗能夠直接照官方文檔來操做學習。 我這篇文章主要是記錄本身的學習過程,最後會提供本身的代碼及測試的數據庫環境部署。不想本身弄這些步驟的同窗能夠參照我這篇文章部署好環境來學習。github
version: '3.1'
services:
mysql:
restart: always
image: mysql:5.7.22
container_name: mysql
ports:
- 3306:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
--sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"
volumes:
- ./data:/var/lib/mysql
複製代碼
不會使用docker容器能夠參考 這篇文章 來學習web
項目是基於Spring Boot的, 建立項目後,添加各項依賴,完整pom.xml文件以下:spring
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.domain</groupId>
<artifactId>hello-mybatisplus</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello-mybatisplus</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--mysql start-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mysql end-->
<!--lombok start-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--lombok end -->
<!--mybatisplus start-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
<!--mybatisplus end-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
複製代碼
主要添加了數據庫鏈接、和MyBatis-Plus的依賴。sql
在application.yml中添加數據庫鏈接配置:docker
spring:
datasource:
druid:
url: jdbc:mysql://192.168.65.130:3306/myshop?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
initial-size: 1
min-idle: 1
max-active: 20
test-on-borrow: true
# MySQL 8.x: com.mysql.cj.jdbc.Driver
driver-class-name: com.mysql.jdbc.Driver
test-while-idle: true
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
複製代碼
主要配置了數據庫的地址,用戶名,密碼, 和打開mybatis-plus的sql日誌, 這樣待會測試的時候日誌就會打印出當前數據庫操做的sql語句,便於學習和排錯。數據庫
MyBatis-Plus 提供了代碼生成器的功能,能自動幫咱們生成mapper.xml
、 Mapper.java
POJO
等文件。運行一下代碼來生成這些文件:apache
package com.domain.hello.mybatisplus;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class CodeGenerator {
/**
* <p>
* 讀取控制檯內容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("請輸入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("請輸入正確的" + tip + "!");
}
public static void main(String[] args) {
// 代碼生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("domain");
gc.setOpen(false);
// gc.setSwagger2(true); //實體屬性 Swagger2 註解
mpg.setGlobalConfig(gc);
// 數據源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://192.168.65.130:3306/myshop?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
// pc.setModuleName(scanner("模塊名"));
pc.setParent("com.domain.hello.mybatisplus");
mpg.setPackageInfo(pc);
// 自定義配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 若是模板引擎是 freemarker
// String templatePath = "/templates/mapper.xml.ftl";
// 若是模板引擎是 velocity
String templatePath = "/templates/mapper.xml.vm";
// 自定義輸出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定義配置會被優先輸出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定義輸出文件名 , 若是你 Entity 設置了先後綴、此處注意 xml 的名稱會跟着發生變化!!
return projectPath + "/src/main/resources/mapper/" /*+ pc.getModuleName()*/
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
/*
cfg.setFileCreate(new IFileCreate() {
@Override
public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
// 判斷自定義文件夾是否須要建立
checkDir("調用默認方法建立的目錄");
return false;
}
});
*/
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定義輸出模板
//指定自定義模板路徑,注意不要帶上.ftl/.vm, 會根據使用的模板引擎自動識別
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("com.domain.hello.mybatisplus.common.BaseEntity");
strategy.setEntityLombokModel(true);
// strategy.setRestControllerStyle(true);
// 公共父類
// strategy.setSuperControllerClass("com.domain.hello.mybatisplus.common.BaseController");
// 寫於父類中的公共字段
strategy.setSuperEntityColumns("id");
// strategy.setInclude(scanner("表名,多個英文逗號分割").split(","));
strategy.setInclude(new String[] { "tb_user", "tb_item_cat","tb_content"});
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
// strategy.setRestControllerStyle(false);
// strategy.setSuperServiceClass(null);
// mpg.setTemplateEngine(new FreemarkerTemplateEngine());
// mpg.setTemplateEngine(new VelocityTemplateEngine());
mpg.execute();
}
}
複製代碼
在單元測試來執行MyBatis-Plus
提供的CRUD
操做
/**
* 測試插入數據
*/
@Test
public void testInsert() {
// 構造一條測試數據
for (int i = 0; i < 3; i++) {
TbUser tbUser = new TbUser();
tbUser.setUsername("domain" + RandomUtils.nextDouble());
tbUser.setPassword("123456" + RandomUtils.nextDouble());
tbUser.setPhone("130" + RandomUtils.nextInt());
tbUser.setEmail("topsale@vip.qq.com" + RandomUtils.nextDouble());
tbUser.setCreated(new Date());
tbUser.setUpdated(new Date());
// 插入數據
tbUserMapper.insert(tbUser);
}
}
複製代碼
@Test
public void testDelete() {
UpdateWrapper updateWrapper = new UpdateWrapper<TbUser>();
HashMap<String, Object> params = new HashMap<>();
params.put("id", 7);
params.put("username", "zhangsan");
updateWrapper.allEq(params);
tbUserMapper.delete(updateWrapper);
// tbUserMapper.deleteById("46");
// ArrayList<Integer> ids = new ArrayList<Integer>();
// ids.add(47);
// tbUserMapper.deleteBatchIds(ids);
}
複製代碼
@Test
public void testUpdate() {
UpdateWrapper<TbUser> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("username", "domain111");
TbUser tbUser = new TbUser();
tbUser.setUsername("domain");
tbUserMapper.update(tbUser, updateWrapper);
}
複製代碼
@Test
public void testSelect() {
UpdateWrapper<TbUser> wrapper = new UpdateWrapper<>();
wrapper.eq("username", "domain"); //等於
List<TbUser> tbUsers = tbUserMapper.selectList(wrapper);
for (TbUser tbUser : tbUsers) {
System.out.println("\n" + tbUser.getUsername());
}
}
複製代碼
MyBatis-Plus 也支持分頁, 只須要簡單配置便可以使用
package com.domain.hello.mybatisplus.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@Configuration
@MapperScan("com.domain.hello.mybatisplus.mapper.*.mapper*")
public class MybatisPlusConfig {
/**
* 分頁插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
複製代碼
mapper.java
@Repository
public interface TbUserMapper extends BaseMapper<TbUser> {
List<TbUser> getAll();
/**
* <p>
* 查詢 : 根據state狀態查詢用戶列表,分頁顯示
* 注意!!: 若是入參是有多個,須要加註解指定參數名才能在xml中取值
* </p>
*
* @param page 分頁對象,xml中能夠從裏面進行取值,傳遞參數 Page 即自動分頁,必須放在第一位(你能夠繼承Page實現本身的分頁對象)
* @param state 狀態
* @return 分頁對象
*/
IPage<TbUser> selectPageVo(Page page, @Param("city") String city);
}
複製代碼
mapper.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.domain.hello.mybatisplus.mapper.TbUserMapper">
<select id="selectPageVo" resultType="com.domain.hello.mybatisplus.entity.TbUser">
SELECT id,username FROM tb_user WHERE city=#{city}
</select>
</mapper>
複製代碼
@Test
public void testPage() {
// 不進行 count sql 優化,解決 MP 沒法自動優化 SQL 問題,這時候你須要本身查詢 count 部分
// page.setOptimizeCountSql(false);
// 當 total 爲小於 0 或者設置 setSearchCount(false) 分頁插件不會進行 count 查詢
// 要點!! 分頁返回的對象與傳入的對象是同一個
//頁碼下標
Integer pageIndex = 1;
//每頁數量
Integer pageSize = 2;
IPage<TbUser> iPage = tbUserMapper.selectPageVo(new Page(pageIndex * pageSize, pageSize), "gz");
List<TbUser> tbUsers = iPage.getRecords();
for (TbUser tbUser : tbUsers) {
System.out.println("\n" + tbUser.getUsername());
}
}
複製代碼
MyBatis-Plus 提供了條件構造器來構建sql語句的條件。
@Test
public void testSelect() {
UpdateWrapper<TbUser> wrapper = new UpdateWrapper<>();
// wrapper.eq("password","195d91be1e3ba6f1c857d46f24c5a454"); //等於
// wrapper.ne("username","domain");//不等於
// wrapper.gt("age",18); //大於
// wrapper.ge("age",22); //大於等於
// wrapper.lt("age", 22); //小於
// wrapper.le("age", 22); //小於等於
// wrapper.between("age","22","25"); //between value1 和 value2之間
// wrapper.notBetween("age","22","25");//not between value1 和 value2之間, null 不會查出來
// wrapper.like("username","domain"); %value%
// wrapper.likeLeft("username","1"); %value
// wrapper.likeRight("username","zhangsan"); value%
// wrapper.isNull("age"); //age == null 的數據
// wrapper.in("age","31","33"); age 是 31 33 的
// wrapper.notIn("age","22","23");age 不是 22 22的, age爲null的 不會查出來
// wrapper.inSql("id", "select id from tb_user where id > 3"); // id 爲 後面語句中查出來的id集合的 記錄 至關於 where id in (4,5,6); SELECT username,password,phone,email,created,updated FROM tb_user WHERE id IN (select id from tb_user where id > 3)
// wrapper.notInSql("id","select id from tb_user where id < 22");//id 不小於 22 的記錄
// wrapper.notInSql("id","select id from tb_user where id < 22");//id 不小於 22 的記錄,null 也查出來, 由於null 不在小於22的範圍內
// wrapper.groupBy("age"); //經過 age 分組,age相同爲一組, 一組只有一條記錄就是組的第一條記錄
// wrapper.orderByAsc("id","age");//以id,age 升序排序,先對id排序, id相同, 對age排序
// wrapper.orderBy(true,true,"id","age"); //和上面效果相同
// wrapper.orderByDesc("id","age");//以id,age 降序排序,先對id排序, id相同, 對age排序
//having
// 須要注意的是,
//
// having 子句中的每個元素也必須出如今select列表中。有些數據庫例外,如oracle.
// having子句和where子句均可以用來設定限制條件以使查詢結果知足必定的條件限制。
// having子句限制的是組,而不是行。where子句中不能使用匯集函數,而having子句中能夠。
// 當加上其餘sql語句時,執行順序以下:
// S-F-W-G-H-O 組合
//
// select –>where –> group by–> having–>order by
//
// 順序是不能改變的
//
// SELECT
// username,
// city,
// SUM(price)
// FROM
// tb_user
// GROUP BY
// city
// HAVING
// SUM(price) > 2000
// wrapper.groupBy("city").having("sum(price)>2000");
// wrapper.having("sum(age)>22");
// wrapper.eq("username","domain").or().eq("age","22"); username = domain 或者 age = 22
//OR 嵌套
// wrapper.eq("username", "domain")
// .or(i -> i.eq("age", "22").eq("phone", "13333333334"));// username = domain 或者 (age = 22 and phone = 13333333334)
//and 嵌套
// wrapper.eq("age","22")
// .and(i -> i.eq("phone","13333333333").or().eq("phone","13333333334"));// age ==22 and (phone =13333333333 or phone = 13333333334)
//nested ,正常嵌套 username=domain 或者 age<22
// wrapper.nested(i -> i.eq("username","domain").or().lt("age","22"));
wrapper.set("username", "domain").eq("username", "niuniu");
List<TbUser> tbUsers = tbUserMapper.selectList(wrapper);
/**
* QueryWrapper, 能夠指定要查詢哪些字段
*/
// QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>();
// queryWrapper.select("username","password","phone");
// queryWrapper.eq("username","domain");
// List<TbUser> tbUsers = tbUserMapper.selectList(queryWrapper);
/**
* 自定義 sql
*/
// List<TbUser> tbUsers = tbUserMapper.getAll();
for (TbUser tbUser : tbUsers) {
System.out.println("\n" + tbUser.getUsername());
}
}
複製代碼
若是MyBatis-Plus 提供的CRUD方法沒辦法知足需求, 這時候就要本身手寫sql來知足需求了。
好比查詢 用戶所在城市的的總金額大於2000 的記錄。
@Repository
public interface TbUserMapper extends BaseMapper<TbUser> {
List<TbUser> getAll();
}
複製代碼
<?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.domain.hello.mybatisplus.mapper.TbUserMapper">
<select id="getAll" resultType="com.domain.hello.mybatisplus.entity.TbUser">
SELECT
username,
city,
SUM(price) as amount
FROM
tb_user
GROUP BY
city
HAVING
SUM(price) > 2000
</select>
</mapper>
複製代碼
@Test
public void testSelect() {
/**
* 自定義 sql
*/
List<TbUser> tbUsers = tbUserMapper.getAll();
for (TbUser tbUser : tbUsers) {
System.out.println("\n" + tbUser.getUsername());
}
}
複製代碼
完整代碼地址:github.com/domain9065/…