新项目的话建议使用Mybatis-plus会好点
1、创建实体类注解
java
/****
* 表名
* @author
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TableName {
String value() default "";
/***
* 别名
*/
String alias() default "";
}
java
/**
* 表主键
* @author
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {
String value() default "";
}
java
public enum FieldStrategy {
IGNORED,
NOT_NULL,
NOT_EMPTY,
DEFAULT,
NEVER;
private FieldStrategy() {
}
}
java
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基类
java
/****
* 通用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、实体类处理
java
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注解的fields
TableInfo 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
java
/****
* 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);
}
}
java
/****
* 根据实体新增数据,为空字段不添加
* @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;
}
}
java
/****
* 根据主键查询数据
* @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;
}
}
java
/****
* 根据主键查询数据
* @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、服务接口
java
/****
* 后续有需要扩展的公共方法接口可以放在这里
* @author
*/
public interface IService<T> {
}
java
/****
* 后续有需要扩展的公共方法接口的实现可以放在这里
* @author
*/
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
@Resource
protected M baseMapper;
public ServiceImpl() {
}
public M getBaseMapper() {
return this.baseMapper;
}
}
6、使用
java
/**
* @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;
}
java
/**
* @author
*/
public interface IDynamicApiHistoryService extends IService<DynamicApiHistory> {
int insert(DynamicApiHistory dynamicApiHistory);
}
java
/**
* @author
*/
@Service
public class DynamicApiHistoryServiceImpl extends ServiceImpl<DynamicApiHistoryMapper, DynamicApiHistory> implements IDynamicApiHistoryService {
@Resource
DynamicApiService dynamicApiService;
@Override
public int insert(DynamicApiHistory dynamicApiHistory ) {
return baseMapper.insert(dynamicApiHistory);
}
}