在以前的博客中介绍了Spring boot
整合Mybatis
以及Druid
,本篇博客主要介绍如何在Spring boot中整合Mybatis的逆向工程Mybatis Generator
如下简称为MBG
,以及实际项目中十分方便简单的物理分页插件PageHelper
,使用这些插件能极大的减轻咱们的开发过程那些简单重复的过程,本篇博客在项目已经整合了Mybatis
的基础上进行,没有整合Mybatis
的朋友能够参考 Spring boot整合Mybatis。php
文章首发于我的博客:【www.xiongfrblog.cn】html
使用过Mybatis
的朋友应该都知道,在使用以前咱们须要根据数据库表的状况在项目中建立出对应的实体类,sql
语句接口层,XML
文件等,这一系列的操做是很是简单的,但又是必不可少的,耗时耗力还没什么养分,若是数据库的表足够多的时候还要手动建立这些内容,那对程序员来讲简直是一种折磨,因此在实际的开发过程当中MBG
是很是有必要的,下面咱们就详细介绍如何在Spring boot
项目中配置MBG
。java
在<plugins></plugins>
标签中添加以下内容:mysql
<!-- Mybatis Generator插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<!-- 配置文件的位置 -->
<configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
<!-- 容许移动生成的文件 -->
<verbose>true</verbose>
<!-- 是否覆盖,true表示会替换生成的Java文件,false则不覆盖 -->
<overwrite>true</overwrite>
</configuration>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
</plugin>
复制代码
其中configurationFile
:MBG
配置文件的位置能够根据本身的实际状况改写。git
注意:如上所示,咱们在插件内还添加了mysql
,mybatis
的依赖项,这两项依赖咱们在项目的依赖项里已经添加过了,可是这里还须要再添加一次,我在配置这里的时候若是这里不添加执行插件的时候就会报错。程序员
这一步是咱们生成实体类等的关键,全部的规则都是在这个配置文件里配置的。 首先在src/main/resources
目录下建立generator
目录,在该目录下建立generatorConfig.xml
配置文件,内容以下:github
<?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.properties"/>
<!-- defaultModelType="flat" s设置复合主键时不单独为主键建立实体 -->
<context id="MySql" defaultModelType="flat" targetRuntime="MyBatis3Simple">
<property name="javaFileEncoding" value="UTF-8"/>
<!-- 当表名或者字段名为SQL关键字的时候,能够设置该属性为true,MBG会自动给表名或字段名添加分隔符(反单引号) -->
<property name="autoDelimitKeywords" value="true"/>
<!-- 因为beginningDelimiter和endingDelimiter的默认值为双引号("),在Mysql中不能这么写,因此还要将这两个默认值改成反单引号(`), -->
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 生成的POJO实现java.io.Serializable接口 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<!--注释-->
<commentGenerator>
<!-- 阻止生成注释 -->
<property name="suppressAllComments" value="true"/>
<!-- 注释里不添加日期 -->
<property name="suppressDate" value="true"/>
</commentGenerator>
<!-- 数据库链接,直接经过${}读取application.properties里的配置 -->
<jdbcConnection driverClass="${spring.datasource.driverClassName}" connectionURL="${spring.datasource.url}" userId="${spring.datasource.username}" password="${spring.datasource.password}"/>
<!-- 生成POJO对象,并将类放到com.web.springbootmybatis.entity包下 -->
<javaModelGenerator targetPackage="com.web.springboot.entity" targetProject="src/main/java"></javaModelGenerator>
<!-- 生成mapper xml文件,并放到resources下的mapper文件夹下 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"></sqlMapGenerator>
<!-- 生成mapper xml对应dao接口,放到com.web.springbootmybatis.dao包下-->
<javaClientGenerator targetPackage="com.web.springboot.dao" targetProject="src/main/java" type="XMLMAPPER"></javaClientGenerator>
<!-- table标签能够有多个,至少一个,tableName指定表名,可使用_和%通配符,我这里的配置代表匹配全部的表 -->
<table tableName="%">
<!-- 是否只生成POJO对象 -->
<property name="modelOnly" value="false"/>
<!-- 插入一条数据时,将id映射到实体类中 -->
<generatedKey column="id" sqlStatement="Mysql"/>
</table>
</context>
</generatorConfiguration>
复制代码
上面的配置是最经常使用的配置,注意使用的时候包名,数据库链接等某些配置须要根据本身的实际状况改写,通常使用这个就已经能够了,若是有其余的特别的需求能够参考这篇博客,里边讲解了该配置文件全部标签,属性的意思,解释的很是清楚,想要深刻了解的朋友请移步【传送门】web
eclipse
中,右键项目-->Run As
-->Maven build...
-->在Goals
中填写命令mybatis-generator:generate
,点击Run
便可。pom.xml
文件所在的目录,运行命令mvn mybatis-generator:generate
便可。执行完以后会发现项目中已经创好了相应的类以及接口文件,项目结构图:spring
实体类demo:sql
package com.web.springboot.entity;
import java.io.Serializable;
public class SysUser implements Serializable {
private Integer id;
private String usercode;
private String username;
private String password;
private String salt;
private String locked;
private static final long serialVersionUID = 1L;
//省略getter.setter方法
}
复制代码
sql
接口demo:
package com.web.springboot.dao;
import com.web.springboot.entity.SysUser;
import java.util.List;
public interface SysUserMapper {
int deleteByPrimaryKey(Integer id);
int insert(SysUser record);
SysUser selectByPrimaryKey(Integer id);
List<SysUser> selectAll();
int updateByPrimaryKey(SysUser record);
}
复制代码
xml
文件demo:
<?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.web.springboot.dao.SysUserMapper" >
<resultMap id="BaseResultMap" type="com.web.springboot.entity.SysUser" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="usercode" property="usercode" jdbcType="VARCHAR" />
<result column="username" property="username" jdbcType="VARCHAR" />
<result column="password" property="password" jdbcType="VARCHAR" />
<result column="salt" property="salt" jdbcType="VARCHAR" />
<result column="locked" property="locked" jdbcType="CHAR" />
</resultMap>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from sys_user
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.web.springboot.entity.SysUser" >
<selectKey resultType="java.lang.Integer" keyProperty="id" order="BEFORE" >
SELECT LAST_INSERT_ID()
</selectKey>
insert into sys_user (id, usercode, username,
`password`, salt, locked
)
values (#{id,jdbcType=INTEGER}, #{usercode,jdbcType=VARCHAR}, #{username,jdbcType=VARCHAR},
#{password,jdbcType=VARCHAR}, #{salt,jdbcType=VARCHAR}, #{locked,jdbcType=CHAR}
)
</insert>
<update id="updateByPrimaryKey" parameterType="com.web.springboot.entity.SysUser" >
update sys_user
set usercode = #{usercode,jdbcType=VARCHAR},
username = #{username,jdbcType=VARCHAR},
`password` = #{password,jdbcType=VARCHAR},
salt = #{salt,jdbcType=VARCHAR},
locked = #{locked,jdbcType=CHAR}
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select id, usercode, username, `password`, salt, locked
from sys_user
where id = #{id,jdbcType=INTEGER}
</select>
<select id="selectAll" resultMap="BaseResultMap" >
select id, usercode, username, `password`, salt, locked
from sys_user
</select>
</mapper>
复制代码
我使用过的就这两种,亲测可行,还有其余的方式,具体请参考官方文档【传送门】
pom.xml
文件中添加完插件以后报错以下:
Plugin execution not covered by lifecycle configuration:
org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate
(execution: Generate MyBatis Artifacts, phase: generate-sources)
复制代码
解决方式:在<plugins>
标签外再套一个 <pluginManagement>
标签,以下:
<build>
<pluginManagement>
<plugins>
<plugin> ... </plugin>
<plugin> ... </plugin>
....
</plugins>
</pluginManagement>
</build>
复制代码
若是还没解决能够参照这里【传送门】
执行插件的时候失败并报错以下:
这一类错误出现的最多,解决的办法也不是惟一的,我根据本身的踩坑以及网上的资料提供两个大的方向。
解决方式:
generatorConfig.xml
里边有错误,好比变量名不对,包名不对等,仔细检查每每有惊喜。PageHelper
是一款很是简单的分页插件,只须要两行代码便可,不须要咱们本身编写sql
语句,自动帮咱们实现,很是好用,下面开始介绍Spring boot
整合PageHelper
。
首先在pom.xml
文件中添加依赖,以下:
<!-- springboot分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<!-- 特别注意版本问题 -->
<version>1.2.3</version>
</dependency>
复制代码
添加这个依赖以后,咱们其实不须要再添加mybatis-spring-boot-starter
的依赖了,由于pagehelper-spring-boot-starter
已经将其包含在其中了。
在aiilication.properties
文件中添加以下内容:
#pageHelper配置
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.params=count=countSql
pagehelper.supportMethodsArguments=true
复制代码
这里简单介绍下几个参数的意思,网上的教程广泛没写,这里介绍下:
helperDialect
:配置使用哪一种数据库语言,不配置的话pageHelper也会自动检测,我这里使用的mysql
。reasonable
:配置分页参数合理化功能,默认是false。启用合理化时,若是pageNum<1会查询第一页,若是pageNum>总页数会查询最后一页; 禁用合理化时,若是pageNum<1或pageNum>总页数会返回空数据。params
:为了支持startPage(Object params)
方法,增长了该参数来配置参数映射,用于从对象中根据属性名取值, 能够配置 pageNum
,pageSize
,count
,pageSizeZero
,reasonable
,不配置映射的用默认值,默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
。supportMethodsArguments
:支持经过Mapper
接口参数来传递分页参数,默认值false
,分页插件会从查询方法的参数值中,自动根据上面 params
配置的字段中取值,查找到合适的值时就会自动分页。更多参数的介绍请移步【传送门】
通过上面的介绍使用MBG
已经为咱们建立好了实体类,sql
接口以及xml
文件,如今咱们须要建立service
层,这里咱们利用泛型知识先建立一个service
层的基类接口IBaseService.java
,以后全部的service
接口都继承这个基类接口,这在实际的项目中是颇有必要的,减小重复不必的操做,代码以下:
package com.web.springboot.service;
import java.util.List;
/** * @author Promise * @createTime 2019年1月20日 下午8:24:40 * @description service接口层基类,包含基本的 CRUD操做。 */
public interface IBaseService<T> {
/** * 根据主键删除 * @param id * @return */
int deleteByPrimaryKey(Object id);
/** * 新增一条记录 * @param entity * @return */
int insert(T entity);
/** * 根据主键查询 * @param id * @return */
T selectByPrimaryKey(Object id);
/** * 查询所有记录 * @return */
List<T> selectAll();
/** * 根据主键修改数据 * @param entity * @return */
int updateByPrimaryKey(T entity);
}
复制代码
该基类接口定义了基本的CRUD
操做,我这里写的比较简单,实际中彻底能够根据本身的需求完善。
而后建立ISysUserService.java
接口,继承该基类接口,并定义两个咱们验证pageHelper
的方法:
package com.web.springboot.service;
import java.util.List;
import com.github.pagehelper.PageInfo;
import com.web.springboot.entity.SysUser;
/** * @author Promise * @createTime 2019年1月20日 下午8:31:09 * @description */
public interface ISysUserService extends IBaseService<SysUser>{
List<SysUser> findAllByPage(int pageNum, int pageSize);
PageInfo<SysUser> findAllByPage2(int pageNum, int pageSize);
}
复制代码
findAllByPage
:实现简单的分页,返回所需对象的list
集合,其中参数pageNum
表明当前页,pageSize
表明每页多少条数据。findAllByPage2
:实现简单的分页,返回PageInfo<T>
对象,包括所需对象的list
集合,还包括数据库总记录数,总页数,当前页,下一页等诸多信息,其中参数pageNum
表明当前页,pageSize
表明每页多少条数据。能够根据项目实际须要选择使用哪种方法。
接口实现类SysUserServiceImpl.java
,代码以下:
package com.web.springboot.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.web.springboot.dao.SysUserMapper;
import com.web.springboot.entity.SysUser;
import com.web.springboot.service.ISysUserService;
/** * @author Promise * @createTime 2019年1月20日 下午8:31:50 * @description */
@Service("sysUserService")
public class SysUserServiceImpl implements ISysUserService{
@Autowired
private SysUserMapper sysUserMapper;
@Override
public int deleteByPrimaryKey(Object id) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int insert(SysUser entity) {
// TODO Auto-generated method stub
return 0;
}
@Override
public SysUser selectByPrimaryKey(Object id) {
// TODO Auto-generated method stub
return sysUserMapper.selectByPrimaryKey((Integer)id);
}
@Override
public List<SysUser> selectAll() {
// TODO Auto-generated method stub
return null;
}
@Override
public int updateByPrimaryKey(SysUser entity) {
// TODO Auto-generated method stub
return 0;
}
@Override
public List<SysUser> findAllByPage(int pageNum, int pageSize) {
// TODO Auto-generated method stub
PageHelper.startPage(pageNum, pageSize);
List<SysUser> lists = sysUserMapper.selectAll();
return lists;
}
@Override
public PageInfo<SysUser> findAllByPage2(int pageNum, int pageSize) {
// TODO Auto-generated method stub
PageHelper.startPage(pageNum, pageSize);
List<SysUser> lists = sysUserMapper.selectAll();
PageInfo<SysUser> pageInfo = new PageInfo<SysUser>(lists);
return pageInfo;
}
}
复制代码
能够看到该类中实现了咱们在基类接口IBaseService.java
以及ISysUSerService.java
里边定义的全部方法,这里咱们先重点关注findAllByPage(int pageNum, int pageSize)
方法中的
PageHelper.startPage(pageNum, pageSize);
List<SysUser> lists = sysUserMapper.selectAll();
复制代码
这段代码,第一句使用了咱们的分页插件,就这一句便可,须要注意的是查询语句必须紧跟这一句,且只能使用一次,意思就是若是还有一个分页查询须要再定义一次PageHelper.startPage(pageNum, pageSize)
。
再来讲findAllByPage2(int pageNum, int pageSize)
方法,只比上边的方法多一句话,且返回结果不同
PageInfo<SysUser> pageInfo = new PageInfo<SysUser>(lists);
复制代码
固然,PageHelper
还有其它的多种使用方式,上面的方式要想保证正确性必需要查询代码紧跟分页代码才行,须要程序员去控制,这就增长了出现错误的概率,因此这里再介绍一种更为安全的方式--ISelect
接口方式:
findAllByPage(int pageNum, int pageSize)
改版:
@Override
public List<SysUser> findAllByPage(int pageNum, int pageSize) {
//这种写法须要jdk8 lambda用法
Page<SysUser> page = PageHelper.startPage(pageNum, pageSize).doSelectPage(()-> sysUserMapper.selectAll());
//若是是低版本的jdk,则使用以下写法(两种写法根据本身jdk版本二选一)
Page<SysUser> page = PageHelper.startPage(pageNum, pageSize).doSelectPage(new ISelect() {
@Override
public void doSelect() {
sysUserMapper.selectAll();
}
});
return page;
}
复制代码
看到这里有的朋友或许会发现咱们返回的是一个
Page<SysUser>
对象,而方法定义的是一个List<SysUser>
对象,这里我直接贴出PageHelper
中该方法定义的源码你们就一目了然了:
public class Page<E> extends ArrayList<E> implements Closeable {
//为了避免占过多的篇幅,这里只贴出方法定义的源码,想要了解具体内容请自行查看源码。
//能够看到该方法继承了ArrayList<T>这也是咱们能够直接返回Page<SysUser>的缘由。
}
复制代码
findAllByPage2(int pageNum, int pageSize)
改版:
@Override
public PageInfo<SysUser> findAllByPage2(int pageNum, int pageSize) {
//这种写法须要jdk8 lambda用法
PageInfo<SysUser> pageInfo = PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(()-> sysUserMapper.selectAll());
//若是是低版本的jdk,则使用以下写法(两种写法根据本身jdk版本二选一)
PageInfo<SysUser> pageInfo = PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(new ISelect() {
@Override
public void doSelect() {
sysUserMapper.selectAll();
}
});
return pageInfo;
}
复制代码
这里就给出这两种使用PageHelper
的方法了,想要了解更多请移步【传送门】
接下来建立测试控制器TestController.java
,以下:
package com.web.springboot.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.github.pagehelper.PageInfo;
import com.web.springboot.entity.SysUser;
import com.web.springboot.service.ISysUserService;
/** * @author Promise * @createTime 2019年1月20日 下午8:21:02 * @description */
@RestController
public class TestController {
@Autowired
private ISysUserService sysUserService;
@RequestMapping("/users/{pageNum}/{pageSize}")
public Object getAllUser(@PathVariable int pageNum, @PathVariable int pageSize) {
List<SysUser> lists=sysUserService.findAllByPage(pageNum, pageSize);
return lists;
}
@RequestMapping("/users2/{pageNum}/{pageSize}")
public Object getAllUser2(@PathVariable int pageNum, @PathVariable int pageSize) {
PageInfo<SysUser> pageInfo=sysUserService.findAllByPage2(pageNum, pageSize);
return pageInfo;
}
}
复制代码
好了,代码就编写完成了!
在这以前,咱们须要在数据中准备一些数据,这里先贴上个人数据库数据状况,实际以自身的数据库数据为准:
启动项目,浏览器访问localhost:8080/users/1/2
,表示访问第一页,每页两条数据,结果以下:
对比数据库,数据返回正确,接下来访问localhost:8080/user2/1/2
,结果以下:
发现json
数据没有格式,不利于咱们查看,可使用在线json
格式转化工具格式化内容以下:
{
"pageNum": 1,
"pageSize": 2,
"size": 2,
"startRow": 1,
"endRow": 2,
"total": 6,
"pages": 3,
"list": [{
"id": 1,
"usercode": "Promise",
"username": "eran",
"password": "123456",
"salt": null,
"locked": "0"
}, {
"id": 2,
"usercode": "Promise2",
"username": "eran",
"password": "123456",
"salt": null,
"locked": "0"
}],
"prePage": 0,
"nextPage": 2,
"isFirstPage": true,
"isLastPage": false,
"hasPreviousPage": false,
"hasNextPage": true,
"navigatePages": 8,
"navigatepageNums": [1, 2, 3],
"navigateFirstPage": 1,
"navigateLastPage": 3,
"lastPage": 3,
"firstPage": 1
}
复制代码
能够发现返回了不少有用的内容,这里就不一一介绍了,字段都浅显易懂,实际开发中咱们能够根据须要选择使用哪一种方式。
关于Spring boot
整合MBG
以及pageHelper
的内容就到这里了,下篇博客见。bye~