看這篇內容以前建議先看一下 MyBatisPlus學習整理(一)
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) NULL DEFAULT NULL COMMENT '主鍵', `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名', `age` int(11) NULL DEFAULT NULL COMMENT '年齡', `email` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '郵箱', `manager_id` bigint(20) NULL DEFAULT NULL COMMENT '直屬上級id', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '建立時間', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改時間', `version` int(11) NULL DEFAULT 1 COMMENT '版本', `deleted` int(1) NULL DEFAULT 0 COMMENT '邏輯刪除標識(0,未刪除;1,已刪除)' ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; INSERT INTO `user` VALUES (1234, '大boss', 40, 'boss@163.com', NULL, '2019-10-02 10:08:02', '2019-10-02 10:08:05', 1, 0); INSERT INTO `user` VALUES (2345, '王天風', 25, 'wtf@163.com', 1234, '2019-10-02 10:09:07', '2019-10-02 10:09:10', 1, 0); INSERT INTO `user` VALUES (2346, '李藝偉', 28, 'lyw@163.com', 2345, '2019-10-02 10:10:09', '2019-10-02 10:10:12', 1, 0); INSERT INTO `user` VALUES (3456, '張雨綺', 31, 'zyq@163.com', 2345, '2019-10-02 10:10:54', '2019-10-02 10:10:58', 1, 0); INSERT INTO `user` VALUES (4566, '劉雨紅', 32, 'lyh@163.com', 2345, '2019-10-02 10:11:51', '2019-10-02 10:11:55', 1, 0); SET FOREIGN_KEY_CHECKS = 1;
項目延用MyBatisPlus學習整理(一)https://github.com/xiao-ren-wu/notebook/tree/master/mybatis-plus-demohtml
在配置文件中配置邏輯刪除和邏輯未刪除的值mysql
mybatis-plus: global-config: logic-not-delete-value: 0 logic-delete-value: 1
@TableLogic
@Data @EqualsAndHashCode(callSuper = false) public class User extends Model<User> { @TableId(type = IdType.AUTO) private Long id; @TableField(condition = SqlCondition.LIKE) private String name; private Integer age; private String email; private Long managerId; private LocalDateTime createTime; private LocalDateTime updateTime; private Integer version; @TableLogic private Integer deleted; }
@Test public void deleteById(){ userMapper.deleteById(4566L); }
邏輯刪除字段只是爲了標識數據是否被邏輯刪除,在查詢的時候,並不想也將該字段查詢出來。
咱們只須要在delete字段上增長@TableField(select = false)
mybatisplus在查詢的時候就會自動忽略該字段。git
@Test public void selectIgnoreDeleteTest(){ userMapper.selectById(3456L); }
自定義sql,MybatisPlus不會忽略deleted屬性,須要咱們手動忽略github
MybaitsPlus在咱們插入數據或者更新數據的時候,爲咱們提供了自動填充功能。相似MySQL提供的默認值同樣。
若是咱們須要使用自動填充功能,咱們須要在實體類的相應屬性上加@TableField
註解,並指定何時進行自動填充。mybatisPlus爲咱們提供了三種填充時機,在FieldFill
枚舉中spring
public enum FieldFill { /** * 默認不處理 */ DEFAULT, /** * 插入時填充字段 */ INSERT, /** * 更新時填充字段 */ UPDATE, /** * 插入和更新時填充字段 */ INSERT_UPDATE }
設置好以後,咱們還須要編寫具體的填充規則,具體是編寫一個填充類並交給Spring管理,而後實現MetaObjectHandler
接口中的insertFill
和updateFill
方法。
eg:sql
@Data @EqualsAndHashCode(callSuper = false) public class User extends Model<User> { ... @TableField(fill = INSERT) private LocalDateTime createTime; @TableField(fill = UPDATE) private LocalDateTime updateTime; ... }
@Component public class MyMetaObjHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { if(metaObject.hasSetter("createTime")){ setInsertFieldValByName("createTime", LocalDateTime.now(),metaObject); } } @Override public void updateFill(MetaObject metaObject) { if(metaObject.hasSetter("updateTime")){ setUpdateFieldValByName("updateTime",LocalDateTime.now(),metaObject); } } }
解釋一下爲何要用if判斷是否有對應的屬性
mybatisPlus在執行插入或者更新操做的時候,每次都會執行該方法,有些表中是沒有設置自動填充字段的,並且有些自動填充字段的值的獲取比較消耗系統性能,因此爲了避免必要的消耗,進行if判斷,決定是否須要填充。
有些時候咱們已經設置了屬性的值。不想讓mybatisPlus再自動填充,也就是說咱們沒有設置屬性的值,mybatisPlus進行填充,若是設置了那麼就用咱們設置的值。這種狀況咱們只須要在填充類中提早獲取默認值,而後使用該默認值就能夠了。數據庫
@Override public void updateFill(MetaObject metaObject) { if(metaObject.hasSetter("updateTime")){ Object updateTime = getFieldValByName("updateTime", metaObject); if(Objects.nonNull(updateTime)){ setUpdateFieldValByName("updateTime",updateTime,metaObject); }else{ setUpdateFieldValByName("updateTime",LocalDateTime.now(),metaObject); } } }
樂觀鎖適用於讀多寫少的狀況,更新數據的時候不使用「鎖「而是使用版本號來判斷是否能夠更新數據。經過不加鎖來減少數據更新時間和系統的性能消耗,進而提升數據庫的吞吐量。CAS機制就是一種典型的樂觀鎖的形式。
樂觀鎖是邏輯存在的一種概念,咱們若是使用樂觀鎖須要手動在表的加上version字段。mybatis
update user set balabala.... where balabala... and version = xxx
1.配置類中注入樂觀鎖插件app
@Bean public OptimisticLockerInterceptor optimisticLockerInterceptor(){ return new OptimisticLockerInterceptor(); }
@version
註解@Data @EqualsAndHashCode(callSuper = false) public class User extends Model<User> { ... @Version private Integer version; ... }
更新王天風的年齡ide
@Test public void testLock(){ int version = 1; User user = new User(); user.setEmail("wtf@163.com"); user.setAge(34); user.setId(2345L); user.setManagerId(1234L); user.setVersion(1); userMapper.updateById(user); }
數據庫中的version已經變成2
@Bean // @Profile({"dev,test"}) public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); // 格式化sql輸出 performanceInterceptor.setFormat(true); // 設置sql執行最大時間,單位(ms) performanceInterceptor.setMaxTime(5L); return performanceInterceptor; }
執行sql就能夠打印sql執行的信息了
https://mp.baomidou.com/guide/p6spy.html
<dependency> <groupId>p6spy</groupId> <artifactId>p6spy</artifactId> <version>3.8.5</version> </dependency>
spring: datasource: # driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root # url: jdbc:mysql://localhost:3306/test?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true driver-class-name: com.p6spy.engine.spy.P6SpyDriver url: jdbc:p6spy:mysql://localhost:3306/test?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
module.log=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,batch,resultset # 日期格式 dateformat=yyyy-MM-dd HH:mm:ss # 實際驅動可多個 #driverlist=org.h2.Driver # 是否開啓慢SQL記錄 outagedetection=true # 慢SQL記錄標準 2 秒 outagedetectioninterval=2
開啓性能分析會消耗系統的性能,因此性能分析插件要配合@Profile
註解執行使用的環境。
實現步驟:
eg: 編寫一個刪除表全部數據的方法
public class DeleteAllMethod extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { // 執行的sql String sql = "delete from " + tableInfo.getTableName(); // mapper接口方法名 String method = "deleteAll"; SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, mapperClass); return addDeleteMappedStatement(mapperClass, method, sqlSource); } }
@Component public class MySqlInject extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); methodList.add(new DeleteAllMethod()); return methodList; } }
public interface UserMapper extends BaseMapper<User> { /** * 刪除全部表數據 * * @return 影響行數 */ int deleteAll(); }
@Test public void deleteAll(){ userMapper.deleteAll(); }