• tk.mybatis扩展通用接口


     一.tk.mybatis已经为我们封装好了许多拆箱即用的通用mapper,但在实际的项目开发中想必不少小伙伴在数据库设计中都会采用逻辑删除这种方案,再去使用通用的mapper接口就不行了。这时候就需要我们封装一些扩展的通用Mapper接口。

     二.项目中提供了大量现成的方法,这些方法可以作为扩展时的参考。

       例如 selectAll 方法。

       首先定义接口:

    @RegisterMapper
    public interface SelectAllMapper<T> {
    
        /**
         * 查询全部结果
         *
         * @return
         */
        @SelectProvider(type = MySelectProvider.class, method = "dynamicSQL")
        List<T> selectAll();
    }
    

      

         其中 MySelectProvider 是你要实现的一个类,该类需要继承 MapperTemplate。@RegisterMapper 注解可以避免 mappers 参数配置,通用 Mapper 检测到该接口被继承时,会自动注册。

    import org.apache.ibatis.mapping.MappedStatement;
    import tk.mybatis.mapper.mapperhelper.MapperHelper;
    import tk.mybatis.mapper.mapperhelper.MapperTemplate;
    import tk.mybatis.mapper.mapperhelper.SqlHelper;
    
    public class MySelectProvider extends MapperTemplate {
    
        public BaseSelectProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
            super(mapperClass, mapperHelper);
        }
      
        /**
         * 查询全部结果
         *
         * @param ms
         * @return
         */
        public String selectAll(MappedStatement ms) {
            final Class<?> entityClass = getEntityClass(ms);
            //修改返回值类型为实体类型
            setResultType(ms, entityClass);
            StringBuilder sql = new StringBuilder();
            sql.append(SqlHelper.selectAllColumns(entityClass));
            sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
            sql.append(SqlHelper.orderByDefault(entityClass));
            return sql.toString();
        }
    }

    其中 selectAll 方法名要和接口中定义的方法名一致。其次就是该方法的参数为 MappedStatement类型。

     在 selectAll 方法中,首先是获取了当前接口的实体类型:

     final Class<?> entityClass = getEntityClass(ms); 

    因为接口返回值类型为 List<T>,MyBatis 会认为返回值类型为 List<Object>,这和我们想要的实体类型不一样,所以下一行代码就是设置返回值类型:

     setResultType(ms, entityClass); 

    注意,只有返回 T 或者 List 时需要设置,返回 int 类型时不需要设置。

    接下来就是纯粹的拼接 XML 形式的 SQL 了。

    /select col1,col2...
    sql.append(SqlHelper.selectAllColumns(entityClass));
    //from tablename - 支持动态表名
    sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
    //order by xxx
    sql.append(SqlHelper.orderByDefault(entityClass));

    当你想要实现某种方法时,可以从已有的例子中找一个最接近的方法,在此基础上进行修改

    三.例:根据主键查询单个实体对象(过滤掉逻辑删除的实体,注:我的数据表逻辑删除字段定义为enabled_status)

     首先定义mapper

    @RegisterMapper
    public interface SelectByKeyAndNotDeletedMapper<T> {
    
        /**
         * 根据主键查询没有被逻辑删除的实体
         *
         * @return
         */
        @SelectProvider(type = SelectByKeyNotDeletedProvider.class, method = "dynamicSQL")
        T selectByKeyNotDeleted(Object key);
    }

    其次定义SelectByKeyNotDeletedProvider

    public class SelectByKeyNotDeletedProvider extends MapperTemplate {
    
        public SelectByKeyNotDeletedProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
            super(mapperClass, mapperHelper);
        }
    
        public String selectByKeyNotDeleted(MappedStatement ms) {
            final Class<?> entityClass = getEntityClass(ms);
            //将返回值修改为实体类型
            setResultType(ms, entityClass);
            StringBuilder sql = new StringBuilder();
            sql.append(SqlHelper.selectAllColumns(entityClass));
            sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
            sql.append(wherePKColumns(entityClass, false));
            return sql.toString();
        }
    
        private String wherePKColumns(Class<?> entityClass, boolean useVersion) {
            StringBuilder sql = new StringBuilder();
            sql.append("<where>");
            //获取全部列
            Set<EntityColumn> columnSet = EntityHelper.getPKColumns(entityClass);
            //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值
            for (EntityColumn column : columnSet) {
                sql.append(" AND " + column.getColumnEqualsHolder());
            }
            if (useVersion) {
                sql.append(whereVersion(entityClass));
            }
            //过滤被逻辑删除的数据
            sql.append(" AND enabled_status = 1 ");
            sql.append("</where>");
            return sql.toString();
        }
    }

    然后定义BasicMapper,让其继承通用Mapper接口以及上面自定义的SelectByKeyAndNotDeletedMapper接口。

     @tk.mybatis.mapper.annotation.RegisterMapper public interface BasicMapper<T> extends Mapper<T>, SelectByKeyAndNotDeletedMapper<T> { } 

    最后在通用service中引入,

      @Autowired private BasicMapper<T> mapper; 

    自定义*.Mapper都去继承BasicMapper<T>即可

     public interface UserPOMapper extends BasicMapper<UserPO> {} 

    注意:最新版本的tk已经支持根据注解@LogicDelete实现逻辑删除

  • 相关阅读:
    mac与windows协同(局域网)
    latex使用minted: Package minted Error: Missing Pygments output
    转换本地obsidian markdown路径为图床url
    您的连接不是私密连接
    OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ip": executable file not found in $PATH: unknown (Docker容器没有ip addr命令:exec ip addr 报错)
    通过命令验证docker容器相当一个轻量级的Linux运行环境,且每个容器内都有一个属于自己的文件系统,容器之间相互隔离
    虚拟机VMware 安装centos、常规配置、共享文件等
    阿里云服务器的购买、基本配置、(xshell)远程连接、搭建环境
    理解C#异步编程
    Asp.Net Core WebApi统一封装返回结果
  • 原文地址:https://www.cnblogs.com/enchaolee/p/11194916.html
Copyright © 2020-2023  润新知