您好,登錄后才能下訂單哦!
這篇文章主要介紹了mybatisplus復合主鍵CRUD的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
最近接到個挺有意思的需求,做用戶觀看學習視頻時長的一個數據埋點
儲存用戶觀看視頻時長、記錄的接口的調用肯定會特別頻繁,因為每間隔指定時間每個用戶都會調用,如果在這個接口里直接操作數據庫將會給我們的數據庫帶來一定的壓力,在我的代碼中是不允許的,而我是這樣完成這個需求的:
首先將用戶觀看視頻的時長、記錄存儲到阿里云的日志庫里,隨后以定時器從阿里云的日志庫中拉取用戶觀看視頻的數據同步到我們的數據庫中。
而就是最后這一步,同步數據到數據庫中,這里的數據量肯定是龐大的,所以我做了分表。
但是盡管做了分表數據量也不少,如果通過自增的主鍵id去編輯數據那么我在更新數據之前都要先從數據庫中查詢一次,然后在更新
在數據量大的情況下依然會給我們數據庫造成不少壓力,且這個定時器的執行時長將會拉大,這是我不能接受的
所以直接使用復合主鍵,以視頻id+用戶id去批量更新數據,這樣就會快很多,然而mybatisplus卻僅支持單一主鍵操作,這就讓我剛屢清楚的思路陷入了僵局
不過還是讓我找到了支持復合主鍵的框架
是不是看起來挺離譜的?啥玩意就plus-plus?別急,讓我們來看看代碼先
注意mybatisplus與mybatisplus-plus的版本兼容性
首先引入jar包
<dependency> <groupId>com.github.jeffreyning</groupId> <artifactId>mybatisplus-plus</artifactId> <version>1.5.1-RELEASE</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.1.0</version> </dependency>
PO對象
package com.youxue.model.lesson; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.github.jeffreyning.mybatisplus.anno.MppMultiId; import com.youxue.sharding.annotation.TableIndex; import com.youxue.sharding.annotation.TableIndices; import com.youxue.sharding.model.BaseShardingPo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.io.Serializable; import java.time.LocalDateTime; /** * <p> * 用戶觀看視頻時長 * <p/> * * @author dx * @since 2021/6/22 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("UserWatchVideoLog") @ApiModel(value="UserWatchVideoLogPo對象", description="用戶觀看視頻時長表") @TableIndices({ @TableIndex(name = "IX_USERID" ,ddl = "CREATE NONCLUSTERED INDEX [IX_USERID] ON UserWatchVideoLog ( [UserId] DESC)" ), @TableIndex(name = "IX_LESSONITEMID_USERID" ,ddl = "CREATE NONCLUSTERED INDEX [IX_LESSONITEMID_USERID] ON UserWatchVideoLog (LessonItemId ASC,UserId ASC)" ) }) public class UserWatchVideoLogPo implements Serializable, BaseShardingPo { @MppMultiId // 復合主鍵 @TableField("userId") @ApiModelProperty(value = "用戶id") private Integer userId; @TableField("lessonItemId") @ApiModelProperty(value = "子課程id") private Integer lessonItemId; @ApiModelProperty(value = "觀看時長 單位秒(s)") @TableField("seconds") private Integer seconds; @ApiModelProperty(value = "科目id") @TableField("subjectId") private Integer subjectId; @ApiModelProperty(value = "視頻觀看時長 單位秒(s)") @TableField("VideoProgress") private Integer videoProgress; @ApiModelProperty(value = "視頻來源 默認 0 ") @TableField("[Resource]") private Integer resource; @ApiModelProperty(value = "類型 默認 0 ") @TableField("[Type]") private Integer type; @ApiModelProperty(value = "創建時間") @TableField("CreateTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonDeserialize(using = LocalDateTimeDeserializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class) private LocalDateTime createTime; @ApiModelProperty(value = "修改時間") @TableField("UpdateTime") private LocalDateTime updateTime; }
@MppMultiId 注解即聲明為復合主鍵,并以@TableField 主鍵 聲明表字段
Service接口
package com.youxue.service.lesson; import com.github.jeffreyning.mybatisplus.service.IMppService; import com.youxue.model.lesson.UserWatchVideoLogPo; /** * <p> * 用戶觀看視頻記錄 服務類 * </p> * * @author dx * @since 2021-06-22 */ public interface IUserWatchVideoLogService extends IMppService<UserWatchVideoLogPo> { }
Impl類
package com.youxue.service.lesson.impl; import com.github.jeffreyning.mybatisplus.service.MppServiceImpl; import com.youxue.dao.lesson.UserWatchVideoLogMapper; import com.youxue.model.lesson.UserWatchVideoLogPo; import com.youxue.service.lesson.IUserWatchVideoLogService; import org.springframework.stereotype.Service; /** * <p> * 用戶觀看視頻記錄 服務類實現類 * </p> * * @author dx * @since 2021/6/22 */ @Service public class UserWatchVideoLogServiceImpl extends MppServiceImpl<UserWatchVideoLogMapper, UserWatchVideoLogPo> implements IUserWatchVideoLogService { }
Mapper接口
package com.youxue.dao.lesson; import com.github.jeffreyning.mybatisplus.base.MppBaseMapper; import com.youxue.model.lesson.UserWatchVideoLogPo; /** * <p> * 用戶觀看視頻記錄 Mapper 接口 * </p> * * @author dx * @since 2021-06-22 */ public interface UserWatchVideoLogMapper extends MppBaseMapper<UserWatchVideoLogPo> { }
service 繼承 IMppService ,mapper 繼承 MppBaseMapper,impl 繼承 MppServiceImpl 實現 service
并在啟動類上添加 @EnableMPP 注解
隨后直接在測試用例中運行(測試用例中未使用分表):
@Autowired private IUserWatchVideoLogService userWatchVideoLogService; @Test public void testUserWatchVideo() { UserWatchVideoLogPo userWatchVideoLogPo = new UserWatchVideoLogPo() .setUserId(6202238) .setLessonItemId(56303) .setSeconds(8888) .setResource(11); boolean create = userWatchVideoLogService.save(userWatchVideoLogPo); System.out.println(create); System.out.println("create result :" + create); System.out.println("================ create end =================="); // 斷點01 UserWatchVideoLogPo watchVideoLogPo = userWatchVideoLogService.selectByMultiId(userWatchVideoLogPo); System.out.println(watchVideoLogPo.toString()); System.out.println("================ retrieve end =================="); userWatchVideoLogPo.setSeconds(99999); userWatchVideoLogPo.setResource(22); // 斷點03 boolean upd = userWatchVideoLogService.updateByMultiId(userWatchVideoLogPo); System.out.println("upd result :" + upd); System.out.println("================ update end =================="); // 斷點03 boolean remove = userWatchVideoLogService.deleteByMultiId(userWatchVideoLogPo); System.out.println("remove result :" + remove); System.out.println("================ remove end =================="); }
我在save 方法后每個方法出都打了斷點,下面我們來看看運行結果
可以看到,添加方法打印的SQL與mybatisplus并沒有什么區別,隨后看一下數據庫中的數據
是正常的,我們來看一下查詢操作
可以看到,這里的where條件后跟的是兩個查詢條件,是不是很棒。再看看編輯操作
可以到編輯操作的SQL也是已兩個條件操作的,數據也更新過來了,最后刪除操作:
至此支持復合組件的CRUD就完成了
而 mybatisplus-plus 作為 mybatisplus 的升級版 新穎的功能肯定不止于此
根據多個字段聯合主鍵增刪改查
原生mybatisplus只支持一個主鍵,
mpp支持多個字段聯合主鍵(復合主鍵)增刪改查,
mapper需要繼承MppBaseMapper
實體類中聯合主鍵的字段需要用@MppMultiId注解修飾
如果需要在service使用多主鍵相關操作包括saveOrUpdateByMultiId和批量操作updateBatchByMultiId和saveOrUpdateBatchByMultiId,可以直接繼承IMppService接口
優化分頁插件實現在不分頁時進行排序操作
原生mybatisplus分頁與排序是綁定的,mpp優化了分頁插件,使用MppPaginationInterceptor插件
在不分頁的情況下支持排序操作
page參數size設置為-1可實現不分頁取全量數據,同時設置OrderItem可以實現排序自動填充優化功能 & 自動掃描Entity類構建ResultMap功能
原生mybatisplus只能做%s+1和now兩種填充,mybatisplus-plus在插入或更新時對指定字段進行自定義復雜sql填充。
需要在實體類字段上用原生注解@TableField設置fill=FieldFill.INSERT fill=FieldFill.UPDATE或fill=FieldFill.INSERT_UPDATE否則不會觸發自定義填充
mybatisplus-plus使用@InsertFill注解觸發插入時,執行注解中自定義的sql填充實體類字段
mybatisplus-plus使用@UpdateFill注解觸發更新時,執行注解中自定義的sql填充實體類字段
還可以自動填充主鍵字段,解決原生mybatisplus不支持多個主鍵的問題
使用ColNameUtil.pn靜態方法,獲取實體類中讀取方法對應的列名稱
感謝你能夠認真閱讀完這篇文章,希望小編分享的“mybatisplus復合主鍵CRUD的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。