@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;
}
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);
}
}
/**
* 作用: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>
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_39651356/article/details/125328483
内容来源于网络,如有侵权,请联系作者删除!