关于增强mapper的实现

当我们学习了mybatis后,我们在感叹mybatis的强大的同时,可能也会为重复的sql而感到厌烦,于是有了MybatisPlus 与 TKMybatis,对于还没用过的可能还不习惯,于是便自己想整一个简单的mapper增强,里面放置一些通用的方法,基于MybatisPlus的一些启发来实现,首先不管这些方法在mapper的具体实现,先考虑将这些通用方法在service与mapper层提取出来

我们首先定义BaseService与BaseMpper接口:

/**
 * service层公用方法接口
 * @param <T>
 */
public interface BaseService<T> {

    T getById(int id);

    List<T> getByCondition(Map paramsMap);

    List<T> getByCondition(T model);

    Long insert(T model);

    Long updateById(T model);

    Long deleteById(int id);

    Boolean existById(int id);
}
/**
 * 基础baseMapper,提取mapper公用的方法
 * 
 * @param <T>
 */
public interface BaseMapper<T> {

    T getById(@Param("id") int id);

    List<T> getByCondition(Map paramsMap);

    List<T> getByCondition(T model);

    Long insert(T model);

    Long updateById(T model);

    Long deleteById(@Param("id") int id);

    Boolean existById(@Param("id") int id);
}

这里mapper层的方法肯定是用注解的方式去解析sql,我们先不管 mapper层方法如何实现,我们来看下如此定义,我们去使用有什么弊端,在我们具体的业务模块中,比如说用户模块中,我们需要分别写接口UserService与UserMapper去继承上面的接口以使用他们的方法,然后写UserService的实现类UserServiceImpl,那我们在UserServiceImpl中反而要调用UserMapper对方法一一实现,显得繁琐,那我们能不能将UserServiceImpl中的具体实现提取出来呢?我们定义一个抽象类BaseServiceImpl实现接口BaseService,使得所有的ServiceImpl都继承它,如下:

/**
 * 定义公用方法的的实现类,业务层只需继承就可以调用
 * @param <T> 实体类泛型
 * @param <M> Mapper泛型
 */
public abstract class BaseServiceImpl<T,M extends BaseMapper<T>> implements BaseService<T> {

    @Autowired
    private M m;

    @Override
    public List<T> getByCondition(T model){return m.getByCondition(model);}

    @Override
    public List<T> getByCondition(Map model){return m.getByCondition(model);}

    @Override
    public T getById(int id){ return m.getById(id);}

    @Override
    public Long insert(T model){ return m.insert(model);}

    @Override
    public Long updateById(T model){return m.updateById(model);}

    @Override
    public Long deleteById(int id){return m.deleteById(id);}

    @Override
    public Boolean existById(int id){return m.existById(id);}

}

 注意类上面的泛型,我们将Mapper以泛型的形式传递进来,然后通过@Autowrid注解从spring容器注入,在这里做这些方法在业务层的具体实现,那我们在具体模块中就只需要继承就ok了,如下:

/**
 * 此处只需要定义mapper层和service层 方法名 不同的方法
 * 同名的方法抽象到 CommonUserMethodInterface 接口
 */
public interface UserMapper extends BaseMapper<User>{

}
-----------------------------------------------------------------------------------
/**
 * 此处只需要定义service层方法名 和 mapper不同的方法
 * 同名的方法抽象到 CommonUserMethodInterface 接口
 */
public interface UserService extends BaseService<User>{

}
------------------------------------------------------------------------------------

@Service
public class UserServiceImpl extends BaseServiceImpl<User,UserMapper> implements UserService{

}

 然后我们在控制层就可以调用到我们的提取到的公用方法了,省掉了我们以前我们在每个模块的业务层去实现这些方法,然后我们来看如何去加载我们的BaseMapper,mybatis提供了一个 @Lang 的注解,允许我们去自定义解析sql的驱动,如下,我们需要定义我们自己的sql驱动

/**
 * 基础baseMapper,提取mapper公用的方法
 * 参数为实体类或者map的不能用  @Param 注解
 * @param <T>
 */
public interface BaseMapper<T> {

    /**
     * 根据id查询
     * @param id
     * @return
     */
    @Lang(BaseMapperDriver.class)
    @Select("SELECT ${columns} FROM ${table} where ${id} = #{id}")
    T getById(@Param("id") int id);

    /**
     * 条件查询,参数为map,
     * 注意: 不能使用 @Param 注解,key的值必须为实体类的字段名
     * @return
     */
    @Lang(BaseMapperDriver.class)
    @Select("SELECT ${columns} FROM ${table} where 1=1 ${conditions}")
    List<T> getByCondition(Map paramsMap);

    /**
     * 优先使用此方法做查询
     * 条件查询,参数为实体类,不能使用 @Param 注解
     * @return
     */
    @Lang(BaseMapperDriver.class)
    @Select("SELECT * FROM ${table} where 1=1 ${conditions} ")
    List<T> getByCondition(T model);

    /**
     * 插入
     * @param model
     * @return
     */
    @Lang(BaseMapperDriver.class)
    @Insert("INSERT INTO ${table} ${keys} values ${values}")
    @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
    Long insert(T model);

    /**
     * 根据id 修改
     * @param model
     * @return
     */
    @Lang(BaseMapperDriver.class)
    @Update("UPDATE ${table} ${sets} WHERE ${id}=#{id}")
    Long updateById(T model);

    /**
     * 删除
     * @param id
     * @return
     */
    @Lang(BaseMapperDriver.class)
    @Delete("DELETE FROM ${table} WHERE ${id}=#{id}")
    Long deleteById(@Param("id") int id);

    /**
     * 判断是否存在
     * @param id
     * @return
     */
    @Lang(BaseMapperDriver.class)
    @Select("SELECT COUNT(1) FROM ${table} WHERE ${id}=#{id}")
    Boolean existById(@Param("id") int id);
}

在定义驱动之前,我们需要重写mybatis的一些配置类:

        将配置类注入工厂

@Configuration
public class DataConfig {

    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;

    @Bean
    public SqlSessionFactoryBean configSqlSessionFactoryBean(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        bean.setMapperLocations(resolver.getResources(mapperLocations));// 设置mapper文件扫描路径
        bean.setConfiguration(new MybatisConfig());
        return bean;
    }
}

         在配置类的构造方法中注入 MybatisMapperRegistry

/**
 * 重写mybatis的 Configuration
 */

public class MybatisConfig extends Configuration {

    protected final MapperRegistry mapperRegistry;

    public MybatisConfig(){
        super();
        this.mapperRegistry =  new MybatisMapperRegistry(this);
        this.mapUnderscoreToCamelCase = true;
    }

    @Override
    public MapperRegistry getMapperRegistry() {
        return this.mapperRegistry;
    }
    @Override
    public void addMappers(String packageName, Class<?> superType) {
        this.mapperRegistry.addMappers(packageName, superType);
    }

    @Override
    public void addMappers(String packageName) {
        this.mapperRegistry.addMappers(packageName);
    }

    @Override
    public <T> void addMapper(Class<T> type) {
        this.mapperRegistry.addMapper(type);
    }

    @Override
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        return this.mapperRegistry.getMapper(type, sqlSession);
    }

    @Override
    public boolean hasMapper(Class<?> type) {
        return this.mapperRegistry.hasMapper(type);
    }
}

         在MybatisMapperRegistry中主要是在addMapper方法中捕获当前的mapper类,在我们自定义sql驱动需要用到

/**
 * 自定义mapperRegistry
 */
public class MybatisMapperRegistry extends MapperRegistry {


    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap();

    private Configuration config;

    private static Class<?> currentMapper;

    public MybatisMapperRegistry(Configuration config) {
        super(config);
        this.config = config;
    }

    public static Class<?> getCurrentMapper() {
        return currentMapper;
    }

    @Override
    public <T> void addMapper(Class<T> type) {
        if (type.isInterface()) {
            if (this.hasMapper(type)) {
                throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
            }

            boolean loadCompleted = false;

            try {
                this.knownMappers.put(type, new MapperProxyFactory(type));
                MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
                currentMapper = type;
                parser.parse();
                currentMapper=null;
                loadCompleted = true;
            } finally {
                if (!loadCompleted) {
                    this.knownMappers.remove(type);
                }
            }
        }

    }

    @Override
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        } else {
            try {
                return mapperProxyFactory.newInstance(sqlSession);
            } catch (Exception var5) {
                throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
            }
        }
    }



    @Override
    public <T> boolean hasMapper(Class<T> type) {
        return this.knownMappers.containsKey(type);
    }



    @Override
    public Collection<Class<?>> getMappers() {
        return Collections.unmodifiableCollection(this.knownMappers.keySet());
    }


    @Override
    public void addMappers(String packageName, Class<?> superType) {
        ResolverUtil<Class<?>> resolverUtil = new ResolverUtil();
        resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
        Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
        Iterator var5 = mapperSet.iterator();

        while(var5.hasNext()) {
            Class<?> mapperClass = (Class)var5.next();
            this.addMapper(mapperClass);
        }

    }

    @Override
    public void addMappers(String packageName) {
        this.addMappers(packageName, Object.class);
    }
}

 然后我们去看如何自定义sql解析器

        自定义类 继承XMLLanguageDriver 实现LanguageDriver , 在LanguageDriver中有三个方法,在XMLLanguageDriver中对三个方法做了简单的实现

1. ParameterHandler createParameterHandler(MappedStatement var1, Object var2, BoundSql         var3);

        该方法用于mybatis参数填充处理,在sql执行之前会被调用

2.SqlSource createSqlSource(Configuration var1, XNode var2, Class<?> var3);

        该方法用于解析xml中的sql

3.SqlSource createSqlSource(Configuration var1, String var2, Class<?> var3);

        该方法用于解析注解中的sql

我们需要重写的就是方法3,基本原理就是获取当前mapper接口的泛型,这个泛型一般都为实体类,我们在这个实体类上添加注解,标记实体类与数据库中表的对应,我添加的注解如下:

/**
 * 注解到实体类属性上,标记属性对应的列名
 * 只有 有此注解的才会被解析进sql
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String name() default "";
}
------------------------------------------------------
/**
 * 指定主键
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
    String name() default "";
}
----------------------------------------------------------
/**
 * 查询时默认查询所有注解有 @column 的属性对应的字段
 * 注解到实体类属性上,标记查询时不被查询的属性
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoredColumn {

}
---------------------------------------------------------
/**
 * 指定表名
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String name();
}
-----------------------------------------------------------
/**
 * 是否使用父类属性
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseParent {
}

重写方法如下:

        我们对获取到的泛型,实际就是实体类,对它的属性进行遍历,通过属性上的注解获取属性在数据库对应的字段,然后对sql进行拼接替换

/**
 * 自定义 基础mapper查询驱动
 *
 */
public class BaseMapperDriver extends XMLLanguageDriver implements LanguageDriver {

    @Override
    public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
        /* 对sql进行解析处理 */
        BaseMapperDriverResolver baseMapperDriverResolver = new BaseMapperDriverResolver();
        script = baseMapperDriverResolver.createSqlSource(configuration,script);
        return super.createSqlSource(configuration, script , parameterType);
    }
}
--------------------------------------------------------------------------------------

public class BaseMapperDriverResolver extends DriverResolver {

    public String createSqlSource(Configuration configuration, String script){
        //获取当前mapper
        Class<?> mapperClass = null;
        if(configuration instanceof MybatisConfig){
            mapperClass = MybatisMapperRegistry.getCurrentMapper();
            if(mapperClass == null){
                throw new BaseException("解析SQL出错");
            }
        }
        //处理SQL
        if(mapperClass!=null) {
            /* 获取当前mapper接口上的泛型,这个泛型实际上对应着实体类 */
            Class<?> generics = getMapperGenerics(mapperClass);
            String newScript = super.commonCreateSqlSource(generics, script);
            StringBuilder sb = new StringBuilder( "<script>");
            sb.append(newScript);
            sb.append("</script>");
            script = sb.toString();
        }
        return script;
    }

}

public abstract class DriverResolver implements BaseResolverInterface {

    static final String tablePattern = "\\$\\{table\\}";

    static final String idPattern = "\\$\\{id\\}";

    static final String columnsPattern = "\\$\\{columns\\}";

    static final String keysPattern = "\\$\\{keys\\}";

    static final String valuesPattern = "\\$\\{values\\}";

    static final String setsPattern = "\\$\\{sets\\}";

    static final String conditionPattern = "\\$\\{conditions\\}";

    /**
     * 判断是否是select方法
     * @param script
     * @return
     */
    public boolean isSelect(String script){
        Matcher matcher = Pattern.compile("[selectSELECT]{6}").matcher(script);
        /* 判断是否是select方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断是否是插入语句
     * @param script
     * @return
     */
    public boolean isInsert(String script){
        Matcher matcher = Pattern.compile("[insertINSERT]{6}").matcher(script);
        /* 判断是否是insert方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断是否更新语句
     * @param script
     * @return
     */
    public boolean isUpdate(String script){
        Matcher matcher = Pattern.compile("[updateUPDATE]{6}").matcher(script);
        /* 判断是否是update方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断是否是删除语句
     * @param script
     * @return
     */
    public boolean isDelete(String script){
        Matcher matcher = Pattern.compile("[deleteDELETE]{6}").matcher(script);
        /* 判断是否是delete方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断sql是否含有 ${table}
     * @param script
     * @return
     */
    public boolean hasTable(String script){
        Matcher matcher = Pattern.compile(tablePattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${id}
     * @param script
     * @return
     */
    public boolean hasId(String script){
        Matcher matcher = Pattern.compile(idPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${columns}
     * @param script
     * @return
     */
    public boolean hasColumns(String script){
        Matcher matcher = Pattern.compile(columnsPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${keys}
     * @param script
     * @return
     */
    public boolean hasKeys(String script){
        Matcher matcher = Pattern.compile(keysPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${values}
     * @param script
     * @return
     */
    public boolean hasValues(String script){
        Matcher matcher = Pattern.compile(valuesPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${sets}
     * @param script
     * @return
     */
    public boolean hasSets(String script){
        Matcher matcher = Pattern.compile(setsPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断是否是条件查询
     * @param script
     * @return
     */
    public boolean hasConditions(String script){
        Matcher matcher = Pattern.compile(conditionPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 获取mapper接口的泛型
     * @param mapperClass
     * @return
     */
    public Class<?> getMapperGenerics(Class<?> mapperClass){
        /*获取mapperClass接口的类型*/
        Type[] types =  mapperClass.getGenericInterfaces();

        ParameterizedType parameterizedType = (ParameterizedType)types[0];
        Type[] types1 = parameterizedType.getActualTypeArguments();
        return (Class<?>)types1[0];

        /* 多个泛型需要遍历 */
        /*Class<?>[]  classes = new Class[types.length];
        for(Type type:types){
            ParameterizedType parameterizedType = (ParameterizedType)type;
            Type[] types1 = parameterizedType.getActualTypeArguments();
            classes[0] = (Class<?>) types1[0];
        }
        return classes;*/
    }

    /**
     * 获取实体类所有的属性
     * @param generics
     * @return
     */
    public List<Field> getFieldList(Class<?> generics){
        /* 获取所有的字段 */
        //获取所有属性的合集
        List<Field> fieldList = new ArrayList();
        /* 判断是否有该注解 */
        if(generics.isAnnotationPresent(UseParent.class)){
            /* 添加父类的所有字段 */
            fieldList.addAll(Arrays.asList(generics.getSuperclass().getDeclaredFields()));
        }
        /* 添加本类所有字段 */
        fieldList.addAll(Arrays.asList(generics.getDeclaredFields()));
        return fieldList;
    }

    /**
     * 替换insert与update的列名
     * 只会拼接有 @column 注解的字段
     * @param field
     * @return
     */
    @Override
    public String setKeys(Field field){
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column;
        if (field.isAnnotationPresent(Column.class)) {
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if ("".equals(__column)) {
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            String keysTemp = "<if test=\"__field != null\"> __column, </if>";
            //拼接
            return keysTemp.replaceAll("__field", __field).replaceAll("__column", __column);
        }
        return "";
    }

    /**
     * 替换insert与update的实体类字段, keys的value
     * 只会拼接有 @column 注解的字段
     * @param field
     * @return
     */
    @Override
    public String setValues(Field field){
        if (field.isAnnotationPresent(Column.class)) {
            String valuesTemp = "<if test=\"__field != null\">  #{__field} , </if>";
            return valuesTemp.replaceAll("__field", field.getName());
        }
        return "";
    }

    /**
     * 替换update的 set集合
     * 只会拼接有 @column 注解的字段
     * @param field
     * @return
     */
    @Override
    public String setSets(Field field){
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column;
        String temp = "";
        if(field.isAnnotationPresent(Column.class)) {
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if ("".equals(__column)) {
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            temp = "<if test=\"__field != null\"> __column=#{__field} </if>";
            //拼接
            temp.replaceAll("__field", __field).replaceAll("__column", __column);
        }
        return temp;
    }

    /**
     * 设置需要查询的列名
     * @param field
     * @return
     */
    @Override
    public String setColumns(Field field) {
        String temp = "";
        boolean ignoredColumn = false;
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column = "";
        if (field.isAnnotationPresent(Column.class)) {
            /*有此注解则被忽略*/
            if (field.isAnnotationPresent(IgnoredColumn.class)) {
                ignoredColumn = true;
            }
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
        } else if(field.isAnnotationPresent(Id.class)){
            /*有此注解则被忽略*/
            if (field.isAnnotationPresent(IgnoredColumn.class)) {
                ignoredColumn = true;
            }
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Id.class).name();
        } else {
            ignoredColumn = true;
        }
        if(!ignoredColumn){
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if ("".equals(__column)) {
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            temp = "  __column     __field ,   ";
            temp = temp.replaceAll("__column", __column).replaceAll("__field",__field);
        }
        return temp;
    }

    /**
     * 替换表名
     * @param generics
     * @return
     */
    @Override
    public String setTable(Class<?> generics){
        /* 若未添加注解,直接返回 */
        if(!generics.isAnnotationPresent(Table.class)){
            throw new BaseException("类:"+generics.getName()+"未添加注解 " + Table.class.getName());
        }
        /* 获取注解上的表名 */
        String tableName = generics.getAnnotation(Table.class).name();
        /* 若table注解没有传值,使用类名进行变换 */
        if("".equals(tableName)){
            tableName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, generics.getName());
        }
        /* 替换表名 */
        return tableName;
    }

    /**
     * 替换主键
     * @param field
     * @return
     */
    @Override
    public String setId(Field field){
        String __id = "";
        if (field.isAnnotationPresent(Id.class)) {
            /* 获取注解中表的列名 */
            __id = field.getAnnotation(Id.class).name();
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if("".equals( __id )){
                __id = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName());
            }
        }
        return __id;
    }

    /**
     * 拼接条件查询动态sql
     * @param field
     * @return
     */
    @Override
    public String setConditions(Field field){
        boolean isPass = false;
        String temp = "";
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column = "";
        if (field.isAnnotationPresent(Id.class)) {
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Id.class).name();
        } else if(field.isAnnotationPresent(Column.class)){
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
        } else {
            /* 没有注解标记的跳过 */
            isPass = true;
        }
        if(!isPass){
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if("".equals(__column)){
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            temp = "<if test=\"__field != null\"> and __column=#{__field} </if>";
            //拼接
            temp = temp.replaceAll("__field", __field).replaceAll("__column", __column);
        }
        return temp;
    }

    /**
     * 通用替换拼接sql
     * @param generics
     * @param script
     * @return
     */
    public String commonCreateSqlSource(Class<?> generics,String script) {

        StringBuilder id = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        StringBuilder keys = new StringBuilder();
        StringBuilder values = new StringBuilder();
        StringBuilder sets = new StringBuilder();
        StringBuilder conditions = new StringBuilder();

        List<Field> fieldList = getFieldList(generics);
        //遍历所有的属性
        for (Field field : fieldList) {
            if(hasId(script)){
                /* 获取id */
                id.append(setId(field));
            }
            if(hasColumns(script)){
                /* 拼接查询的列名 */
                columns.append(setColumns(field));
            }
            if(hasKeys(script)){
                /* 拼接insert和update的keys */
                keys.append(setKeys(field));
            }
            if(hasValues(script)){
                /* 拼接insert和update的values */
                values.append(setValues(field));
            }
            if(hasSets(script)){
                /* 拼接update的sets */
                sets.append(setSets(field));
            }
            if (hasConditions(script)){
                conditions.append(setConditions(field));
            }
        }
        /* 判断是否需要替换 ${table} 表名不需要遍历 */
        if(hasTable(script)){
            String table = setTable(generics);
            script = script.replaceAll(tablePattern,table);
        }
        /* 判断是否需要替换 ${id} */
        if (hasId(script)){
            script = script.replaceAll(idPattern,id.toString());
        }
        /* 判断是否需要替换 ${columns} */
        if (hasColumns(script)){
            StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
            sb.append(columns);
            sb.append("</trim> ");
            script = script.replaceAll(columnsPattern,sb.toString());
        }
        /* 判断是否需要替换 ${keys} */
        if (hasKeys(script)){
            StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
            sb.append(keys);
            sb.append("</trim> ");
            script = script.replaceAll(keysPattern,sb.toString());
        }
        /* 判断是否需要替换 ${values} */
        if (hasValues(script)){
            StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
            sb.append(values);
            sb.append("</trim> ");
            script = script.replaceAll(valuesPattern,sb.toString());
        }
        /* 判断是否需要替换 ${sets} */
        if (hasSets(script)){
            StringBuilder sb = new StringBuilder("<set> <trim suffixOverrides=\",\"> ");
            sb.append(sets);
            sb.append("</trim> </set>");
            script = script.replaceAll(setsPattern,sb.toString());
        }
        /* 判断是否需要添加查询条件 */
        if (hasConditions(script)){
            StringBuilder sb = new StringBuilder();
            sb.append(conditions);
            script = script.replaceAll(conditionPattern,sb.toString());
        }
        return script;
    }
}
public interface BaseResolverInterface {
     String setTable(Class<?> entityClazz);

     String setId(Field field);

     String setColumns(Field field);

     String setKeys(Field field);

     String setValues(Field field);

     String setSets(Field field);

     String setConditions(Field field);
}

gitee地址:https://gitee.com/dchenleilei/springboot/tree/master

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mybatis-plus是MyBatis增强工具包,用于简化CRUD操作。该工具包为MyBatis提供了一些高效,有用,即用的功能,使用它可以有效地节省您的开发时间。 Mybatis-plus特征: 与MyBatis完全兼容 启动时自动配置 开箱即用的用于操作数据库的界面 强大而灵活的条件包装器 生成主键的多种策略 Lambda样式的API 全能和高度可定制的代码生成器 自动分页操作 SQL注入防御 支持活动记录 支持可插拔的自定义界面 内置许多有用的扩展 Mybatis-plus功能: 1、单表CURD(简单 + 批量)操作,自动完成(支持 like 比较等查询)。 2、分页插件,Count查询自动或自定义SQL查询。 3、Spring根据不同环境加载不同配置支持(支持typeAliasesPackage通配符扫描)。 【自动生成Entity  Mapper  Service文件】 Mybatis-plus更新日志: v3.4.3 增加瀚高数据库支持 增加注解 Order By 支持默认排序 Wrapper exists notExists orderBy groupBy 支持参数绑定 Wrapper 支持 setParamAlias 其它优化 优化 KeyGenerator 支持多实现多数据源注入 增强 ServiceImpl 泛型推断,解决多继承与代理问题 新增 PageDto 用于微服务对象传输序列化 新增 Page 提供静态 of 构造方式 增加代理 MethodHandleProxies 对 lambda 调试支持 调整 ActiveRecord 日志对象初始化 调整 ActiveRecord 模式 Model 类开发 pkVal 方法外部可用 删除标记过时代码 优化枚举值获取方式 分页 count 安全处理 Sequence 方法支持重写支持 升级 Mybatis 3.5.7 修复自动配置 lazy-initialization 无属性提示 修复 mysql on duplicate key update 字段名判断为表名问题 修复 lambda 条件 npe 异常 重构 lambda 信息提取方法 获取 lambda 信息不在序列化 合并 gitee pulls/ 141 fixed github issues/3208 3016 fixed github issues/3482 数据权限处理器支持 union all 调整事务未启用打印提示信息 单元测试优化相关依赖升级

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值