MyBatis Plus
1.引入
1.簡介
??MyBatis-Plus(簡稱 MP),是一個 MyBatis 的增強工具包,只做增強不做改變. 為簡化開發工作、提高生產率而生,愿景是成為 Mybatis 最好的搭檔,就像 魂斗羅 中的 1P、2P,基友搭配,效率
翻倍,基于mybatis
2.相關文檔
??官方地址:
http://mp.baomidou.com
https://mybatis.plus/
??代碼發布地址:Github: https://github.com/baomidou/mybatis-plusGitee: https://gitee.com/baomidou/mybatis-plus
??文檔發布地址:http://mp.baomidou.com/#/?id=簡??%
3.前置知識
Mybatis、Spring、Maven
2.環境搭建
2.1 準備
表結構
-- 創建庫
CREATE DATABASE mp;
-- 使用庫
USE mp;
-- 創建表
CREATE TABLE tbl_employee(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(50),
email VARCHAR(50),
gender CHAR(1),
age int
);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom','tom@zhenqk.com',1,18);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tony','jerry@zhenqk.com',0,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Black','black@zhenqk.com',1,20);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('White','white@zhenqk.com',0,30);
用包裝類的原因: 每個基本類型的默認值不一樣
domain
@Setter
@Getter
@ToString
public class Employee implements Serializable {
private Integer id;
private String lastNamprivate;
String email;
private Integer gender;
private Integer age;
}
pom.xml
<dependencies>
<!-- mp依賴
mybatisPlus 會自動的維護Mybatis 以及MyBatis-spring相關的依賴
-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.0</version>
</dependency>
<!--junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
2.mybatis 的整合
log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- 日志輸出到控制臺 -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<!-- 日志輸出格式 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p][%d{yyyy-MM-dd HH:mm:ss SSS}][%c]-[%m]%n"/>
</layout>
<!--過濾器設置輸出的級別-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- 設置日志輸出的最小級別 -->
<param name="levelMin" value="INFO"/>
<!-- 設置日志輸出的最大級別 -->
<param name="levelMax" value="ERROR"/>
</filter>
</appender>
<!-- 輸出日志到文件 -->
<appender name="fileAppender" class="org.apache.log4j.FileAppender">
<!-- 輸出文件全路徑名-->
<param name="File" value="/data/applogs/own/fileAppender.log"/>
<!--是否在已存在的文件追加寫:默認時true,若為false則每次啟動都會刪除并重新新建文件-->
<param name="Append" value="false"/>
<param name="Threshold" value="INFO"/>
<!--是否啟用緩存,默認false-->
<param name="BufferedIO" value="false"/>
<!--緩存大小,依賴上一個參數(bufferedIO), 默認緩存大小8K -->
<param name="BufferSize" value="512"/>
<!-- 日志輸出格式 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p][%d{yyyy-MM-dd HH:mm:ss SSS}][%c]-[%m]%n"/>
</layout>
</appender>
<!-- 輸出日志到文件,當文件大小達到一定閾值時,自動備份 -->
<!-- FileAppender子類 -->
<appender name="rollingAppender" class="org.apache.log4j.RollingFileAppender">
<!-- 日志文件全路徑名 -->
<param name="File" value="/data/applogs/RollingFileAppender.log" />
<!--是否在已存在的文件追加寫:默認時true,若為false則每次啟動都會刪除并重新新建文件-->
<param name="Append" value="true" />
<!-- 保存備份日志的最大個數,默認值是:1 -->
<param name="MaxBackupIndex" value="10" />
<!-- 設置當日志文件達到此閾值的時候自動回滾,單位可以是KB,MB,GB,默認單位是KB,默認值是:10MB -->
<param name="MaxFileSize" value="10KB" />
<!-- 設置日志輸出的樣式 -->`
<layout class="org.apache.log4j.PatternLayout">
<!-- 日志輸出格式 -->
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n" />
</layout>
</appender>
<!-- 日志輸出到文件,可以配置多久產生一個新的日志信息文件 -->
<appender name="dailyRollingAppender" class="org.apache.log4j.DailyRollingFileAppender">
<!-- 文件文件全路徑名 -->
<param name="File" value="/data/applogs/own/dailyRollingAppender.log"/>
<param name="Append" value="true" />
<!-- 設置日志備份頻率,默認:為每天一個日志文件 -->
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<!--每分鐘一個備份-->
<!--<param name="DatePattern" value="'.'yyyy-MM-dd-HH-mm'.log'" />-->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p][%d{HH:mm:ss SSS}][%c]-[%m]%n"/>
</layout>
</appender>
<!--
1. 指定logger的設置,additivity是否遵循缺省的繼承機制
2. 當additivity="false"時,root中的配置就失靈了,不遵循缺省的繼承機制
3. 代碼中使用Logger.getLogger("logTest")獲得此輸出器,且不會使用根輸出器
-->
<logger name="logTest" additivity="false">
<level value ="INFO"/>
<appender-ref ref="dailyRollingAppender"/>
</logger>
<!-- 根logger的設置,若代碼中未找到指定的logger,則會根據繼承機制,使用根logger-->
<root>
<appender-ref ref="console"/>
<appender-ref ref="fileAppender"/>
<appender-ref ref="rollingAppender"/>
<appender-ref ref="dailyRollingAppender"/>
</root>
</log4j:configuration>
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring
http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 數據源 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${druid.driver}"></property>
<property name="url" value="${druid.url}"></property>
<property name="username" value="${druid.username}"></property>
<property name="password" value="${druid.password}"></property>
</bean>
<!-- 事務管理器 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 基于注解的事務管理 -->
<tx:annotation-driven
transaction-manager="dataSourceTransactionManager"/>
<!-- 配置 SqlSessionFactoryBean -->
<bean id="sqlSessionFactoryBean"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 數據源 -->
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation"
value="classpath:mybatis-config.xml"></property>
<!-- 別名處理 -->
<property name="typeAliasesPackage"
value="cn.ccut.domain"></property>
</bean>
<!--
配置 mybatis 掃描 mapper 接口的路徑
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage"
value="cn.ccut.mapper"></property>
</bean>
</beans>
mybatisPlus 適配 更改這里, 由原來的 SqlSessionFactoryBean改成MybatisSqlSessionFactoryBean
<!-- 配置SqlSessionFactoryBean
Mybatis提供的: org.mybatis.spring.SqlSessionFactoryBean
MP提供的:com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean
-->
<bean id="sqlSessionFactoryBean"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
3.通用增刪改實現
0.準備
1.繼承接口
基于Mybatis: 在Mapper接口中編寫CRUD相關的方法 提供Mapper接口所對應的SQL映射文件 以及 方法對應的SQL語句.
基于MP: 讓XxxMapper接口繼承 BaseMapper接口即可.
BaseMapper : 泛型指定的就是當前Mapper接口所操作的實體類類型
public interface EmployeeMapper extends BaseMapper<Employee> { }
2.BaseMapper 已經定義了各式各樣的方法不用我們去定義
1.insert方法
1.指定主鍵策略
@TableId:
* value: 指定表中的主鍵列的列名, 如果實體屬性名與列名一致,可以省略不指定.
* type: 指定主鍵策略.
@TableId(value="id" , type =IdType.AUTO)
private Integer id ; // int
2.指定表名注解
* MybatisPlus會默認使用實體類的類名到數據中找對應的表.
@TableName(value="tbl_employee")
public class Employee {
3.test
@Test
public void testInsert() throws SQLException {
//初始化Employee對象
Employee employee = new Employee();
employee.setLastName("MP");
employee.setEmail("mp@zhenqk.com");
employee.setGender(1);
employee.setAge(22);
// employee.setSalary(20000.0);
int a=employeeMapper.insert(employee);
}
4.再分析
屬性名是lastName ,而數據庫是last_name(駝峰命名法) ,原因是因為全局默認配置是true
5.如何配置 主鍵策略和表名
通過全局配置整個都起作用,若通過注解只能在當前類有作用
需要將配置作用在mybatis-session (注冊)
spring配置文件
<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 數據源 -->
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 別名處理 -->
<property name="typeAliasesPackage" value="com.atguigu.mp.beans"></property>
// -------------------------------------------------
<!-- 注入全局MP策略配置 -->
<property name="globalConfig" ref="globalConfiguration"></property>
</bean>
<!-- 定義MybatisPlus的全局策略配置-->
<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在2.3版本以后,dbColumnUnderline 默認值就是true 駝峰 -->
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主鍵策略 實體類中可以刪除了 -->
<property name="idType" value="0"></property>
<!-- 全局的表前綴策略配置 實體類中可以刪除了 -->
<property name="tablePrefix" value="tbl_"></property>
</bean>
// ------------
6.@TableField
指定別名
當數據庫不存在此字段,選擇性過濾插入 就是舍棄掉
@TableField(exist=false)
7.插入獲取當前數據的主鍵值
8.insertAllColumn方法 -- 全字段的插入,
默認數據為空就不插入
// insert方法在插入時, 會根據實體類的每個屬性進行非空判斷,只有非空的屬性對應的字段才會出現到SQL語句中
//insertAllColumn方法在插入時, 不管屬性是否非空, 屬性所對應的字段都會出現到SQL語句中.
2.更新操作
1.updateById
會做非空判斷,選擇性更新操作
2.沒有賦值就為null(在全賦值情況下) updateAllColumnById
//初始化修改對象
Employee employee = new Employee();
employee.setId(7);
employee.setLastName("小澤老師");
employee.setEmail("xz@sina.com");
employee.setGender(0);
Integer result = employeeMapper.updateAllColumnById(employee);
System.out.println("result: " + result );
沒有給值就為ull,為每一個字段賦值
3.通用的查詢操作
1.selectById(Serialize id)
2.通過多列進行查詢 id+lastName selectOne |
注意: 最多只能查詢一條,不能查詢多條(當條件相同的列有多條的時候)
3.通過多個id 進行查詢 in () ===mybatis foreach
4.通過map封裝條件查詢----selectByMap
注意:是數據庫類名
分頁查詢--selectPage
wapper 條件構造器
注意:當前頁碼,每頁顯示的條數,不是通過limit
是一種內存分頁 RowBound,物理分頁借助分頁插件
不推薦使用
4.通用刪除
1.根據id 進行刪除--- deleteById
2.根據條件進行刪除-----deleteByMap
where 進行可拼接
3.批量刪除 deleteBatchIds
底層 in
5.MP 啟動自動注入SQL原理分析
??啟動的時候就注入進來了,繼承了BaseMapper 中提供的CRUB方法,方法來源于BaseMapper有方法就必須有SQL,因為Mabatis最終還是需要通過SQL語句操作實現,要熟悉:MyBatis 執行流程, 透過現象看本質
Configuration 全局配置--->MappedStatement
?AutoSqlInjector
?SqlMethod 枚舉對象 MP支持的SQL方法
?TableInfo 數據庫表放射信息,可以獲取數據庫表的相關信息
?SqlSource :sql 處理對象
?MapperbuilderAssistant 用于緩存sql參數 查詢方法的結果集處理等
? 通過MapperbuilderAssistant 將每一個MappedStatement添加到Configuration中
?MappedStatements
共17 種方法
wrapper 實體對象封裝操作類
4.條件構造器
1.EntityWrapper 簡介
Mybatis-Plus 通過 EntityWrapper(簡稱 EW,MP 封裝的一個查詢條件構造器)或者Condition(與 EW 類似) 來讓用戶自由的構建查詢條件,簡單便捷,沒有額外的負擔,
能夠有效提高開發效率
實體包裝器,主要用于處理 sql 拼接,排序,實體參數查詢等
注意: 使用的是數據庫字段,不是 Java 屬性!
條件參數的說明
用的最多是查詢操作
2.需求
??現有一個需求,我們需要分頁查詢 tbl_employee 表中,年齡在 18~50 之間性別為男且姓名為 xx 的所有用戶,這時候我們該如何實現上述需求呢?
??MyBatis : 需要在 SQL 映射文件中編寫帶條件查詢的 SQL,并基于 PageHelper 插件完成分頁. 實現以上一個簡單的需求,往往需要我們做很多重復單調的工作。普通的 Mapper能夠解決這類痛點嗎?
??MP: 依舊不用編寫 SQL 語句, MP 提供了功能強大的條件構造器 EntityWrapper
利用條件構造器查詢
//我們需要分頁查詢tbl_employee表中,年齡在18~50之間且性別為男且姓名為Tom的所有用戶
// 是數據庫字段名
List<Employee> emps =employeeMapper.selectPage(new Page<Employee>(1, 2),
new EntityWrapper<Employee>()
.between("age", 18, 50)
.eq("gender", 1)
.eq("last_name", "Tom")
);
System.out.println(emps);
3. 帶條件的查詢selectList方法
小語法
or() 或者 關系 前面是一起的,后面是一起
orNew()
// 查詢tbl_employee表中, 性別為女并且名字中帶有"老師" 或者 郵箱中帶有"a"
List<Employee> emps = employeeMapper.selectList(
new EntityWrapper<Employee>()
.eq("gender", 0)
.like("last_name", "老師")
//.or()
// SQL: (gender = ? AND last_name LIKE ? OR email LIKE ?)
.orNew()
// SQL: (gender = ? AND last_name LIKE ?) OR (email LIKE ?) or New 另起一個括號
.like("email", "a")
);
System.out.println(emps);
4. 帶條件的修改
??update
把tom 修改成蒼老師
Employee employee = new Employee();
employee.setLastName("蒼老師");
employee.setEmail("cls@sina.com");
employee.setGender(0);
employeeMapper.update(employee,
new EntityWrapper<Employee>()
.eq("last_name", "Tom")
.eq("age", 44)
);
5.帶條件的刪除
employeeMapper.delete(
new EntityWrapper<Employee>()
.eq("last_name", "Tom")
.eq("age", 22)
);
6.其他常用方法
orderby 默認是升序列
orderSesc 降序
// 查詢性別為女的, 根據age進行排序(asc/desc), 簡單分頁
List<Employee> emps = employeeMapper.selectList(
new EntityWrapper<Employee>()
.eq("gender", 0)
.orderBy("age")
//.orderDesc(Arrays.asList(new String [] {"age"}))
.last("desc limit 1,3")
);
last 具有SQL注入風險
7.使用Condition的方式打開如上需求
List<Employee > emps = employeeMapper.selectPage(
new Page<Employee>(1,2),
Condition.create() // 獲取方式一樣 new EntityWrapper<Employee>()
.between("age", 18, 50)
.eq("gender", "1")
.eq("last_name", "Tom")
);
System.out.println(emps);
mp 條件構造器 Condition // EntityWrapper
逆向工程qbc
5.ActiveRecord 活動記錄
1.介紹
? Active Record(活動記錄),是一種領域模型模式,特點是一個模型類對應關系型數據庫中的
一個表,而模型類的一個實例對應表中的一行記錄。
? ActiveRecord 一直廣受動態語言( PHP 、 Ruby 等)的喜愛,而 Java 作為準靜態語言,
對于 ActiveRecord 往往只能感嘆其優雅,所以 MP 也在 AR 道路上進行了一定的探索
概念慢慢理解 慢慢會用就可以了
2.開啟AR模式
僅僅需要讓實體類繼承 Model 類且實現主鍵指定方法,即可開啟 AR 之旅
@TableName("tbl_employee")
public class Employee extends Model<Employee>{
// .. fields
// .. getter and setter
@Override
protected Serializable pkVal() {
return this.id;
}
3.基本CRUB
1. 插入操作
對象進行操作 自己插入自己
/**
* AR 插入操作
*/
@Test
public void testARInsert() {
Employee employee = new Employee();
employee.setLastName("王老師");
employee.setEmail("king@ccut.com");
employee.setGender(1);
employee.setAge(35);
boolean result = employee.insert();
System.out.println("result:" +result );
}
2.修改操作
/**
* AR 修改操作
*/
@Test
public void testARUpdate() {
Employee employee = new Employee();
employee.setId(20);
employee.setLastName("王大師");
employee.setEmail("king@ccut.com");
employee.setGender(1);
employee.setAge(36);
boolean result = employee.updateById();
System.out.println("result:" +result );
}
3.AR的查詢操作
1.selectById方法 and selectById(Serializable id)
第一種方式:
Employee employee = new Employee();
Employee result = employee.selectById(14);
System.out.println(result );
第二種方式:
Employee employee = new Employee();
employee.setId(14);
Employee result = employee.selectById();
System.out.println(result );
2.selectAll()
Employee employee = new Employee();
List<Employee> emps = employee.selectAll();
System.out.println(emps);
3.selectList and selectCount 方法
Employee employee = new Employee();
List<Employee > emps=
employee.selectList(new EntityWrapper<Employee>().like("last_name", "老師"));
System.out.println(emps);
Employee employee = new Employee();
Integer result = employee.selectCount(new EntityWrapper<Employee>().eq("gender", 0));
// 全表統計 就不要加條件了
System.out.println("result: " +result );
4. 刪除操作
1.注意: 刪除不存在的數據 邏輯上也是屬于成功的.
2.deleteById(id) 和deleteById()
第一種方式
Employee employee = new Employee();
boolean result = employee.deleteById(2);
第二種方式
刪除不存在在邏輯上也是成功的
Employee employee = new Employee();
employee.setId(2);
boolean result = employee.deleteById();
System.out.println("result:" +result );
3.delete(wrapper)
boolean result = employee.delete(new EntityWrapper<Employee>().like("last_name", "小"));
System.out.println(result );
4.分頁的復雜操作
@Test
public void testARPage() {
Employee employee = new Employee();
Page<Employee> page = employee.selectPage(new Page<>(1, 1),
new EntityWrapper<Employee>().like("last_name", "老"));
List<Employee> emps = page.getRecords(); //獲取查詢數據庫 查詢回來的記錄返回
System.out.println(emps);
}
返回的是一個page 對象,更加的方便使用分頁信息
5.小結:
AR 模式提供了一種更加便捷的方式實現 CRUD 操作,其本質還是調用的 Mybatis 對
應的方法,類似于語法糖
語法糖是指計算機語言中添加的某種語法,這種語法對原本語言的功能并沒有影響.可以更方便開發者使用,可以避免出錯的機會,讓程序可讀性更好.
到此,我們簡單領略了 Mybatis-Plus 的魅力與高效率,值得注意的一點是:我們提供了強大的代碼生成器,可以快速生成各類代碼,真正的做到了即開即用
6.代碼生成器
通過java代碼來實現的
逆向軟件通過 xml而配置
1.MP與MBG的簡單比較
??1) MP 提供了大量的自定義設置,生成的代碼完全能夠滿足各類型的需求
??2) MP 的代碼生成器 和 Mybatis MBG 代碼生成器:MP 的代碼生成器都是基于 java 代碼來生成。MBG 基于 xml 文件進行代碼生成
?MyBatis 的代碼生成器可生成: 實體類、Mapper 接口、Mapper 映射文件
?MP 的代碼生成器可生成: 實體類(可以選擇是否支持 AR)、Mapper 接口、Mapper 映射文件、 Service 層、Controller 層.
??3) 表及字段命名策略選擇
??在 MP 中,我們建議數據庫表名 和 表字段名采用駝峰命名方式, 如果采用下劃線命名方式 請開啟全局下劃線開關,如果表名字段名命名方式不一致請注解指定,我們建議最好保持一致。
??這么做的原因是為了避免在對應實體類時產生的性能損耗,這樣字段不用做映射就能直接和實體類對應。當然如果項目里不用考慮這點性能損耗,那么你采用下滑線也是沒問題的,只需要在生成代碼時配置 ; dbColumnUnderline 屬性就可以
2. 準備
導入代碼產生器依賴
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
加入日志 sl4f 日志輸出依賴
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
3. GlobalConfig全局配置參數
1.全局配置
//1. 全局配置
GlobalConfig config = new GlobalConfig();
config.setActiveRecord(true) // 是否支持AR模式
.setAuthor("weiyunhui") // 作者
.setOutputDir("D:\workspace_mp\mp03\src\main\java") // 生成路徑
.setFileOverride(true) // 文件覆蓋
.setIdType(IdType.AUTO) // 主鍵策略
.setServiceName("%sService") // 設置生成的service接口的名字的首字母是否為I
// IEmployeeService
.setBaseResultMap(true)
.setBaseColumnList(true);
2.數據源配置
//2. 數據源配置
DataSourceConfig dsConfig = new DataSourceConfig();
dsConfig.setDbType(DbType.MYSQL) // 設置數據庫類型
.setDriverName("com.mysql.jdbc.Driver")
.setUrl("jdbc:mysql://localhost:3306/mp")
.setUsername("root")
.setPassword("1234");
3.策略配置
原來在配置文件
StrategyConfig stConfig = new StrategyConfig();
stConfig.setCapitalMode(true) //全局大寫命名
.setDbColumnUnderline(true) // 指定表名 字段名是否使用下劃線
.setNaming(NamingStrategy.underline_to_camel) // 數據庫表映射到實體的命名策略
.setTablePrefix("tbl_")
.setInclude("tbl_employee"); // 生成的表 所使用的表
4.包名策略設置
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("com.atguigu.mp")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("beans")
.setXml("mapper");
// .setBaseResultMap(true) xml
// .setBaseColumnList(true);
5.整合配置
//5. 整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(pkConfig);
//6. 執行
ag.execute();
導入包 spring-webmvc
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {
//不用再進行mapper的注入.
/**
* EmployeeServiceImpl 繼承了ServiceImpl
* 1. 在ServiceImpl中已經完成Mapper對象的注入,直接在EmployeeServiceImpl中進行使用
* 2. 在ServiceImpl中也幫我們提供了常用的CRUD方法, 基本的一些CRUD方法在Service中不需要我們自己定義.
*
*
*/
}
Controller
@Controller
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
// public String login() {
//
// //employeeService.select
// }
}
更多詳情信息可以看文檔
7.插件擴展
1.介紹
??1) 插件機制: Mybatis 通過插件(Interceptor) 可以做到攔截四大對象相關方法的執行,根據需求,完 成相關數據的動態改變。 Executor StatementHandler ParameterHandler ResultSetHandler
?? 2) 插件原理 四大對象的每個對象在創建時,都會執行 interceptorChain.pluginAll(),會經過每個插 件對象的 plugin()方法,目的是為當前的四大對象創建代理。代理對象就可以攔截到四 大對象相關方法的執行,因為要執行四大對象的方法需要經過代理.
2.分頁插件
??物理分頁
com.baomidou.mybatisplus.plugins.PaginationInterceptor
??注冊有兩種方式
1.mybaiss 配置文件
<configuration>
<!-- <plugins>
<plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></plugin>
</plugins> -->
</configuration>
?2.放在spring中 數組可以用list
<!-- 插件注冊 -->
<property name="plugins">
<list>
<!-- 注冊分頁插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
</list>
</property>
</bean>
?測試方法
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = ctx.getBean("employeeMapper",EmployeeMapper.class);
Page<Employee> page = new Page<>(1,1);
List<Employee > emps =
employeeMapper.selectPage(page, null);
System.out.println(emps);
?把mapper 中開啟二級緩存去掉
注冊分頁插件后,Page對象的使用
@Test
public void testPage() {
Page<Employee> page = new Page<>(1,1);
List<Employee > emps =
employeeMapper.selectPage(page, null);
System.out.println(emps);
System.out.println("===============獲取分頁相關的一些信息======================");
System.out.println("總條數:" +page.getTotal());
System.out.println("當前頁碼: "+ page.getCurrent());
System.out.println("總頁碼:" + page.getPages());
System.out.println("每頁顯示的條數:" + page.getSize());
System.out.println("是否有上一頁: " + page.hasPrevious());
System.out.println("是否有下一頁: " + page.hasNext());
//將查詢的結果封裝到page對象中
page.setRecords(emps);
}
3.執行分析插件(不建議生產環境用)
1) com.baomidou.mybatisplus.plugins.SqlExplainInterceptor
2) SQL 執行分析攔截器,只支持 MySQL5.6.3 以上版本
3) 該插件的作用是分析 DELETE UPDATE 語句,防止小白
或者惡意進行 DELETE UPDATE 全表操作
4) 只建議在開發環境中使用,不建議在生產環境使用
5) 在插件的底層 通過 SQL 語句分析命令:Explain 分析當前的 SQL 語句,
根據結果集中的 Extra 列來斷定當前是否全表操作。
插件注冊
<!-- 插件注冊 -->
<property name="plugins">
<list>
<!-- 注冊分頁插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
<!-- 注冊執行分析插件 發現對全表的操作就停止 -->
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<property name="stopProceed" value="true"></property>
</bean>
測試
/**
* 測試SQL執行分析插件 發現全表刪除操作 就停止
*/
@Test
public void testSQLExplain() {
employeeMapper.delete(null); // 全表刪除
}
explain sql分析
4. 性能分析插件
?1) com.baomidou.mybatisplus.plugins.PerformanceInterceptor
?2) 性能分析攔截器,用于輸出每條 SQL 語句及其執行時間
?3) SQL 性能執行分析,開發環境使用,超過指定時間,停止運行。有助于發現問題----測試可以用
注冊插件
<!-- 注冊性能分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"> 是否格式化sql語句
<property name="format" value="true"></property>
<!-- <property name="maxTime" value="5"></property> --> 每條sql語句執行所消耗的時間
</bean>
時間是 5毫秒
測試
/**
* 測試 性能分析插件
*/
@Test
public void testPerformance() {
Employee employee = new Employee();
employee.setLastName("瑪利亞老師");
employee.setEmail("mly@sina.com");
employee.setGender("0");
employee.setAge(22);
employeeMapper.insert(employee);
}
5.樂觀鎖插件
?1) com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor
?2) 如果想實現如下需求: 當要更新一條記錄的時候,希望這條記錄沒有被別人更新
?3) 樂觀鎖的實現原理: 取出記錄時,獲取當前 version 2 更新時,帶上這個 version 2 執行更新時, set version = yourVersion+1 where version = yourVersion 如果 version 不對,就更新失敗
?4) @Version 用于注解實體字段,必須要有。
domian
加上字段
? - 數據庫也要加上 version int 11
注冊樂觀鎖
<!-- 基于注解的事務管理 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
<!-- 配置SqlSessionFactoryBean
Mybatis提供的: org.mybatis.spring.SqlSessionFactoryBean
MP提供的:com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean
-->
<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 數據源 -->
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 別名處理 -->
<property name="typeAliasesPackage" value="com.atguigu.mp.beans"></property>
<!-- 注入全局MP策略配置 -->
<property name="globalConfig" ref="globalConfiguration"></property>
<!-- 插件注冊 -->
<property name="plugins">
<list>
<!-- 注冊分頁插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
<!-- 注冊執行分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<property name="stopProceed" value="true"></property>
</bean>
<!-- 注冊性能分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
<property name="format" value="true"></property>
<!-- <property name="maxTime" value="5"></property> -->
</bean>
<!-- 注冊樂觀鎖插件 -->
<bean class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor">
</bean>
</list>
</property>
</bean>
?測試比對
/**
* 測試 樂觀鎖插件
*/
@Test
public void testOptimisticLocker() {
//更新操作
Employee employee = new Employee();
employee.setId(15);
employee.setLastName("TomAA");
employee.setEmail("tomAA@sina.com");
employee.setGender("1");
employee.setAge(22);
employee.setVersion(3);
employeeMapper.updateById(employee);
}
8.全局配置
? 根據 MybatisPlus 的 AutoSqlInjector 可以自定義各種你想要的 sql ,注入到全局中,相當于自 定義 Mybatisplus 自動注入的方法。
? 之前需要在 xml 中進行配置的 SQL 語句,現在通過擴展 AutoSqlInjector 在加載 mybatis 環境 時就注入。
8.1 AutoSqlInjector
在 Mapper 接口中定義相關的 CRUD 方法
擴展 AutoSqlInjector inject 方法,實現 Mapper 接口中方法要注入的 SQL
新建包 injector/MySqlInjector.java
/**
* 自定義全局操作
*/
public class MySqlInjector extends AutoSqlInjector{
/**
* 擴展inject 方法,完成自定義全局操作
a模仿 injectDeleteSql
*/
@Override
public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass,
Class<?> modelClass, TableInfo table) {
//將EmployeeMapper中定義的deleteAll, 處理成對應的MappedStatement對象,加入到configuration對象中。
//注入的SQL語句
String sql = "delete from " +table.getTableName();
//注入的方法名 一定要與EmployeeMapper接口中的方法名一致
String method = "deleteAll" ;
//構造SqlSource對象
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
//構造一個刪除的MappedStatement
this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
?3) 在 MP 全局策略中,配置 自定義注入器
<!-- 定義MybatisPlus的全局策略配置-->
<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在2.3版本以后,dbColumnUnderline 默認值就是true -->
<property name="dbColumnUnderline" value="true"></property>
<!-- Mysql 全局的主鍵策略 -->
<!-- <property name="idType" value="0"></property> -->
<!-- Oracle全局主鍵策略 -->
<property name="idType" value="1"></property>
<!-- 全局的表前綴策略配置 -->
<property name="tablePrefix" value="tbl_"></property>
<!--注入自定義全局操作
<property name="sqlInjector" ref="mySqlInjector"></property>
<property name="keyGenerator" ref="oracleKeyGenerator"></property>
</bean>
<!-- 定義自定義注入器 -->
<bean id="mySqlInjector" class="com.ccut.mp.injector.MySqlInjector"></bean>
測試
/**
* 測試自定義全局操作
*/
@Test
public void testMySqlInjector() {
Integer result = employeeMapper.deleteAll();
System.out.println("result: " +result );
}
沒有寫映射文件mapper 是在啟動的時候就注入了
8.2 自定義注入器的應用之 邏輯刪除
假刪除、邏輯刪除: 并不會真正的從數據庫中將數據刪除掉,而是將當前被刪除的這條數據 中的一個邏輯刪除字段置為刪除狀態. tbl_user logic_flag = 1 → -1
com.baomidou.mybatisplus.mapper.LogicSqlInjector
logicDeleteValue 邏輯刪除全局值
logicNotDeleteValue 邏輯未刪除全局值
在 POJO 的邏輯刪除字段 添加 @TableLogic 注解
會在 mp 自帶查詢和更新方法的 sql 后面,追加『邏輯刪除字段』=『LogicNotDeleteValue 默認值』 刪除方法: deleteById()和其他 delete 方法, 底層 SQL 調用的是 update tbl_xxx set 『邏輯刪除字段』=『logicDeleteValue 默認值』
8.3 實戰
全局sql 注入器的使用,配置
1.appcattionContex.xml
<!-- 定義MybatisPlus的全局策略配置-->
<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在2.3版本以后,dbColumnUnderline 默認值就是true -->
<property name="dbColumnUnderline" value="true"></property>
.....
<!-- 注入邏輯刪除 -->
<property name="sqlInjector" ref="logicSqlInjector"></property>
<!-- 注入邏輯刪除全局值 -->
<property name="logicDeleteValue" value = "-1"></property>
<property name="logicNotDeleteValue" value="1"></property>
</bean>
<!-- 邏輯刪除 -->
<bean id="logicSqlInjector" class="com.baomidou.mybatisplus.mapper.LogicSqlInjector"></bean>
創建表:
logflag 字段
實體類
usermapper
直接繼承BaseMapper<User>
/**
* 測試邏輯刪除
*/
@Test
public void testLogicDelete() {
// Integer result = userMapper.deleteById(1); 變成了更新狀態
// System.out.println("result:" +result );
User user = userMapper.selectById(1); //查詢不到的 null 判斷 and 邏輯字段等于1
System.out.println(user);
}
9.公共字段填充
希望有些默認的值給他填充上去
?9.1 元數據處理器接口 com.baomidou.mybatisplus.mapper.MetaObjectHandler
insertFill(MetaObject metaObject) 插入的填充
updateFill(MetaObject metaObject) 更新的時候填充
metaobject: 元對象. 是 Mybatis 提供的一個用于更加方便,更加優雅的訪問對象的屬性, 給對象的屬性設置值 的一個對象. 還會用于包裝對象. 支持對 Object 、Map、Collection 等對象進行包裝
本質上 metaObject 獲取對象的屬性值或者是給對象的屬性設置值,最終是要 通過 Reflector 獲取到屬性的對應方法的 Invoker, 最終 invoke.
?9.2 開發步驟
注解填充字段 @TableFile(fill = FieldFill.INSERT) 查看 FieldFill
自定義公共字段填充處理器
MP 全局注入 自定義公共字段填充處理器
1.實現步驟
實體類
公共字段處理器
全局配置
放在全局策略上
<!-- 注入公共字段填充處理器 -->
<property name="metaObjectHandler" ref="myMetaObjectHandler"></property>
<!-- 注入Oracle主鍵Sequence -->
<property name="keyGenerator" ref="oracleKeyGenerator"></property>
</bean>
<!-- 公共字段填充 處理器 -->
<bean id="myMetaObjectHandler" class="com.atguigu.mp.metaObjectHandler.MyMetaObjectHandler"> </bean>
2.自定義填充處理器的實現
/**
* 自定義公共字段填充處理器
*/
public class MyMetaObjectHandler extends MetaObjectHandler {
/**
* 插入操作 自動填充
*/
@Override
public void insertFill(MetaObject metaObject) {
//獲取到需要被填充的字段的值
Object fieldValue = getFieldValByName("name", metaObject);
if(fieldValue == null) {
System.out.println("*******插入操作 滿足填充條件*********");
setFieldValByName("name", "weiyunhui", metaObject);
}
}
/**
* 修改操作 自動填充
*/
@Override
public void updateFill(MetaObject metaObject) {
Object fieldValue = getFieldValByName("name", metaObject);
if(fieldValue == null) {
System.out.println("*******修改操作 滿足填充條件*********");
setFieldValByName("name", "weiyh", metaObject);
}
}
}
3.測試
/**
* 測試公共字段填充
有名字就不會進行填充
*/
@Test
public void testMetaObjectHandler() {
User user = new User();
//user.setName("Tom");
// userMapper.insert(user);
user.setId(5);
user.setLogicFlag(1);
userMapper.updateById(user);
}
對某個字段修改,就不適合了,它認為沒有值就填充了
10. Oracle 主鍵 Sequence
MySQL: 支持主鍵自增。 IdType.Auto
Oracle: 序列(Sequence) 不支持主鍵自增
1.步驟
實體類配置主鍵 Sequence @KeySequence(value=”序列名”,
clazz=xxx.class 主鍵屬性類 型)
全局 MP 主鍵生成策略為 IdType.INPUT
多個 ,也就是整個環境都在使用oracle數據庫
<!-- Oracle全局主鍵策略 -->
<property name="idType" value="1"></property>
全局 MP 中配置 Oracle 主鍵 Sequence com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
<!-- 注入Oracle主鍵Sequence -->
<property name="keyGenerator" ref="oracleKeyGenerator"></property>
</bean>
<!-- 配置Oracle主鍵Sequence -->
<bean id="oracleKeyGenerator" class="com.baomidou.mybatisplus.incrementer.OracleKeyGenerator"></bean>
可以將@keySequence 定義在父類中,可實現多個子類對應的多個表公用一個 Sequence
2.Oracle 驅動依賴問題
3.配置連接信息
orcl.driver=oracle.jdbc.OracleDriver
orcl.url=jdbc:oracle:thin:@localhost:1521:xe
orcl.username=system
orcl.password=1234
4.創建表及序列
5.演示.
/**
* 測試Oracle 主鍵 Sequence
*/
@Test
public void testOracle() {
User user = new User();
user.setLogicFlag(1);
user.setName("OracleSEQ");
userMapper.insert(user);
}
6. 擴展 多個實體類公用一個序列
11. idea
MybatisX 輔助 idea 快速開發插件,
為效率而生. 可以實現 java 與 xml 跳轉,根據 Mapper 接口中的方法自動生成 xml 結構.
官方安裝: File -> Settings -> Plugins -> Browse Repositories.. 輸入 mybatisx 安裝下載
Jar 安裝: File -> Settings -> Plugins -> Install plugin from disk.. 選中 mybatisx..jar 安裝
不停的思考,就會不停的進步
總結
以上是生活随笔為你收集整理的MyBatis Plus的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django 之 CBV
- 下一篇: mysql绿色版下载及应用