1. 程式人生 > >springboot2.0.5整合mybatis(PageHelper分頁外掛、generator外掛使用)

springboot2.0.5整合mybatis(PageHelper分頁外掛、generator外掛使用)

用IDEA搭建springboot2.0.5專案

選擇Spring initializr就可以輕鬆搭建一個springboot專案,第一次搭建很費時

在Group寫上公司域名,Artifact寫上專案名,打包用Jar

選Web勾選

SQL項,勾選MySQL、JDBC、MyBatis,這裡選擇了過後,IDEA會方便地幫我們匯入相關依賴

資料庫建立

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL,
  `weight` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

INSERT INTO `user` VALUES ('1', '23', 'zhangsan', '123');
INSERT INTO `user` VALUES ('2', '25', 'lisi', '125');
INSERT INTO `user` VALUES ('3', '30', 'wangwu', '90');
INSERT INTO `user` VALUES ('4', '12', 'zhengxie', '120');
INSERT INTO `user` VALUES ('5', '50', 'zhaocao', '100');
INSERT INTO `user` VALUES ('6', '60', 'caohuai', '150');

搭建簡陋的一張表新增、查詢系統

專案名稱會與上面不一致,因為做demo時沒有截圖。

搭建完成的結構如下圖:

UserController程式碼:

package com.zab.mybatis.web;

import com.zab.mybatis.beans.User;
import com.zab.mybatis.common.GeneralResponse;
import com.zab.mybatis.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*@author Jackson Zhang
*@date 22:58
*/
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/findAll")
    public GeneralResponse findAll(){
        return userService.findAll();
    }

    @PostMapping("/findByPage")
    public GeneralResponse findByPaging(Integer pageNum, Integer pageSize){
        return userService.findByPaging(pageNum,pageSize);
    }

    @PostMapping("/selectByPrimaryKey")
    public GeneralResponse selectByPrimaryKey(Integer id){
        return userService.selectByPrimaryKey(id);
    }

    @PostMapping("/insert")
    public GeneralResponse insert(@RequestBody User user){
        return userService.insert(user);
    }
}

UserServiceImpl程式碼:

package com.zab.mybatis.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zab.mybatis.beans.User;
import com.zab.mybatis.common.GeneralResponse;
import com.zab.mybatis.mapper.UserMapper;
import com.zab.mybatis.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
/**
*@author Jackson Zhang
*@date 22:59 
*/
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;//會報紅線

    @Override
    public GeneralResponse findAll() {
        List<User> users = userMapper.findAll();
        return new GeneralResponse("0","查詢成功","查詢成功",users);
    }

    @Override
    public GeneralResponse selectByPrimaryKey(Integer id) {
        User user = userMapper.selectByPrimaryKey(id);
        return new GeneralResponse("0","查詢成功","查詢成功",user);
    }

    @Override
    public GeneralResponse insert(User user) {
        int result = userMapper.insert(user);
        if(result==1){
            return new GeneralResponse("0","新增成功","新增成功",result);
        }
        return new GeneralResponse("1","新增失敗","新增失敗",result);
    }

    @Override
    public GeneralResponse findByPaging(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        Page<User> userList = userMapper.findByPaging();
        return new GeneralResponse("0","查詢成功","查詢成功",userList);
    }
}

UserMapper程式碼:這裡並不是自己寫的,除了findByPaging方法都是用外掛生成的!

package com.zab.mybatis.mapper;

import com.github.pagehelper.Page;
import com.zab.mybatis.beans.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
/**
*@author Jackson Zhang
*@date 23:01 
*/
@Mapper
public interface UserMapper {

    List<User> findAll();

    int deleteByPrimaryKey(Integer id);

    int insert(User record);

    int insertSelective(User record);

    User selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);

    Page<User> findByPaging();
}

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.zab.mybatis.mapper.UserMapper">
    <resultMap id="BaseResultMap" type="com.zab.mybatis.beans.User">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="age" property="age" jdbcType="VARCHAR"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <result column="weight" property="weight" jdbcType="VARCHAR"/>
    </resultMap>
    <sql id="Base_Column_List">
    id, age, name, weight
  </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List"/>
        from user
        where id = #{id,jdbcType=INTEGER}
    </select>

    <select id="findAll" resultMap="BaseResultMap" parameterType="java.util.List">
        select
        <include refid="Base_Column_List"/>
        from USER
    </select>

    <select id="findByPaging" resultMap="BaseResultMap" parameterType="com.github.pagehelper.Page">
        select
        <include refid="Base_Column_List"/>
        from USER
    </select>

    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from user
    where id = #{id,jdbcType=INTEGER}
  </delete>
    <insert id="insert" parameterType="com.zab.mybatis.beans.User">
    insert into user (id, age, name, 
      weight)
    values (#{id,jdbcType=INTEGER}, #{age,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, 
      #{weight,jdbcType=VARCHAR})
  </insert>
    <insert id="insertSelective" parameterType="com.zab.mybatis.beans.User">
        insert into user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">
                id,
            </if>
            <if test="age != null">
                age,
            </if>
            <if test="name != null">
                name,
            </if>
            <if test="weight != null">
                weight,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null">
                #{id,jdbcType=INTEGER},
            </if>
            <if test="age != null">
                #{age,jdbcType=VARCHAR},
            </if>
            <if test="name != null">
                #{name,jdbcType=VARCHAR},
            </if>
            <if test="weight != null">
                #{weight,jdbcType=VARCHAR},
            </if>
        </trim>
    </insert>
    <update id="updateByPrimaryKeySelective" parameterType="com.zab.mybatis.beans.User">
        update user
        <set>
            <if test="age != null">
                age = #{age,jdbcType=VARCHAR},
            </if>
            <if test="name != null">
                name = #{name,jdbcType=VARCHAR},
            </if>
            <if test="weight != null">
                weight = #{weight,jdbcType=VARCHAR},
            </if>
        </set>
        where id = #{id,jdbcType=INTEGER}
    </update>
    <update id="updateByPrimaryKey" parameterType="com.zab.mybatis.beans.User">
    update user
    set age = #{age,jdbcType=VARCHAR},
      name = #{name,jdbcType=VARCHAR},
      weight = #{weight,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

實體類User:

package com.zab.mybatis.beans;
/**
*@author Jackson Zhang
*@date 23:02 
*/
public class User {

    private Integer id;

    private String age;

    private String name;

    private String weight;
    //getter、setter略
}

通用響應類GeneralResponse:

package com.zab.mybatis.common;

/**
 * @author zhang anbing
 * @date 2018/8/21
 */
public class GeneralResponse<T> {
    /**
     * 0表示正常,1表示異常
     */
    private String code;
    /**
     * 面向使用者的訊息
     */
    private String message;
    /**
     * 面向開發者的詳細資訊
     */
    private String detail;
    /**
     * 返回給前端的資料
     */
    private T datas;

    public GeneralResponse(String code, String message, String detail, T datas) {
        this.code = code;
        this.message = message;
        this.detail = detail;
        this.datas = datas;
    }

    public static GeneralResponse success(String message, String detail) {
        return new GeneralResponse("0", message, detail, null);
    }

    public static GeneralResponse fail(String message, String detail) {
        return new GeneralResponse("1", message, detail, null);
    }
//getter、setter略
}

接下來就是配置檔案,實際開發中配置檔案絕不止一兩個,springboot專案通常來說會有一個切換配置的配置檔案application.yml:

spring:
  profiles:
    active: dev

然後就是dev、test、prod等,這裡只配開發application-dev.yml:

server:
  port: 8080
spring:
  datasource:
    name: mybatis-test
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://127.0.0.1:3306/test
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapping/*.xml         #配置對映檔案位置,classpath指resources
  type-aliases-package: com.zab.mybatis.beans      #實體類所在位置
  configuration:                                    #列印sql到控制檯
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

pagehelper:
    helperDialect: mysql                           #分頁外掛方言選擇
    reasonable: true                               #合理化引數,設為true時pageNum<=0 時會查第一頁, pageNum>pages(超過總數時),會查詢最後一頁
    supportMethodsArguments: true                  
                                                   
    

整個demo專案的pom.xml檔案如下:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zab</groupId>
    <artifactId>mybatis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>mybatis</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>


        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-joda</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-parameter-names</artifactId>
        </dependency>
        <!-- 分頁外掛 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!-- alibaba的druid資料庫連線池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.9</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <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.2</version>
                <configuration>
                    <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                    <verbose>true</verbose>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

自動生成mapper(包括*mapper.xml和*mapper.java)的配置檔案:

<?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>
    <!-- 資料庫驅動:選擇你的本地硬碟上面的資料庫驅動包-->
    <classPathEntry  location="D:\mvn_repository\mysql\mysql-connector-java\5.1.47\mysql-connector-java-5.1.47.jar"/>
    <context id="DB2Tables"  targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自動生成的註釋 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--資料庫連結URL,使用者名稱、密碼 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1/test" userId="root" password="root">
        </jdbcConnection>
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- 生成模型的包名和位置-->
        <javaModelGenerator targetPackage="com.zab.mybatis.beans" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成對映檔案的包名和位置-->
        <sqlMapGenerator targetPackage="mapping" targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成DAO的包名和位置-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.zab.mybatis.mapper" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 要生成的表 tableName是資料庫中的表名或檢視名 domainObjectName是實體類名-->
        <table tableName="user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>
</generatorConfiguration>

generator使用方法

1.配置Maven Configurations如下

2.選擇配置好的generator執行即可,就會發現配置好的資料夾中(java-->mapper和resource-->mapping)生成好了響應的mapper.java和mapper.xml

generator除了這種依靠IDEA的,還有一種GUI版,執行過後再彈出的視窗中定製Mapper生成地址,給出下載連結:

MySQL分頁簡介

MySQL分頁是通過limit完成的

#LIMIT [offset], rows
#offset是相對於首行的偏移量(首行是0),rows是返回條數。

# 每頁10條記錄,取第一頁,返回的是前10條記錄
select * from tableA limit 0,10;
# 每頁10條記錄,取第二頁,返回的是第11條記錄,到第20條記錄,
select * from tableA limit 10,10;

其實說得簡單點,limit會跟倆數字a和b,a表示排除幾筆,b表示取幾筆。

比如:

limit 1000,10 - 過濾出1010條資料,然後排除前1000條,取10條。

limit 100000,10 - 會過濾100010條資料,然後排除前100000條,取10條。當偏移量大(排除數量過多)的時候,效能會有所下降。

例如資料庫有一千萬條資料,你要取500萬後面十條資料,採用如下方式是不合理的:

select * from table limit 5000000,10;

可以考慮這樣寫:

select * from table where id>5000000 limit 0,10;

PageHelper使用方法

外掛作者是國人大神劉增輝,聽朋友說以前也有個PageHelper的外掛用的是記憶體分頁,就是一次性全查,再分頁,不清楚是不是說的這個,但是liuzh這個外掛確實是物理分頁。

使用很簡單,介紹兩種方式

第一種,也就是上面程式碼展示的:

PageHelper.startPage(pageNum,pageSize);
Page<User> userList = userMapper.findByPaging();

對應的*mapper.xml:

 <select id="findByPaging" resultMap="BaseResultMap" parameterType="com.github.pagehelper.Page">
        select
        <include refid="Base_Column_List"/>
        from USER
  </select>

起初,我光看這幾行程式碼,感覺這玩意是不是先全查,然後在記憶體中取了我們想要的那一頁,畢竟sql語句是全查呀。

然後追了下原始碼,一調就是一下午啊,流程很複雜,也不能說看懂,大致有那麼幾個主要的類參與其中:MapperProxy、MapperMethod、DefaultSqlSession、Plugin、PageIntercepter(這就是PageHelper關鍵)、SqlSessionTemplate

注意到@Intercepts這個註解可以攔截Excutor類的query方法

攔截query方法過後,設定分頁引數,這種分頁與上述UserServiceImpl中

PageHelper.startPage(pageNum,pageSize);
Page<User> userList = userMapper.findByPaging();

的方式不一樣,只是多了一個VO,少了PageHelper.startPage(pageNum,pageSize),原理都是要把分頁引數通過攔截mybatis的執行流程加入到最終的sql中

 Page<User> userList = userMapper.findByPaging(pageVo);

最後執行分頁查詢

前面說到PageHelper的第一種使用方式和簡單過了下PageHelper怎麼實現分頁的,下面是PageHelper的第二種使用方式:

建一個PageVo類

package com.zab.mybatis.vo;

public class PageVo {
    private Integer pageNum;
    private Integer pageSize;

    //getter、setter略
}

把UserServiceImpl中的:

PageHelper.startPage(pageNum,pageSize);
Page<User> userList = userMapper.findByPaging();

改為:

 Page<User> userList = userMapper.findByPaging(pageVo);

響應的類中形參和實參進行修改就可以了,UserMapper.xml檔案不用改動。

用postman測試

總共6筆資料,第二頁取三筆:

提醒下,Controller類中方法的形參如果沒有加@RequestBody,那麼postman用x-www-form-urlencoded傳參,加上@RequestBody則用raw中的json傳參。

最後給出PageHelper的官方地址,詳細使用請參考: