文章目录

  • 一、什么是通用mapper
  • 二、什么是pagehelper
  • 三、MyBatis之分页插件(PageHelper)工作原理
  • 四、mapper、pagehelper maven引入配置
  • 1. 和 Spring 集成
  • 1.1 MapperScannerConfigurer
  • 2. spring boot v2.2.1集成通用mapper
  • 第一步:maven引入
  • 第二步:添加配置
  • 第三步: @MapperScan 注解配置
  • 五、通用mapper基本原理
  • 六、如何使用通用mapper
  • 1. 定义实体类
  • 2. 创建 Mapper 接口
  • 3. 通用mapper主键策略
  • JDBC 支持通过 getGeneratedKeys 方法取回主键的情况
  • 支持自增的数据库
  • 七、通用 Mapper常用方法
  • select方法
  • Insert方法
  • Update方法
  • Delete方法


一、什么是通用mapper

官网 https://mybatis.io/
官方github文档 https://github.com/abel533/Mapper/wiki

辅助mybatis单表开发的组件。它不是为了替代mybatis,而是让mybatis的开发更方便。用于解决原生mybatis痛点:

原生Mybatis的痛点
1、mapper.xml文件里有大量的sql,当数据库表字段变动,配置文件就要修改

2、需要自己实现sql分页,select * from table where . . . limit 1,3

自己手写分页,除了传参page、pageSize,还需要返回条目总数count。

3、数据库可移植性差:如果项目更换数据库,比如oracle–>mysql,mapper.xml中的sql要重新写,因为Oracle的PLSQL 和mysql 支持的函数是不同的。

4、生成的代码量过大。

5、批量操作,批量插入,批量更新,需要自写。

二、什么是pagehelper

三、MyBatis之分页插件(PageHelper)工作原理

MyBatis之分页插件(PageHelper)工作原理
参考URL:

com.github.pagehelper.PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件。

PageHelper除了本身的jar包外,它还依赖了一个叫jsqlparser的jar包,使用时,我们不需要单独指定jsqlparser的maven依赖,maven的间接依赖会帮我们引入。

四、mapper、pagehelper maven引入配置

1. 和 Spring 集成

官方:https://github.com/abel533/Mapper/wiki/1.2-spring

<!-- https://mvnrepository.com/artifact/tk.mybatis/mapper -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>4.1.5</version>
        </dependency>
        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- jpa -->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>

注意:项目依赖于JPA的注解,需要引入persistence-api-1.0.jar或者添加Maven依赖

mybatis.xml配置添加

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations">
            <array>
                <value>classpath:mapper/*.xml</value>
            </array>
        </property>
        <property name="typeAliasesPackage" value="com.xxx.xxx.entity;com.xxx.xxx.pojo"/>
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <!-- 这里的几个配置主要演示如何使用,如果不理解,一定要去掉下面的配置 -->
                    <property name="properties">
                        <value>
                            helperDialect=mysql
                            reasonable=true
                            supportMethodsArguments=true
                            params=count=countSql
                            autoRuntimeDialect=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

    <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.xdja.dialer.dao"/>
    </bean>

只需要将org.mybatis.spring.mapper.MapperScannerConfigurer改成tk.mybatis.spring.mapper.MapperScannerConfigurer

helperDialect=mysql:代表指定分页插件使用mysql。
rowBoundsWithCount=true:代表使用RowBounds分页会进行count查询。
reasonable=true:当pageNum <= 0时会查询第一页,pageNum > 总数的时候,会查询最后一页。

1.1 MapperScannerConfigurer

Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
参考URL:

Mybatis在与Spring集成的时候可以配置MapperFactoryBean来生成Mapper接口的代理. 例如

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

MapperFactoryBean 创建的代理类实现了 UserMapper 接口,并且注入到应用程序中。 因为代理创建在运行时环境中 ,那么指定的映射器必须是一个接口,而不是一个具体的实现类。

上面的配置有一个很大的缺点,就是系统有很多的配置文件时 全部需要手动编写。

因此就有了MapperScannerConfigurer:
没有必要在 Spring 的 XML 配置文件中注册所有的映射器。相反,你可以使用一个 MapperScannerConfigurer , 它 将 会 查 找 类 路 径 下 的 映 射 器 并 自 动 将 它 们 创 建 成 MapperFactoryBean。

要创建 MapperScannerConfigurer,可以在 Spring 的配置中添加如下代码:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>

basePackage 属性是让你为映射器接口文件设置基本的包路径。 你可以使用分号或逗号 作为分隔符设置多于一个的包路径。每个映射器将会在指定的包路径中递归地被搜索到。

2. spring boot v2.2.1集成通用mapper

第一步:maven引入
<dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>
第二步:添加配置

详细的配置项请阅读手册:Mapper Config
https://gitee.com/free/Mapper/wikis/3.config?parent=3.config

如果你没有使用 @MapperScan 注解,你就需要在你的接口上增加 @Mapper 注解,否则 MyBatis 无法判断扫描哪些接口。

如果你需要对通用 Mapper 进行配置,你可以在 Spring Boot 的配置文件中配置 mapper. 前缀的配置。

mapper.mappers=tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.common.Mapper2
mapper.not-empty=false
mapper.identity=MYSQL

根据官方如下描述,mapper.mappers最新的可以不用了。

在 4.0 以前这是一个非常重要的参数,当时只有通过 mappers 配置过的接口才能真正调用,由于很多人不注意看文档,通用 Mapper 90% 的问题都出在这个参数上。

4.0 之后,增加了一个 @RegisterMapper 注解,通用 Mapper 中提供的所有接口都有这个注解,有了该注解后,通用 Mapper 会自动解析所有的接口,如果父接口(递归向上找到的最顶层)存在标记该注解的接口,就会自动注册上。因此 4.0 后使用通用 Mapper 提供的方法时,不需要在配置这个参数。

当你自己扩展通用接口时,建议加上该注解,否则就要配置 mappers 参数。

第三步: @MapperScan 注解配置

你可以给带有 @Configuration 的类配置该注解,或者直接配置到 Spring Boot 的启动类上,如下:

@tk.mybatis.spring.annotation.MapperScan(basePackages = "扫描包")
@SpringBootApplication
public class SampleMapperApplication implements CommandLineRunner {

注意:这里使用的 tk.mybatis.spring.annotation.MapperScan !

五、通用mapper基本原理

TKmybatis的框架介绍和原理分析及Mybatis新特性演示
参考URL:

此框架为我们实现这些功能所有的改动都在Mapper层面,所有的Mapper都继承了tk.mybatis.mapper.common.Mapper

public interface WorkerMapper extends Mapper {}

Mapper接口的声明如下,可以看到Mapper接口实现了所有常用的方法

public interface Mapper<T> extends
        BaseMapper<T>,
        ExampleMapper<T>,
        RowBoundsMapper<T>,
        Marker {

}

通用mapper生成的PersonMapper.java接口,extends MyMapper<?>。

六、如何使用通用mapper

通用Mapper和PageHelper插件 学习笔记
参考URL: https://cloud.tencent.com/developer/article/1143564

1. 定义实体类

继承通用的Mapper,必须指定泛型

泛型(实体类)的类型必须符合要求(实体类定义要求):
1、表名默认使用类名,驼峰转下划线(只对大写字母进行处理),如UserInfo默认对应的表名为user_info。

2、表名可以使用@Table(name = “tableName”)进行指定,对不符合第一条默认规则的可以通过这种方式指定表名.

3、字段默认和@Column一样,都会作为表字段,表字段默认为Java对象的Field名字驼峰转下划线形式.

4、可以使用@Column(name = “fieldName”)指定不符合第3条规则的字段名

5、使用@Transient注解可以忽略字段,添加该注解的字段不会作为表字段使用.

6、建议一定是有一个@Id注解作为主键的字段,可以有多个@Id注解的字段作为联合主键.

经过上面简单的配置后,相当于就有了 MyBatis 中的 关系映射了,特别注意,这个映射关系只对通用 Mapper 有效,自己手写方法时,需要自己处理映射关系。

注意: 如果POJO类名和表名不对应一定要在类名上指名对应的表名。

总结:原生mybatis生成的POJO中,纯代码,不包含注解。
通用mapper生成的POJO中,属性加了 (持久化)注解,与数据库字段进行匹配。

注意:为了可以使用通用mapper中通过主键查询的方法:一定要配置主键@Id

2. 创建 Mapper 接口

通用Mapper 提供了大量的通用接口,这里以最常用的Mapper 接口为例子
该实体类对应的数据库操作接口如下:

import tk.mybatis.mapper.common.Mapper;

public interface CountryMapper extends Mapper<Country> {
}

只要配置MyBatis 时能注册或者扫描到该接口,该接口提供的方法就都可以使用。
该接口默认继承的方法如下:
selectOne
select
selectAll
selectCount
selectByPrimaryKey

3. 通用mapper主键策略

通用mapper主键策略
参考URL:

首先主键策略和数据库关系很大,有些数据库支持主键自增,而有些数据库只能通过序列来获得。

新增的@KeySql 注解用于替换 @GeneratedValue 注解,因此 @KeySql 能以更简单方式实现原来的功能,下面的示例都先使用 @KeySql 进行配置,然后在使用 @GeneratedValue,大家

JDBC 支持通过 getGeneratedKeys 方法取回主键的情况

这种情况首先需要数据库支持自增,其次数据库提供的 JDBC 支持 getGeneratedKeys 方法。

常见的如 MySql,SqlServer 支持这种模式。

这种情况下,配置主键策略最简单。

用法如下:

@Id
@KeySql(useGeneratedKeys = true)
private Long id;

@Id
@GeneratedValue(generator = "JDBC")
private Long id;

对应 生成mybatis的xml如下:

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into country (id, countryname, countrycode)
    values (#{id},#{countryname},#{countrycode})
</insert>

注意:
SqlServer 中使用时,需要设置 id 的 insertable=false

useGeneratedKeys=“true” 表示给主键设置自增长
keyProperty=“userId” 表示将自增长后的Id赋值给实体类中的userId字段。

支持自增的数据库

支持自增的数据库列表如下:

DB2: VALUES IDENTITY_VAL_LOCAL()
MYSQL: SELECT LAST_INSERT_ID()
SQLSERVER: SELECT SCOPE_IDENTITY()
CLOUDSCAPE: VALUES IDENTITY_VAL_LOCAL()
DERBY: VALUES IDENTITY_VAL_LOCAL()
HSQLDB: CALL IDENTITY()
SYBASE: SELECT @@IDENTITY
DB2_MF: SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1
INFORMIX: select dbinfo(‘sqlca.sqlerrd1’) from systables where tabid=1

这类数据库主键策略配置示例如下:

@Id
//DEFAULT 需要配合 IDENTITY 参数(ORDER默认AFTER)
@KeySql(dialect = IdentityDialect.DEFAULT)
private Integer id;
//建议直接指定数据库
@Id
@KeySql(dialect = IdentityDialect.MYSQL)
private Integer id;

七、通用 Mapper常用方法

select方法

方法:List select(T record);

说明:根据实体中的属性值进行查询,查询条件使用等号

方法:T selectByPrimaryKey(Object key);

说明:根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号

方法:List selectAll();

说明:查询全部结果,select(null)方法能达到同样的效果

方法:T selectOne(T record);

说明:根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号

方法:int selectCount(T record);

说明:根据实体中的属性查询总数,查询条件使用等号

Insert方法

方法:int insert(T record);
说明:保存一个实体,null的属性也会保存,不会使用数据库默认值

方法:int insertSelective(T record);
说明:保存一个实体,null的属性不会保存,会使用数据库默认值

注意,这里返回的插入成功的行数。 要拿主键id,从传入的实体类中拿。

Update方法

方法:int updateByPrimaryKey(T record);
说明:根据主键更新实体全部字段,null值会被更新

方法:int updateByPrimaryKeySelective(T record);
说明:根据主键更新属性不为null的值

Delete方法

方法:int delete(T record);
说明:根据实体属性作为条件进行删除,查询条件使用等号

方法:int deleteByPrimaryKey(Object key);
说明:根据主键字段进行删除,方法参数必须包含完整的主键属性