当前位置: 首页 > news >正文

Mybatis通用接口-基于Provider

新项目的话建议使用Mybatis-plus会好点

1、创建实体类注解

/***** 表名* @author*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TableName {String value() default "";/**** 别名 */String alias() default "";
}
/*** 表主键* @author*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {String value() default "";
}
public enum FieldStrategy {IGNORED,NOT_NULL,NOT_EMPTY,DEFAULT,NEVER;private FieldStrategy() {}
}
import java.lang.annotation.*;/***** 实体属性注解*@author chenzhongchao*@date 2024/9/6*@time 11:09*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableField {/*** 数据库字段名*/String value() default "";FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;/*** 字段是否存在*/boolean exist() default true;FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;/*** jdbc类型*/JdbcType jdbcType() default JdbcType.UNDEFINED;
}

2、创建Mapper基类

/***** 通用mapper基类,采用Provider方式省略xml编写sql,复杂性sql请自行编写xml* 实体必须有@TableName注解* 属性必须有@TableField注解* 否则默认类名、属性名作为表名列名*@author*/
public interface BaseMapper<T> {/***** 根据实体新增数据,为空的字段不处理*@param var1 实体*@return 影响行数*/@InsertProvider(type = InsertSqlProvider.class, method = "sql")int insert(T var1);/*** 根据主键查询* @param var1 主键* @return  实体*/@SelectProvider(type = SelectByPrimarySqlProvider.class, method = "sql")T selectByPrimaryKey(String var1);/*** 根据实体查询列表(非空属性作为条件,只做等于,复杂请写xml)* @param var1 实体* @return  实体列表*/@SelectProvider(type = SelectListSqlProvider.class, method = "sql")List<T> selectList(T var1);@UpdateProvider(type = UpdateSqlProvider.class, method = "sql")int updateByPrimaryKey(T var1);@DeleteProvider(type = DeleteSqlProvider.class, method = "sql")int deleteByPrimaryKey(String var1);}

3、实体类处理

public class TableInfo {/*** 表名*/private String tableName;/*** 表名*/private String tableAliasName;/*** 实体类型field*/private Field[] fields;/*** 实体类型非空field*/private Field[] notNullFields;/*** 所有列名*/private String[] notNullColumns;/*** 主键列名*/private String primaryKeyColumn;/*** 所有列名*/private String[] columns;public String getTableName() {return tableName;}public String getTableAliasName() {return tableAliasName;}public String[] getColumns() {return columns;}public Field[] getFields() {return fields;}public Field[] getNotNullFields() {return notNullFields;}public String[] getNotNullColumns() {return notNullColumns;}private TableInfo() {}/*** 获取主键的where条件,如 id = #{id}** @return  主键where条件*/public String getPrimaryKeyWhere() {String pk = this.primaryKeyColumn;return pk + " = #{" + pk + "}";}/*** 获取TableInfo的简单工厂** @param mapperType mapper类型* @return    {@link TableInfo}*/public static TableInfo of(Class<?> mapperType) {Class<?> entityClass = entityType(mapperType);// 获取不含有@NoColumn注解的fieldsTableInfo tableInfo = new TableInfo();Field[] fields = excludeNoColumnField(entityClass,tableInfo);tableInfo.fields = fields;TableName tableName = tableName(entityClass);tableInfo.tableName = tableName== null ?  entityClass.getSimpleName() : tableName.value();tableInfo.tableAliasName = tableName== null ?  entityClass.getSimpleName() : tableName.alias();return tableInfo;}/*** 过滤静态的field** @param entityClass 实体类型* @return 不包含@NoColumn注解的fields*/public static Field[] excludeNoColumnField(Class<?> entityClass,TableInfo tableInfo) {List<Field> fields = new ArrayList<>();List<Field> noNullFields = new ArrayList<>();List<String> columns = new ArrayList<>();List<String> notNullColumns = new ArrayList<>();Field[] allFields = entityClass.getDeclaredFields();for (Field field:allFields) {TableId id = field.getAnnotation(TableId.class);if (id != null){tableInfo.primaryKeyColumn = StringUtils.isEmpty(id.value())?field.getName():id.value();columns.add(StringUtils.isEmpty(id.value())?field.getName():id.value());}TableField tableField = field.getAnnotation(TableField.class);if (tableField != null&&!Modifier.isStatic(field.getModifiers())&&tableField.exist()){fields.add(field);columns.add(StringUtils.isEmpty(tableField.value())?field.getName():tableField.value());}}tableInfo.columns = columns.toArray(new String[0]);return fields.toArray(new Field[0]);}public static Field[] getNoColumnField(Object entityClass,TableInfo tableInfo) {List<Field> noNullFields = new ArrayList<>();List<String> notNullColumns = new ArrayList<>();Field[] allFields = entityClass.getClass().getDeclaredFields();for (Field field:allFields) {TableId id = field.getAnnotation(TableId.class);if (id != null){try {field.setAccessible(true);Object value =  field.get(entityClass);if (value!=null){noNullFields.add(field);notNullColumns.add(StringUtils.isEmpty(id.value())?field.getName():id.value());}} catch (IllegalAccessException e) {e.printStackTrace();}}TableField tableField = field.getAnnotation(TableField.class);if (tableField != null&&!Modifier.isStatic(field.getModifiers())&&tableField.exist()){try {field.setAccessible(true);Object value =  field.get(entityClass);if (value!=null){noNullFields.add(field);notNullColumns.add(StringUtils.isEmpty(tableField.value())?field.getName():tableField.value());}} catch (IllegalAccessException e) {e.printStackTrace();}}}tableInfo.notNullColumns = notNullColumns.toArray(new String[0]);tableInfo.notNullFields = noNullFields.toArray(new Field[0]);return noNullFields.toArray(new Field[0]);}/*** 获取表名** @param entityType  实体类型* @return      表名*/public static TableName tableName(Class<?> entityType) {TableName tableName = entityType.getAnnotation(TableName.class);return tableName ;}/*** 获取BaseMapper接口中的泛型类型** @param mapperType  mapper类型* @return       实体类型*/public static Class<?> entityType(Class<?> mapperType) {return Stream.of(mapperType.getGenericInterfaces()).filter(ParameterizedType.class::isInstance).map(ParameterizedType.class::cast).filter(type -> type.getRawType() == BaseMapper.class).findFirst().map(type -> type.getActualTypeArguments()[0]).filter(Class.class::isInstance).map(Class.class::cast).orElseThrow(() -> new IllegalStateException("未找到BaseMapper的泛型类 " + mapperType.getName() + "."));}/*** 绑定参数** @param field  字段* @return        参数格式*/public static String bindParameter(Field field) {TableField tableField = field.getAnnotation(TableField.class);if (tableField != null&&!Modifier.isStatic(field.getModifiers())&&tableField.exist()){String value =  "#{" + field.getName() +",jdbcType="+tableField.jdbcType()+ "}";return value;}return "#{" + field.getName() + "}";}/*** 获取该字段的参数赋值语句,如 user_name = #{userName}* @param field  字段* @return       参数赋值语句*/public static String assignParameter(Field field) {String column = null;TableField tableField = field.getAnnotation(TableField.class);if (tableField != null&&!Modifier.isStatic(field.getModifiers())&&tableField.exist()){column=StringUtils.isEmpty(tableField.value())?field.getName():tableField.value();}if (StringUtil.isBlank(column)){TableId id = field.getAnnotation(TableId.class);if (id != null){column = StringUtils.isEmpty(id.value())?field.getName():id.value();}}return column + " = " + bindParameter(field);}
}

4、Provider

/***** SqlProvider基类 创建表信息* @author*/
public class BaseSqlProviderSupport {/*** key -> mapper class   value -> tableInfo*/private static Map<Class<?>, TableInfo> tableCache = new ConcurrentHashMap<>(128);/*** 获取表信息结构** @param context  provider context* @return  表基本信息*/protected TableInfo tableInfo(ProviderContext context) {// 如果不存在则创建-会调用TableInfo的of方法return tableCache.computeIfAbsent(context.getMapperType(), TableInfo::of);}}
/***** 根据实体新增数据,为空字段不添加* @author*/
public class InsertSqlProvider extends BaseSqlProviderSupport{/*** sql* @param context context* @return  sql*/public String sql(Object entity,ProviderContext context) {TableInfo table = tableInfo(context);TableInfo.getNoColumnField(entity,table);String sql = new SQL().INSERT_INTO(table.getTableName()).INTO_COLUMNS(table.getNotNullColumns()).INTO_VALUES(Stream.of(table.getNotNullFields()).map(TableInfo::bindParameter).toArray(String[]::new)).toString();return sql;}
}
/***** 根据主键查询数据* @author*/
public class SelectByPrimarySqlProvider  extends BaseSqlProviderSupport{/*** sql* @param context context* @return  sql*/public String sql(ProviderContext context) {TableInfo table = tableInfo(context);//mapper里的参数会直接赋值给#{id}String sql = new SQL().SELECT(table.getColumns()).FROM(table.getTableName()).WHERE(table.getPrimaryKeyWhere()).toString();return sql;}
}
/***** 根据主键查询数据* @author*/
public class SelectListSqlProvider extends BaseSqlProviderSupport{/*** sql* @param context context* @return  sql*/public String sql(Object entity,ProviderContext context) {TableInfo table = tableInfo(context);TableInfo.getNoColumnField(entity,table);//mapper里的参数会直接赋值给#{id}String sql = new SQL().SELECT(table.getColumns()).FROM(table.getTableName()).WHERE(Stream.of(table.getNotNullFields()).map(TableInfo::assignParameter).toArray(String[]::new)).toString();return sql;}
}

剩下根据自己的要求编写

5、服务接口

/***** 后续有需要扩展的公共方法接口可以放在这里* @author*/
public interface IService<T> {
}
/***** 后续有需要扩展的公共方法接口的实现可以放在这里* @author*/
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {@Resourceprotected M baseMapper;public ServiceImpl() {}public M getBaseMapper() {return this.baseMapper;}}

6、使用

/*** @author*/
@TableName(value = "TableName")
@Data
public class DynamicApiHistory  {@TableField("apiId")private String apiId;@TableId("apiHistoryId")private String apiHistoryId;@TableField("orgCode")private String orgCode;@TableField(value = "dynamicApiColumn",jdbcType = JdbcType.CLOB)private String dynamicApiColumn;
}
/*** @author*/
public interface IDynamicApiHistoryService extends IService<DynamicApiHistory> {int insert(DynamicApiHistory dynamicApiHistory);
}
/*** @author*/
@Service
public class DynamicApiHistoryServiceImpl extends ServiceImpl<DynamicApiHistoryMapper, DynamicApiHistory> implements IDynamicApiHistoryService {@ResourceDynamicApiService dynamicApiService;@Overridepublic int insert(DynamicApiHistory dynamicApiHistory ) {return baseMapper.insert(dynamicApiHistory);}}


http://www.mrgr.cn/news/26903.html

相关文章:

  • 模型部署基础
  • 2023年09月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 + 解析
  • VPP配置网卡多队列no bufs问题
  • Humanize AI 简介
  • vue2基础系列教程之v-model及面试高频问题
  • Brave编译指南2024 Windows篇:构建并启动Brave项目(七)
  • Flutter iOS混淆打包
  • CAESES许可证转移方法
  • Linux下read函数详解
  • 【SpringBoot】调度和执行定时任务--Quartz(超详细)
  • kafka 之 本地部署单机版
  • 9.14 DFS 简单 111 Minimum Depth of Binary Tree 112 Path Sum
  • C/C++动态库函数导出 windows
  • Netty配置SSL证书加密
  • 使用PyTorch进行图像风格迁移:基于VGG19实现
  • SpringBoot框架下的房产销售系统开发
  • SQL Server数据库深入解析(建议收藏)
  • 使用nvm安装node版本报错
  • AI创作新手册:精通Prompt提示词的提问策略
  • ZYNQ FPGA自学笔记