概述
文章目录
- 1. 增强
- 1.1 抽取公共字段(Model)
- 1.2 物理删除、逻辑删除同时支持(BaseMapper增强)
- 2. 工具类
- 2.1 Lambda获取字段名
- 代码
- 使用
1. 增强
1.1 抽取公共字段(Model)
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class BaseDB<T extends BaseDB<?>> extends Model<T> {
private static final long serialVersionUID = 3253505422347170166L;
/** 主键 - 记录插入自动填充主键处理{@path application.yml} */
@TableId
private String id;
@TableField(fill = FieldFill.INSERT)
private String createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateTime;
/** 记录是否被逻辑删除:0未删除 1逻辑删除 - 逻辑处理值定义{@path application.yml}*/
@TableField
@TableLogic
private Integer isDel;
@TableField("is_del")
private IsDelEnum isDelEnum;
/**
* 乐观锁(记录的被修改数)
*
* 很鸡肋,需要通过代码查出记录然后手动取此对象的version给准备update的对象,或者直接在查出记录上进行update
*/
@TableField
@Version
private Integer version;
}
1.2 物理删除、逻辑删除同时支持(BaseMapper增强)
MyBatisPlusConfig.java
@Configuration
public class MyBatisPlusConfig {
/**
* SQL注入器
* @return
*/
@Bean
public ISqlInjector enhanceISqlInjector() {
return new DefaultSqlInjector() {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new DeleteByIdPhysical());
methodList.add(new DeleteByIdLogic());
return methodList;
}
};
}
}
DeleteByIdLogic.java
/**
* 作用:逻辑删除
*
照抄官方{@link DeleteById}
* @author LinRuChang
* @version 1.0
* @date 2022/06/14
* @since 1.8
**/
public class DeleteByIdLogic extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
boolean withLogicDelete = tableInfo.isWithLogicDelete();
//当前表支持逻辑删除,不支持则不注入
if(withLogicDelete) {
String sql;
SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID;
List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream()
.filter(TableFieldInfo::isWithUpdateFill)
.filter(f -> !f.isLogicDelete())
.collect(toList());
if (CollectionUtils.isNotEmpty(fieldInfos)) {
String sqlSet = "SET " + SqlScriptUtils.convertIf(fieldInfos.stream()
.map(i -> i.getSqlSet(EMPTY)).collect(joining(EMPTY)), "!@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(_parameter.getClass())", true)
+ tableInfo.getLogicDeleteSql(false, false);
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, tableInfo.getKeyColumn(),
tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, true));
} else {
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo),
tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
tableInfo.getLogicDeleteSql(true, true));
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
//return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
return addUpdateMappedStatement(mapperClass, modelClass, "deleteByIdLogic", sqlSource);
}
//无逻辑删除字段,则不注入上述SQL,当调用work.linruchang.mybatisplussamplestest.dao.MyBaseMapper.deleteByIdLogic(java.io.Serializable)会报异常
return null;
}
}
DeleteByIdPhysical.java
/**
* 作用:物理删除
*
照抄{@link DeleteById}
* @author LinRuChang
* @version 1.0
* @date 2022/06/14
* @since 1.8
**/
public class DeleteByIdPhysical extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql;
SqlMethod sqlMethod
= SqlMethod.DELETE_BY_ID;
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(),
tableInfo.getKeyProperty());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
//return this.addDeleteMappedStatement(mapperClass, getMethod(sqlMethod), sqlSource);
return this.addDeleteMappedStatement(mapperClass, "deleteByIdPhysical", sqlSource);
}
}
MyBaseMapper.java
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 物理删除
* @param id
* @return
*/
int deleteByIdPhysical(Serializable id);
/**
* 物理删除
* @param entity
* @return
*/
int deleteByIdPhysical(T entity);
/**
* 逻辑删除
*
* 打算调这个方法,如果发现实体没有@TableLogic就会报异常出来提示用户
* @param id
* @return
*/
int deleteByIdLogic(Serializable id);
/**
* 逻辑删除
* @param entity
* @return
*/
int deleteByIdLogic(T entity);
/**
* 删除
* @param id 主键ID
* @param logicDeleteFlag null老逻辑
true逻辑删除 false物理删除
* @return
*/
default int deleteById(Serializable id, Boolean logicDeleteFlag) {
//无指定则根据实体是否有@TableLogic进行评判(原逻辑)
if(logicDeleteFlag == null) {return deleteById(id);}
//指定逻辑删除、物理删除
if(BooleanUtil.isTrue(logicDeleteFlag)) {
Class currentMapperClazz = (Class) ReflectUtil.getFieldValue(ReflectUtil.getFieldValue(AopUtils.getTargetObject(this),"h"),"mapperInterface");
Type typeArgument = TypeUtil.getTypeArgument(currentMapperClazz, 0);
TableInfo tableInfo = TableInfoHelper.getTableInfo((Class<?>) typeArgument);
if(tableInfo.isWithLogicDelete()) {
return deleteByIdLogic(id);
}
throw new RuntimeException(StrUtil.format("当前表【{}】:不支持逻辑删除,请检查是否有配置逻辑删除字段", tableInfo.getTableName()));
}else {
return deleteByIdPhysical(id);
}
}
}
SysUserDao.java
@Mapper
public interface SysUserDao extends MyBaseMapper<SysUser> {
}
SysUserServiceTest.java
@SpringBootTest
class SysUserServiceTest {
@Autowired
SysUserDao sysUserDao;
/**
* 物理删除支持
*/
@Test
public void test9() {
int insertFlag = sysUserDao.deleteById("dde66e90c44bcc535cce872541dd8b36", false);
Console.log("删除情况:{}",insertFlag);
}
/**
* 逻辑删除
*/
@Test
public void test10() {
int insertFlag = sysUserDao.deleteById("dde66e90c44bcc535cce872541dd8b36", true);
Console.log("逻辑删除情况:{}",insertFlag);
}
}
2. 工具类
2.1 Lambda获取字段名
代码
/**
* 作用:mybatisPlus工具类
*
* @author LinRuChang
* @version 1.0
* @date 2021/03/09
* @since 1.8
**/
public class MyBatisPlusUtil {
/**
* Collection<SFunction> 转成 Array<SFunction>
* 容器类型转换
* @param beanFields
* @param <T>
* @return
*/
public static <T> SFunction<T,?>[] sFunctionCollsToArray(Collection<SFunction<T, ?>> beanFields) {
return Optional.ofNullable(beanFields)
.map(bfs -> {
SFunction<T,?>[] result = new SFunction[beanFields.size()];
return bfs.toArray(result);
})
.orElse(new SFunction[0]);
}
/**
* Bean字段转select的数据库列名【即Bean变量名【驼峰变量名】转成下划线形式】
*
过程:sfunction =》Bean变量名 =》驼峰转下划线字符串
*
注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
* @param beanFields
* @param <T>
* @return 同一个表的多个表列名
*/
public static <T> Set<String> sFunctionConvertToDataBaseFields(SFunction<T, ?>... beanFields) {
return sFunctionConvertToDataBaseFields(beanFields == null ? Collections.emptySet():Arrays.asList(beanFields));
}
/**
* Bean字段转select的数据库列名【即Bean变量名【驼峰变量名】转成下划线形式】
*
过程:sfunction =》Bean变量名 =》驼峰转下划线字符串
*
注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
* @param beanFields 多个属性Bean变量
* @param <T>
* @return 同一个表的多个表列名
*/
public static <T> Set<String> sFunctionConvertToDataBaseFields(Collection<SFunction<T, ?>> beanFields) {
return Optional.ofNullable(beanFields).map(columnNames -> {
return beanFields.stream()
.map(MyBatisPlusUtil::sFunctionConverToDataBaseFieldFieldName)
.collect(Collectors.toSet());
}).orElse(Collections.emptySet());
}
/**
* 将Bean变量名转成数据库列名【约定俗成的形式】 == 驼峰转下划线
* 注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
* @param beanFileldName 属性Bean变量
* @param <T>
* @return 数据库列名【下划线】
*/
public static <T> String sFunctionConverToDataBaseFieldFieldName(SFunction<T, ?> beanFileldName) {
return Optional.ofNullable(sFunctionConverToBeanFieldName(beanFileldName))
.map(com.baomidou.mybatisplus.core.toolkit.StringUtils::camelToUnderline)
.orElse(null);
}
/**
* 获取Bean的变量名 == 一般都是驼峰变量名
* 注意:仅仅只是基于getxx进行解析,对于@TableFiled上的真正的注解列名不生效
* @param beanFileldName 属性Bean变量
* @param <T>
* @return Bean属性名
*/
public static <T> String sFunctionConverToBeanFieldName(SFunction<T, ?> beanFileldName) {
return Optional.ofNullable(beanFileldName).map(bfe -> {
SerializedLambda resolve = LambdaUtils.resolve(bfe);
return PropertyNamer.methodToProperty(resolve.getImplMethodName());
}).orElse(null);
}
}
使用
@Service
@Slf4j
public class RoleService extends ServiceImpl<RoleDao, Role> {
public List<Role> getList(SFunction<Role, ?>... fieldName) {
return this.getBaseMapper().getList(MyBatisPlusUtil.sFunctionConvertToDataBaseFields(fieldName));
}
}
@Mapper
public interface RoleDao extends BaseMapper<Role> {
public List<Role> getList(@Param("selectTableColumnNames") Set<String> selectTableColumnNames);
}
<!--注意列名拼接必须使用${变量},使用#{变量}的话,最后语句变成
select '列名1', '列名2' from 表名 这句是错的,应该变成 select 列名1, 列名2 from 表名 -->
<select id="getList" resultType="top.linruchang.springdemo.db.Role">
SELECT
<choose>
<when test="selectTableColumnNames != null and selectTableColumnNames.size() > 0">
<foreach collection="selectTableColumnNames" separator="," item="columnName">
${columnName}
</foreach>
</when>
<otherwise>*</otherwise>
</choose>
FROM role
</select>
最后
以上就是拼搏过客为你收集整理的MyBatis-Plus:代码增强-抽取公共字段、Lambda获取字段名的全部内容,希望文章能够帮你解决MyBatis-Plus:代码增强-抽取公共字段、Lambda获取字段名所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复