用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生成地址,给出下载链接:
https://pan.baidu.com/s/13s9zO93eVmcVNBCGV4-T3A
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的官方地址,详细使用请参考:
https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md