关于增强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
    评论
要对Mapper接口中定义的方法做aop增强,可以采用以下步骤: 1. 定义一个切面类,使用@Aspect注解标识; 2. 在切面类中定义一个切入点,使用@Pointcut注解标识,指定需要增强Mapper中的方法; 3. 编写增强逻辑,并使用@Around注解将增强逻辑织入到切入点中; 4. 在Spring配置文件中声明切面类和Mapper接口的实现类,使用<aop:aspectj-autoproxy/>启用自动代理。 下面是一个示例: ``` @Aspect public class MapperAspect { @Autowired private DataSourceTransactionManager transactionManager; @Pointcut("execution(* com.example.mapper.*.*(..))") public void mapperPointcut() {} @Around("mapperPointcut()") public Object mapperAround(ProceedingJoinPoint joinPoint) throws Throwable { // 在Mapper方法执行前开启事务 transactionManager.getTransaction(new DefaultTransactionDefinition()); // 调用Mapper方法 Object result = joinPoint.proceed(); // 在Mapper方法执行后提交事务 transactionManager.commit(transactionManager.getTransaction()); return result; } } ``` 在这个示例中,我们定义了一个切面类MapperAspect,使用@Aspect注解标识。 在MapperAspect中,我们使用@Autowired注解注入了一个DataSourceTransactionManager,用于在Mapper方法执行前开启事务,在执行后提交事务。 我们使用@Pointcut注解定义了一个名为mapperPointcut的切入点,指定了需要增强Mapper中的方法。 最后,我们使用@Around注解将增强逻辑织入到切入点中,在Mapper方法执行前开启事务,在执行后提交事务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值