插件簡介
PageHelper
與通用 Mapper
作者為同一人 abel533 居砖,使用這兩個插件可以極大地簡化 MyBatis
的開發(fā),如果你想深入了解Mybatis以及插件開發(fā)可以購買作者的書籍毕骡。
分頁插件 PageHelper
GitHub地址:https://github.com/pagehelper/Mybatis-PageHelper
如果你也在用 MyBatis削饵,建議嘗試該分頁插件,這一定是最方便使用的分頁插件
在沒有分頁插件之前挺峡,寫一個分頁需要兩條 SQL
語句葵孤,一條查詢一條統(tǒng)計担钮,然后計算封裝 PageBean
橱赠,這樣的代碼冗余而又枯燥,更重要的一點是數(shù)據(jù)庫遷移箫津,眾所周知不同的數(shù)據(jù)庫分頁寫法是不同的狭姨,而Mybatis
不同于 Hibernate
的是它只提供動態(tài) SQL
和結(jié)果集映射。值得慶幸的是苏遥,它雖然沒有為分頁提供良好的解決方案饼拍,但卻提供了 Interceptor
以供開發(fā)者自己擴展,這也是這款分頁插件的由來….
通用Mapper
GitHub地址:https://github.com/abel533/Mapper/
文檔地址:https://github.com/abel533/Mapper/wiki
gitee地址:https://gitee.com/free/Mapper
通用Mapper都可以極大的方便開發(fā)人員田炭∈Τ可以隨意的按照自己的需要選擇通用方法,還可以很方便的開發(fā)自己的通用方法教硫。
極其方便的使用MyBatis單表的增刪改查叨吮。
支持單表操作,不支持通用的多表聯(lián)合查詢瞬矩。
添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis與Spring Boot整合starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- MyBatis 通用Mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.3</version>
</dependency>
<!-- MyBatis 分頁插件pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<!-- mysql 驅(qū)動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
相關(guān)配置
spring:
application:
name: spring-boot-mbg
datasource:
url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
username: root
password: mysql123
driver-class-name: com.mysql.jdbc.Driver
mybatis:
config-location: classpath:mybatis/mybatis-config.xml # mybatis配置文件位置
mapper-locations: classpath:mybatis/mappers/*.xml # mapper映射文件位置
type-aliases-package: com.example.springbootmybatis.entity # 別名包
mapper:
mappers:
- com.example.springbootmbg.common.MyBaseMapper
identity: MYSQL # 取回主鍵的方式 MYSQL: SELECT LAST_INSERT_ID()
order: AFTER # 還可設(shè)置為 mapper.before = false
not-empty: true # insertSelective 和 updateByPrimaryKeySelective 中茶鉴,是否判斷字符串類型 !=''
style: camelhumpAndLowercase # 實體和表轉(zhuǎn)換時的默認規(guī)則:駝峰轉(zhuǎn)下劃線小寫形式
enableMethodAnnotation: true # 是否支持(getter 和 setter)在方法上使用注解,默認false
enumAsSimpleType: true # 枚舉類型當成基本類型對待
pagehelper:
helper-dialect: mysql
reasonable: false
support-methods-arguments: true
params: count=countSql
# mybatis sql日志
logging:
level:
com:
example:
springbootmbg:
mapper: debug
屬性解釋
通用Mapper
通用Mapper
屬性配置上面的注釋已經(jīng)很清楚了景用,這里不再做過多解釋涵叮,唯一一點是 mappers
配置的是自定義的 MyBaseMapper
接口,具體下面介紹伞插。
更多 通用Mapper
屬性配置可參考官方文檔 3.配置介紹部分
PageHelper
helperDialect
:分頁插件會自動檢測當前的數(shù)據(jù)庫鏈接割粮,自動選擇合適的分頁方式。 你可以配置 helperDialect
屬性來指定分頁插件使用哪種方言媚污。配置時舀瓢,可以使用下面的縮寫值:
oracle
, mysql
, mariadb
, sqlite
, hsqldb
, postgresql
, db2
, sqlserver
, informix
, h2
, sqlserver2012
, derby
特別注意:使用 SqlServer2012
數(shù)據(jù)庫時,需要手動指定為 sqlserver2012
杠步,否則會使用 SqlServer2005
的方式進行分頁氢伟。
reasonable
:分頁合理化參數(shù)榜轿,默認值為 false
,直接根據(jù)參數(shù)進行查詢 朵锣。當該參數(shù)設(shè)置為 true
時谬盐,pageNum<=0
時會查詢第一頁, pageNum>pages
(超過總數(shù)時)诚些,會查詢最后一頁飞傀。
supportMethodsArguments
:支持通過 Mapper
接口參數(shù)來傳遞分頁參數(shù),默認值 false
诬烹,分頁插件會從查詢方法的參數(shù)值中砸烦,自動根據(jù)上面 params
配置的字段中取值,查找到合適的值時就會自動分頁绞吁。 使用方法可以參考測試代碼中的 com.github.pagehelper.test.basic
包下的 ArgumentsMapTest
和 ArgumentsObjTest
幢痘。
params
:為了支持 startPage(Object params)
方法,增加了該參數(shù)來配置參數(shù)映射家破,用于從對象中根據(jù)屬性名取值颜说, 可以配置 pageNum
, pageSize
, count
, pageSizeZero
, reasonable
,不配置映射的用默認值汰聋, 默認值為pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
门粪。
更多 PageHelper
屬性配置可參考官方使用方法部分
MyBatis sql日志
對于 MyBatis sql
日志可以像上面那樣在 application.yml
文件中配置,但在項目中往往使用 logback
日志框架烹困,因此可以在 logback-spring.xml
配置文件中添加如下 logger
<logger name="com.example.springbootmbg.mapper" level="DEBUG" additivity="false"></logger>
MyBatis配置文件 mybatis-config.xml
src/main/resource/mybatis/mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--<typeAliases>
<package name="com.example.springbootmbg.entity"/>
</typeAliases>-->
</configuration>
Spring DevTools 配置
在使用 DevTools
時玄妈,通用Mapper
經(jīng)常會出現(xiàn) class x.x.A cannot be cast to x.x.A。
同一個類如果使用了不同的類加載器,就會產(chǎn)生這樣的錯誤,所以解決方案就是讓 通用Mapper
和實體類使用相同的類加載器即可熊昌。
DevTools
默認會對 IDE
中引入的所有項目使用 restart 類加載器
,對于引入的 jar
包使用 base 類加載器
瞭郑,因此只要保證 通用Mapper
的 jar
包使用 restart 類加載器
即可。
在 src/main/resources
中創(chuàng)建 META-INF
目錄鸭你,在此目錄下添加 spring-devtools.properties
配置屈张,內(nèi)容如下:
restart.include.mapper=/mapper-[\\w-\\.]+jar
restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar
使用這個配置后,就會使用 restart 類加載器
加載 include
進去的 jar
包袱巨。
以上 Spring DevTools 配置
內(nèi)容引自官方Spring 集成示例——集成Spring Boot部分
通用Mapper MBG代碼生成
Maven集成MBG插件
pom.xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<configurationFile>
${basedir}/src/main/resources/generator/generatorConfig.xml
</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
</plugin>
MBG配置文件
詳細配置參數(shù)可參考http://git.oschina.net/free/Mybatis_Utils/blob/master/MybatisGeneator/MybatisGeneator.md 和官方文檔 4.1專用代碼生成器部分在此不作過多解釋
src/main/resources/generator/generatorConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="application.yml"/>
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="autoDelimitKeywords" value="true"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.example.springbootmbg.common.MyBaseMapper"/>
</plugin>
<commentGenerator>
<!-- suppressAllComments:阻止生成注釋阁谆,默認為false -->
<property name="suppressAllComments" value="false"/>
<!-- suppressDate:阻止生成的注釋包含時間戳,默認為false -->
<property name="suppressDate" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/test_db"
userId="root"
password="mysql123">
</jdbcConnection>
<!-- 對應(yīng)生成的pojo所在包 -->
<javaModelGenerator targetPackage="com.example.springbootmbg.entity" targetProject="src/main/java"/>
<!-- 對應(yīng)生成的mapper所在目錄 -->
<sqlMapGenerator targetPackage="mybatis/mappers" targetProject="src/main/resources"/>
<!-- 對應(yīng)生成的mapper接口所在包 -->
<javaClientGenerator targetPackage="com.example.springbootmbg.mapper" targetProject="src/main/java"
type="XMLMAPPER"/>
<table tableName="tb_user" domainObjectName="User">
<!--mysql 配置-->
<!--<generatedKey column="id" sqlStatement="Mysql" />-->
<!--oracle 配置-->
<!--<generatedKey column="id" sqlStatement="select SEQ_{1}.nextval from dual" identity="false" type="pre"/>-->
</table>
</context>
</generatorConfiguration>
<table>
標簽需要根據(jù)數(shù)據(jù)庫表自行增添
com.example.springbootmbg.common.MyBaseMapper
package com.example.springbootmbg.common;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
public interface MyBaseMapper<T> extends Mapper<T>, MySqlMapper<T> {
//TODO
//FIXME 特別注意愉老,該接口不能被掃描到场绿,否則會出錯
}
很簡單的一個接口,繼承了 通用Mapper
提供的 tk.mybatis.mapper.common.Mapper
及tk.mybatis.mapper.common.MySqlMapper
接口嫉入,MBG
生成的 Mapper
接口都會繼承這個接口焰盗,從而間接繼承前面提到的兩個接口璧尸,從而獲得 通用Mapper
的魔力(其實就是獲得了一系列 通用Mapper
提供的單表增、刪熬拒、改爷光、查方法而已),具體方法可以查看那兩個接口澎粟。
掃描Mapper接口所在的包
需要在啟動類上添加 @MapperScan
注解蛀序,但請注意這個注解不是 提供的 MyBatis
而是 org.mybatis.spring.annotation.MapperScan
通用Mapper
提供的 tk.mybatis.spring.annotation.MapperScan
package com.example.springbootmbg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@MapperScan(basePackages = {"com.example.springbootmbg.mapper"})
public class SpringBootMbgApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMbgApplication.class, args);
}
}
注意:這里有個坑就是這個自定義
MyBaseMapper
接口不能被掃描到,否則會報錯活烙,因此上面將該接口放在了別的包下徐裸。
不嫌麻煩的話可以去
MBG
生成的每個Mapper
接口上添加@Mapper
注解
使用MBG生成實體類、Mapper接口及xml映射文件
在項目 Maven
插件中找到 mybatis-generator
插件啸盏,點擊 mybatis-generator:generate
一下就可以了重贺,如果數(shù)據(jù)庫連接信息配置正確的話,不出意外就會順利在配置的目錄下生成對應(yīng)的實體類宫补、Mapper接口及xml映射文件啦檬姥。
為示例這里創(chuàng)建一張用戶表
CREATE TABLE `tb_user` (
`id` varchar(64) NOT NULL COMMENT '用戶id',
`username` varchar(64) NOT NULL COMMENT '用戶名',
`password` varchar(64) NOT NULL COMMENT '用戶密碼',
`face_icon` varchar(255) DEFAULT NULL COMMENT '用戶頭像',
`nickname` varchar(64) NOT NULL COMMENT '用戶昵稱',
`fans_counts` int(11) DEFAULT '0' COMMENT '用戶粉絲數(shù)',
`follow_counts` int(11) DEFAULT '0' COMMENT '關(guān)注其他用戶數(shù)',
`receive_like_counts` int(11) DEFAULT '0' COMMENT '收到的喜歡數(shù)目',
`create_time` datetime NOT NULL COMMENT '創(chuàng)建時間',
`update_time` datetime NOT NULL COMMENT '更新時間',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用戶表';
生成的代碼大致像下面這樣
com.example.springbootmbg.entity.user
package com.example.springbootmbg.entity;
import java.util.Date;
import javax.persistence.*;
@Table(name = "tb_user")
public class User {
/**
* 用戶id
*/
@Id
private String id;
/**
* 用戶名
*/
private String username;
/**
* 用戶密碼
*/
private String password;
/**
* 用戶頭像
*/
@Column(name = "face_icon")
private String faceIcon;
/**
* 用戶昵稱
*/
private String nickname;
/**
* 用戶粉絲數(shù)
*/
@Column(name = "fans_counts")
private Integer fansCounts;
/**
* 關(guān)注其他用戶數(shù)
*/
@Column(name = "follow_counts")
private Integer followCounts;
/**
* 收到的喜歡數(shù)目
*/
@Column(name = "receive_like_counts")
private Integer receiveLikeCounts;
/**
* 創(chuàng)建時間
*/
@Column(name = "create_time")
private Date createTime;
/**
* 更新時間
*/
@Column(name = "update_time")
private Date updateTime;
// setters and getters
}
通用Mapper
會用到Jpa
的幾個簡單注解曾我,這里不做解釋
com.example.springbootmbg.mapper.UserMapper
package com.example.springbootmbg.mapper;
import com.example.springbootmbg.common.MyBaseMapper;
import com.example.springbootmbg.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends MyBaseMapper<User> {
}
生成的代碼不帶
@Repository
注解
src/main/resource/mybatis/mappers/UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootmbg.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.example.springbootmbg.entity.User">
<!--
WARNING - @mbg.generated
-->
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="face_icon" jdbcType="VARCHAR" property="faceIcon" />
<result column="nickname" jdbcType="VARCHAR" property="nickname" />
<result column="fans_counts" jdbcType="INTEGER" property="fansCounts" />
<result column="follow_counts" jdbcType="INTEGER" property="followCounts" />
<result column="receive_like_counts" jdbcType="INTEGER" property="receiveLikeCounts" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
</resultMap>
</mapper>
測試
com.example.springbootmbg.mapper.UserMapperTest
package com.example.springbootmbg.mapper;
import com.example.springbootmbg.entity.User;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
private static final Logger logger = LoggerFactory.getLogger(UserMapperTest.class);
@Test
public void testInsert() {
User user = new User();
user.setId(UUID.randomUUID().toString().replaceAll("-", ""));
user.setUsername("aaa");
user.setPassword("123456");
user.setNickname("aaa");
user.setCreateTime(new Date());
user.setUpdateTime(new Date());
userMapper.insertSelective(user);
User user2 = new User();
user2.setId(UUID.randomUUID().toString().replaceAll("-", ""));
user2.setUsername("bbb");
user2.setPassword("123456");
user2.setNickname("bbb");
user2.setCreateTime(new Date());
user2.setUpdateTime(new Date());
userMapper.insertSelective(user2);
}
@Test
public void testPage() {
PageHelper.startPage(1, 10);
List<User> userList = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<>(userList);
logger.info("pageInfo: {}", pageInfo);
}
}