MyBatis-Plus:代码增强-抽取公共字段、Lambda获取字段名

x33g5p2x  于2022-06-27 转载在 其他  
字(8.3k)|赞(0)|评价(0)|浏览(522)

1. 增强

1.1 抽取公共字段(Model)

  1. @Getter
  2. @Setter
  3. @ToString
  4. @Accessors(chain = true)
  5. public class BaseDB<T extends BaseDB<?>> extends Model<T> {
  6. private static final long serialVersionUID = 3253505422347170166L;
  7. /** 主键 - 记录插入自动填充主键处理{@path application.yml} */
  8. @TableId
  9. private String id;
  10. @TableField(fill = FieldFill.INSERT)
  11. private String createTime;
  12. @TableField(fill = FieldFill.INSERT_UPDATE)
  13. private String updateTime;
  14. /** 记录是否被逻辑删除:0未删除 1逻辑删除 - 逻辑处理值定义{@path application.yml}*/
  15. @TableField
  16. @TableLogic
  17. private Integer isDel;
  18. @TableField("is_del")
  19. private IsDelEnum isDelEnum;
  20. /**
  21. * 乐观锁(记录的被修改数)
  22. *
  23. * 很鸡肋,需要通过代码查出记录然后手动取此对象的version给准备update的对象,或者直接在查出记录上进行update
  24. */
  25. @TableField
  26. @Version
  27. private Integer version;
  28. }

1.2 物理删除、逻辑删除同时支持(BaseMapper增强)

MyBatisPlusConfig.java

  1. @Configuration
  2. public class MyBatisPlusConfig {
  3. /**
  4. * SQL注入器
  5. * @return
  6. */
  7. @Bean
  8. public ISqlInjector enhanceISqlInjector() {
  9. return new DefaultSqlInjector() {
  10. @Override
  11. public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
  12. List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
  13. methodList.add(new DeleteByIdPhysical());
  14. methodList.add(new DeleteByIdLogic());
  15. return methodList;
  16. }
  17. };
  18. }
  19. }

DeleteByIdLogic.java

  1. /**
  2. * 作用:逻辑删除
  3. * 照抄官方{@link DeleteById}
  4. * @author LinRuChang
  5. * @version 1.0
  6. * @date 2022/06/14
  7. * @since 1.8
  8. **/
  9. public class DeleteByIdLogic extends AbstractMethod {
  10. @Override
  11. public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
  12. boolean withLogicDelete = tableInfo.isWithLogicDelete();
  13. //当前表支持逻辑删除,不支持则不注入
  14. if(withLogicDelete) {
  15. String sql;
  16. SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID;
  17. List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream()
  18. .filter(TableFieldInfo::isWithUpdateFill)
  19. .filter(f -> !f.isLogicDelete())
  20. .collect(toList());
  21. if (CollectionUtils.isNotEmpty(fieldInfos)) {
  22. String sqlSet = "SET " + SqlScriptUtils.convertIf(fieldInfos.stream()
  23. .map(i -> i.getSqlSet(EMPTY)).collect(joining(EMPTY)), "!@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(_parameter.getClass())", true)
  24. + tableInfo.getLogicDeleteSql(false, false);
  25. sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, tableInfo.getKeyColumn(),
  26. tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, true));
  27. } else {
  28. sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo),
  29. tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
  30. tableInfo.getLogicDeleteSql(true, true));
  31. }
  32. SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
  33. //return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
  34. return addUpdateMappedStatement(mapperClass, modelClass, "deleteByIdLogic", sqlSource);
  35. }
  36. //无逻辑删除字段,则不注入上述SQL,当调用work.linruchang.mybatisplussamplestest.dao.MyBaseMapper.deleteByIdLogic(java.io.Serializable)会报异常
  37. return null;
  38. }
  39. }

DeleteByIdPhysical.java

  1. /**
  2. * 作用:物理删除
  3. * 照抄{@link DeleteById}
  4. * @author LinRuChang
  5. * @version 1.0
  6. * @date 2022/06/14
  7. * @since 1.8
  8. **/
  9. public class DeleteByIdPhysical extends AbstractMethod {
  10. @Override
  11. public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
  12. String sql;
  13. SqlMethod sqlMethod = SqlMethod.DELETE_BY_ID;
  14. sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(),
  15. tableInfo.getKeyProperty());
  16. SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
  17. //return this.addDeleteMappedStatement(mapperClass, getMethod(sqlMethod), sqlSource);
  18. return this.addDeleteMappedStatement(mapperClass, "deleteByIdPhysical", sqlSource);
  19. }
  20. }


MyBaseMapper.java

  1. public interface MyBaseMapper<T> extends BaseMapper<T> {
  2. /**
  3. * 物理删除
  4. * @param id
  5. * @return
  6. */
  7. int deleteByIdPhysical(Serializable id);
  8. /**
  9. * 物理删除
  10. * @param entity
  11. * @return
  12. */
  13. int deleteByIdPhysical(T entity);
  14. /**
  15. * 逻辑删除
  16. *
  17. * 打算调这个方法,如果发现实体没有@TableLogic就会报异常出来提示用户
  18. * @param id
  19. * @return
  20. */
  21. int deleteByIdLogic(Serializable id);
  22. /**
  23. * 逻辑删除
  24. * @param entity
  25. * @return
  26. */
  27. int deleteByIdLogic(T entity);
  28. /**
  29. * 删除
  30. * @param id 主键ID
  31. * @param logicDeleteFlag null老逻辑 true逻辑删除 false物理删除
  32. * @return
  33. */
  34. default int deleteById(Serializable id, Boolean logicDeleteFlag) {
  35. //无指定则根据实体是否有@TableLogic进行评判(原逻辑)
  36. if(logicDeleteFlag == null) {return deleteById(id);}
  37. //指定逻辑删除、物理删除
  38. if(BooleanUtil.isTrue(logicDeleteFlag)) {
  39. Class currentMapperClazz = (Class) ReflectUtil.getFieldValue(ReflectUtil.getFieldValue(AopUtils.getTargetObject(this),"h"),"mapperInterface");
  40. Type typeArgument = TypeUtil.getTypeArgument(currentMapperClazz, 0);
  41. TableInfo tableInfo = TableInfoHelper.getTableInfo((Class<?>) typeArgument);
  42. if(tableInfo.isWithLogicDelete()) {
  43. return deleteByIdLogic(id);
  44. }
  45. throw new RuntimeException(StrUtil.format("当前表【{}】:不支持逻辑删除,请检查是否有配置逻辑删除字段", tableInfo.getTableName()));
  46. }else {
  47. return deleteByIdPhysical(id);
  48. }
  49. }
  50. }

SysUserDao.java

  1. @Mapper
  2. public interface SysUserDao extends MyBaseMapper<SysUser> {
  3. }

SysUserServiceTest.java

  1. @SpringBootTest
  2. class SysUserServiceTest {
  3. @Autowired
  4. SysUserDao sysUserDao;
  5. /**
  6. * 物理删除支持
  7. */
  8. @Test
  9. public void test9() {
  10. int insertFlag = sysUserDao.deleteById("dde66e90c44bcc535cce872541dd8b36", false);
  11. Console.log("删除情况:{}",insertFlag);
  12. }
  13. /**
  14. * 逻辑删除
  15. */
  16. @Test
  17. public void test10() {
  18. int insertFlag = sysUserDao.deleteById("dde66e90c44bcc535cce872541dd8b36", true);
  19. Console.log("逻辑删除情况:{}",insertFlag);
  20. }
  21. }

2. 工具类

2.1 Lambda获取字段名

代码
  1. /**
  2. * 作用:mybatisPlus工具类
  3. *
  4. * @author LinRuChang
  5. * @version 1.0
  6. * @date 2021/03/09
  7. * @since 1.8
  8. **/
  9. public class MyBatisPlusUtil {
  10. /**
  11. * Collection<SFunction> 转成 Array<SFunction>
  12. * 容器类型转换
  13. * @param beanFields
  14. * @param <T>
  15. * @return
  16. */
  17. public static <T> SFunction<T,?>[] sFunctionCollsToArray(Collection<SFunction<T, ?>> beanFields) {
  18. return Optional.ofNullable(beanFields)
  19. .map(bfs -> {
  20. SFunction<T,?>[] result = new SFunction[beanFields.size()];
  21. return bfs.toArray(result);
  22. })
  23. .orElse(new SFunction[0]);
  24. }
  25. /**
  26. * Bean字段转select的数据库列名【即Bean变量名【驼峰变量名】转成下划线形式】
  27. * 过程:sfunction =》Bean变量名 =》驼峰转下划线字符串
  28. * 注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
  29. * @param beanFields
  30. * @param <T>
  31. * @return 同一个表的多个表列名
  32. */
  33. public static <T> Set<String> sFunctionConvertToDataBaseFields(SFunction<T, ?>... beanFields) {
  34. return sFunctionConvertToDataBaseFields(beanFields == null ? Collections.emptySet():Arrays.asList(beanFields));
  35. }
  36. /**
  37. * Bean字段转select的数据库列名【即Bean变量名【驼峰变量名】转成下划线形式】
  38. * 过程:sfunction =》Bean变量名 =》驼峰转下划线字符串
  39. * 注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
  40. * @param beanFields 多个属性Bean变量
  41. * @param <T>
  42. * @return 同一个表的多个表列名
  43. */
  44. public static <T> Set<String> sFunctionConvertToDataBaseFields(Collection<SFunction<T, ?>> beanFields) {
  45. return Optional.ofNullable(beanFields).map(columnNames -> {
  46. return beanFields.stream()
  47. .map(MyBatisPlusUtil::sFunctionConverToDataBaseFieldFieldName)
  48. .collect(Collectors.toSet());
  49. }).orElse(Collections.emptySet());
  50. }
  51. /**
  52. * 将Bean变量名转成数据库列名【约定俗成的形式】 == 驼峰转下划线
  53. * 注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
  54. * @param beanFileldName 属性Bean变量
  55. * @param <T>
  56. * @return 数据库列名【下划线】
  57. */
  58. public static <T> String sFunctionConverToDataBaseFieldFieldName(SFunction<T, ?> beanFileldName) {
  59. return Optional.ofNullable(sFunctionConverToBeanFieldName(beanFileldName))
  60. .map(com.baomidou.mybatisplus.core.toolkit.StringUtils::camelToUnderline)
  61. .orElse(null);
  62. }
  63. /**
  64. * 获取Bean的变量名 == 一般都是驼峰变量名
  65. * 注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
  66. * @param beanFileldName 属性Bean变量
  67. * @param <T>
  68. * @return Bean属性名
  69. */
  70. public static <T> String sFunctionConverToBeanFieldName(SFunction<T, ?> beanFileldName) {
  71. return Optional.ofNullable(beanFileldName).map(bfe -> {
  72. SerializedLambda resolve = LambdaUtils.resolve(bfe);
  73. return PropertyNamer.methodToProperty(resolve.getImplMethodName());
  74. }).orElse(null);
  75. }
  76. }
使用
  1. @Service
  2. @Slf4j
  3. public class RoleService extends ServiceImpl<RoleDao, Role> {
  4. public List<Role> getList(SFunction<Role, ?>... fieldName) {
  5. return this.getBaseMapper().getList(MyBatisPlusUtil.sFunctionConvertToDataBaseFields(fieldName));
  6. }
  7. }
  8. @Mapper
  9. public interface RoleDao extends BaseMapper<Role> {
  10. public List<Role> getList(@Param("selectTableColumnNames") Set<String> selectTableColumnNames);
  11. }
  1. <!--注意列名拼接必须使用${变量},使用#{变量}的话,最后语句变成 select '列名1', '列名2' from 表名 这句是错的,应该变成 select 列名1, 列名2 from 表名 -->
  2. <select id="getList" resultType="top.linruchang.springdemo.db.Role">
  3. SELECT
  4. <choose>
  5. <when test="selectTableColumnNames != null and selectTableColumnNames.size() > 0">
  6. <foreach collection="selectTableColumnNames" separator="," item="columnName">
  7. ${columnName}
  8. </foreach>
  9. </when>
  10. <otherwise>*</otherwise>
  11. </choose>
  12. FROM role
  13. </select>

相关文章