文章目录
- 一、什么是通用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);
说明:根据主键字段进行删除,方法参数必须包含完整的主键属性