
MyBatis-Plus 通用 Service 与常用注解目录1 通用 Service1.1 IService 接口简介1.2 创建 Service 接口与实现类1.3 测试通用 Service1.3.1 查询记录数1.3.2 批量插入1.3.3 修改操作1.3.4 批量删除2 常用注解2.1 TableName —— 表名映射2.1.1 注解方式2.1.2 全局配置方式2.2 TableId —— 主键映射2.2.1 value 属性指定主键字段名2.2.2 type 属性指定主键生成策略2.2.3 雪花算法简介2.3 TableField —— 字段映射2.4 TableLogic —— 逻辑删除1 通用 Service1.1 IService 接口简介MyBatis-Plus 封装了IService接口在BaseMapper的 CRUD 基础上做了进一步封装。Service 层的方法采用不同的前缀命名来区分 Mapper 层避免混淆前缀含义示例方法get查询单行getById()list查询集合list()remove删除removeById()、removeBatchByIds()save插入save()、saveBatch()update修改updateById()count计数count()page分页查询page()IService接口由ServiceImpl类实现。如果内置方法无法满足业务需求可以在自定义的 Service 接口中扩展方法。1.2 创建 Service 接口与实现类业务接口/** * UserService 继承 IService获得模板提供的基础功能 */publicinterfaceUserServiceextendsIServiceUser{}业务实现类/** * ServiceImpl 实现了 IService提供了基础功能的实现 * 若 ServiceImpl 无法满足业务需求可在 UserService 中定义方法并在此类中实现 */ServicepublicclassUserServiceImplextendsServiceImplUserMapper,UserimplementsUserService{}ServiceImplUserMapper, User的两个泛型参数分别是 Mapper 接口和实体类。1.3 测试通用 Service1.3.1 查询记录数AutowiredprivateUserServiceuserService;TestpublicvoidtestGetCount(){longcountuserService.count();System.out.println(总记录数count);}1.3.2 批量插入TestpublicvoidtestSaveBatch(){ArrayListUserusersnewArrayList();for(inti0;i5;i){UserusernewUser();user.setName(abci);user.setAge(20i);users.add(user);}// SQL: INSERT INTO t_user (username, age) VALUES (?, ?)userService.saveBatch(users);}saveBatch()会将集合中的数据分批执行插入是 Service 层相比 Mapper 层额外提供的便利方法。1.3.3 修改操作TestpublicvoidtestUpdate(){UserusernewUser(1778690964123090947L,miller,30,millerqq.com);// SQL: UPDATE user SET name?, age?, email? WHERE id?userService.updateById(user);}1.3.4 批量删除TestpublicvoidtestDelete(){ListLongidsnewArrayList();ids.add(1778690963879821313L);ids.add(1778690964114702337L);ids.add(1778690964114702338L);ids.add(1778690964123090946L);ids.add(1778690964123090947L);// SQL: DELETE FROM user WHERE id IN (?, ?, ?, ?, ?)userService.removeBatchByIds(ids);}2 常用注解MyBatis-Plus 提供了一系列注解用于处理实体类与数据库表之间的映射关系。核心注解汇总如下注解作用位置功能TableName类指定实体类对应的表名TableId主键字段指定主键字段名及主键生成策略TableField普通字段指定实体属性对应的表字段名TableLogic逻辑删除字段标记该字段为逻辑删除标志位2.1 TableName —— 表名映射MyBatis-Plus 默认将实体类的类名作为表名。当实体类名与表名不一致时例如实体类为User表名为tb_user查询会报错Table mybatis_plus.user doesnt exist有两种解决方式。2.1.1 注解方式在实体类上添加TableName注解指定对应的表名DataNoArgsConstructorAllArgsConstructorTableName(tb_user)publicclassUser{privateLongid;privateStringname;privateIntegerage;privateStringemail;}2.1.2 全局配置方式如果所有表都有统一前缀如tb_可以在application.yml中全局配置无需逐个添加注解mybatis-plus:global-config:db-config:table-prefix:tb_2.2 TableId —— 主键映射MyBatis-Plus 默认将名为id的字段作为主键。当主键字段名不是id例如为uid时需要使用TableId注解手动指定。2.2.1 value 属性指定主键字段名当实体属性名与数据库主键字段名不一致时通过value属性指定数据库中的字段名DataNoArgsConstructorAllArgsConstructorpublicclassUser{TableId(valueuid)// 实体属性为 id数据库字段为 uidprivateLongid;privateStringname;privateIntegerage;privateStringemail;}2.2.2 type 属性指定主键生成策略type属性用于指定主键的生成策略。MyBatis-Plus 通过IdType枚举类定义了以下策略IdType 值描述AUTO数据库 ID 自增。前提表中主键字段必须设置为自增否则插入时会报错NONE无状态未设置主键类型。等同于跟随全局配置全局默认为ASSIGN_IDINPUT插入前由用户自行设置主键值ASSIGN_ID自动分配 ID适用于Long、Integer、String类型。默认策略使用雪花算法ASSIGN_UUID自动分配 UUID适用于String类型使用自增策略的示例DataNoArgsConstructorAllArgsConstructorpublicclassUser{TableId(valueuid,typeIdType.AUTO)privateLongid;privateStringname;privateIntegerage;privateStringemail;}也可以在application.yml中全局配置主键策略mybatis-plus:global-config:db-config:table-prefix:tb_id-type:autoIdType枚举源码如下publicenumIdType{AUTO(0),NONE(1),INPUT(2),ASSIGN_ID(3),ASSIGN_UUID(4);}2.2.3 雪花算法简介雪花算法Snowflake是 Twitter 开源的分布式主键生成算法能够保证不同表的主键不重复且同一表的主键按时间有序。产生背景随着数据量增长单表可能需要进行水平分表。分表后需要一种全局唯一的 ID 生成方案常见方案有三种方案原理优点缺点主键自增分段按固定范围分配 ID 段如 1~999999 放表11000000~1999999 放表2可平滑扩充新表原有数据不受影响数据分布可能不均匀取模用ID % 表数量决定数据归属数据分布均匀扩充新表时所有数据需要重新分布雪花算法64 bit 组合符号位(1) 时间戳(41) 机器ID(10) 序列号(12)按时间有序分布式环境无 ID 碰撞效率高依赖机器时钟雪花算法 ID 结构64 bit1 bit符号位固定为 0正数41 bit时间戳毫秒级存储当前时间与起始时间的差值约可使用 69.73 年10 bit机器 ID5 bit 数据中心 5 bit 机器 ID支持 1024 个节点12 bit序列号每个节点每毫秒可生成 4096 个 ID2.3 TableField —— 字段映射MyBatis-Plus 要求实体类属性名与表字段名能对应上。存在两种情况情况一驼峰命名 ↔ 下划线命名自动转换实体类属性使用驼峰命名如userName表字段使用下划线命名如user_name时MyBatis-Plus会自动转换无需额外配置。DataNoArgsConstructorAllArgsConstructorpublicclassUser{TableId(valueuid)privateLongid;privateStringuserName;// 自动映射到表字段 user_nameprivateIntegerage;privateStringemail;}情况二属性名与字段名完全不一致需手动映射当属性名与字段名不满足驼峰/下划线转换规则时如属性为userName字段为name需要使用TableField注解手动指定DataNoArgsConstructorAllArgsConstructorpublicclassUser{TableId(valueuid)privateLongid;TableField(name)// 手动映射属性 userName → 字段 nameprivateStringuserName;privateIntegerage;privateStringemail;}2.4 TableLogic —— 逻辑删除数据删除有两种方式删除方式说明物理删除执行DELETE语句数据从数据库中真实移除不可恢复逻辑删除执行UPDATE语句将删除标志字段修改为已删除状态数据仍保留在表中使用TableLogic注解实现逻辑删除的步骤如下第一步在数据表中添加逻辑删除字段添加is_deleted字段默认值为 00 表示未删除1 表示已删除ALTERTABLEtb_userADDCOLUMNis_deletedINTDEFAULT0;第二步在实体类中添加对应属性并标注注解DataNoArgsConstructorAllArgsConstructorpublicclassUser{TableId(valueuid)privateLongid;TableField(name)privateStringuserName;privateIntegerage;privateStringemail;TableLogic// 标记为逻辑删除字段privateIntegerisDeleted;}第三步测试逻辑删除TestpublicvoidtestDeleteById(){intresultuserMapper.deleteById(7L);System.out.println(受影响行数result);}添加TableLogic注解后调用deleteById()等删除方法时MyBatis-Plus 实际执行的 SQL 会从-- 物理删除DELETEFROMtb_userWHEREuid?变为-- 逻辑删除UPDATEtb_userSETis_deleted1WHEREuid?ANDis_deleted0同时后续的查询操作会自动在 WHERE 条件中追加AND is_deleted 0自动过滤已逻辑删除的数据。