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实现逻辑删除

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • mybatis如何通过接口查找对应的mapper.xml及方法执行详解

    本文主要介绍的是关于mybatis通过接口查找对应mapper.xml及方法执行的相关内容,下面话不多说,来看看详细的介绍: 在使用mybatis的时候,有一种方式是 BookMapper bookMapper = SqlSession().getMapper(BookMapper.class) 获取接口,然后调用接口的方法.只要方法名和对应的mapper.xml中的id名字相同,就可以执行sql. 那么接口是如何与mapper.xml对应的呢? 首先看下,在getMapper()方法是如何操作

  • 详解mybatis通过mapper接口加载映射文件

    通过 mapper 接口加载映射文件,这对于后面 ssm三大框架 的整合是非常重要的.那么什么是通过 mapper 接口加载映射文件呢? 我们首先看以前的做法,在全局配置文件 mybatis-configuration.xml 通过 <mappers> 标签来加载映射文件,那么如果我们项目足够大,有很多映射文件呢,难道我们每一个映射文件都这样加载吗,这样肯定是不行的,那么我们就需要使用 mapper 接口来加载映射文件 以前的做法: 改进做法:使用 mapper 接口来加载映射文件 1.定义

  • Mybatis MapperScannerConfigurer自动扫描Mapper接口生成代理注入到Spring的方法

    前言 Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring Mybatis在与Spring集成的时候可以配置 MapperFactoryBean来生成Mapper接口的代理. 例如: <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mappe

  • 详解MyBatis的getMapper()接口、resultMap标签、Alias别名、 尽量提取sql列、动态操作

    一.getMapper()接口 解析:getMapper()接口 IDept.class定义一个接口, 挂载一个没有实现的方法,特殊之处,借楼任何方法,必须和小配置中id属性是一致的 通过代理:生成接口的实现类名称,在MyBatis底层维护名称$$Dept_abc,selectDeptByNo() 相当于是一个强类型 Eg 第一步:在cn.happy.dao中定义一个接口 package cn.happy.dao; import java.util.List; import cn.happy.e

  • 通过MyBatis读取数据库数据并提供rest接口访问

    1 mysql 创建数据库脚本 -- phpMyAdmin SQL Dump -- version 4.2.11 -- http://www.phpmyadmin.net -- -- Host: localhost -- Generation Time: 2016-08-02 18:13:50 -- 服务器版本: 5.6.21 -- PHP Version: 5.6.3 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = &q

  • Mybatis接口式编程的原理

    Mybatis 有两种实现方式 其一:通过xml配置文件实现 其二:面向接口编程的实现 前者原理在Mybatis运行套路里面大致说了一下,此节说的是后者,面向接口的编程,可以解决掉 namespace / 传入参数 / 返回值 / 与Sql关联Id 等四处风险. 意思就是,Mybatis配置文件Dao.xml找了一个接口作为自己的代言人,并告诉其他的Java对象,以后访问数据库不要再骚扰我这个Dao.xml文件了,你去找我的代言人助理它会全权负责的. 如果接口助理要全权负责Dao.xml文件的所

  • tk.mybatis扩展通用接口使用详解

    一.tk.mybatis已经为我们封装好了许多拆箱即用的通用mapper,但在实际的项目开发中想必不少小伙伴在数据库设计中都会采用逻辑删除这种方案,再去使用通用的mapper接口就不行了. 这时候就需要我们封装一些扩展的通用Mapper接口. 二.项目中提供了大量现成的方法,这些方法可以作为扩展时的参考. 例如 selectAll 方法. 首先定义接口: @RegisterMapper public interface SelectAllMapper<T> { /** * 查询全部结果 * *

  • Mybatis各种查询接口使用详解

    目录 一.查询一个实体类对象 二.查询一个list集合 三.查询单个数据 四.查询一个数据为map集合 五.查询多条数据为map集合 一.查询一个实体类对象 ①创建SelectMapper接口 若sql语句查询的结果为多条时,一定不能以实现类类型作为方法的返回值 否则会抛出异常TooManyResultsException 若sql语句查询的结果为1条时,此时可以使用实体类类型或list集合类型作为方法的返回值 /** * 根据id查询用户信息 * @param id * @return */

  • SpringBoot整合MyBatis逆向工程及 MyBatis通用Mapper实例详解

    一.添加所需依赖,当前完整的pom文件如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&q

  • ASP.NET Core扩展库之Http通用扩展库的使用详解

    本文将介绍Xfrogcn.AspNetCore.Extensions扩展库对于Http相关的其他功能扩展,这些功能旨在处理一些常见需求, 包括请求缓冲.请求头传递.请求头日志范围.针对HttpClient与HttpRequestMessage.HttpResponseMessage的扩展方法. 一.开启服务端请求缓冲 ASP.NET Core 中请求体是不能多次读取的,由于在MVC中,框架已经读取过请求体,如果你在控制器中再次读取,将会引发异常,如下示例: [ApiController] [Ro

  • Mybatis Generator最完美配置文件详解(完整版)

    最近没做项目,重新整理了一个最完整的Mybatis Generator(简称MBG)的最完整配置文件,带详解,再也不用去看EN的User Guide了: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"

  • MyBatis 执行动态 SQL语句详解

    大家基本上都知道如何使用 MyBatis 执行任意 SQL,使用方法很简单,例如在一个 XXMapper.xml 中: <select id="executeSql" resultType="map"> ${_parameter} </select> 你可以如下调用: sqlSession.selectList("executeSql", "select * from sysuser where enabled

  • 基于Spring + Spring MVC + Mybatis 高性能web构建实例详解

    一直想写这篇文章,前段时间痴迷于JavaScript.NodeJs.AngularJS,做了大量的研究,对前后端交互有了更深层次的认识. 今天抽个时间写这篇文章,我有预感,这将是一篇很详细的文章,详细的配置,详细的注释,看起来应该很容易懂. 用最合适的技术去实现,并不断追求最佳实践.这就是架构之道. 希望这篇文章能给你们带来一些帮助,同时希望你们可以为这个项目贡献你的想法. 源码地址:https://github.com/Eliteams/quick4j 点击打开 源码地址:https://gi

  • MyBatis Mapper代理使用方法详解

    MyBatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 下文重点给大家介绍mapper代理使用方法. 一.开发人员需要完成的任务: mapper.xml映射文件和mapper.java 二.开发规范

  • java 中MyBatis注解映射的实例详解

    java  中MyBatis注解映射的实例详解 1.普通映射 @Select("select * from mybatis_Student where id=#{id}") public Student getStudent(int id); @Insert("insert into mybatis_Student (name, age, remark, pic,grade_id,address_id) values (#{name},#{age},#{remark}, #{

  • Java对象Serializable接口实现详解

    这篇文章主要介绍了Java对象Serializable接口实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 导读 最近这段时间一直在忙着编写Java业务代码,麻木地搬着Ctrl-C.Ctrl-V的砖,在不知道重复了多少次定义Java实体对象时"implements Serializable"的C/V大法后,脑海中突然冒出一个思维(A):问了自己一句"Java实体对象为什么一定要实现Serializable接口呢?&qu

随机推荐