作者介绍:
我是小明哥,有制造业、能源、金融担保等业务领域经验,Java、C#、PHP、Oracle、DB2、Spring MVC,Spring Boot、Spring Cloud微服务架构、IBM Portal、IBM ESB MB、IBM BI Cognos、IBM BPM 等等,十几年IT农民工的我踩过的坑还不够多吗?,来,我们一起分享。
1.介绍篇
教程结合当前主流的springboot、Mybatis-Plus、lombok、mysql串起来重点、完整的学习Mybatis-Plus,场景比较简单,即通过对“工作招聘信息表(dy_job表)”进行CURD操作(下面详细介绍)。如有不清楚之处,可加微信或者qq问清楚。由于篇幅有限涉及的源代码会贴出80%保证各路新手朋友按照一下步骤一步一步往下做完全没问题,代码没有全部贴完有需要的朋友可以私信。本教程亮点,每一个章节都有总结和注意事项。
教程大纲(如果读到中间有点模糊,请回头看看这个大纲):
1.1. lombok插件介绍
Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法。
为了代码简便,在这个培训教材中加入了这个小插件。比较好用,在实际项目中也推荐使用。要使用这个小插件,需要到官网上去下载,然后单独安装一下,安装方式很简单,下面有介绍。
1.2. Mybatis-Plus插件介绍
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。这是官方给的定义,关于mybatis-plus的更多介绍及特性,可以参考mybatis-plus官网。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA。
1.3. lombok的安装
官方地址:https://projectlombok.org/
github地址:https://github.com/rzwitserloot/lombok。
1)第一步:下载
下载安装很方便,打开https://projectlombok.org/,点击Download进入下载页面,并下载。
它是一个jar包文件,下载后直接点开安装即可。
2)第二步:安装
官网提供基于很多种开发工具的安装方法,我是在eclipse上安装,如下图所示:
以下是官网上提供的安装在eclipse上
安装完之后到开发工具上查看一下插件,如果有,则显示如下图上的信息
3.1. 注意事项 ️
1)lombok目前发现的问题:eclipse所在目录不要有中文,否则加载lombok是不成功的;
2)Mybatis-Plus不需要像lombok安装,只需要在Maven项目中引入依赖即可,非常方便;
2.创建项目
2.1. 创建过程
工程名称“mptest”,具体如下
1)第一步:创建Maven项目,如图:
2)第二步:在"create a simple project。。。"前打勾
3)第三步:输入项目名称相关信息
2.2. 项目结构
3.pom文件中引入相关的依赖
3.1. 拷贝这段贴入刚创建工程的pom.xml里
org.springframework.boot
spring-boot-starter-parent
2.1.3.RELEASE
1.8
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
true
com.baomidou
mybatis-plus-boot-starter
3.1.0
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-cache
org.aspectj
aspectjweaver
1.8.13
3.1. 注意事项 ️
com.baomidou
mybatis-plus-boot-starter
3.1.0
如果在其它框架中引入依赖,只需要这个就可以了。
4.基础代码准备
4.1. 创建数据库表
这里用的是mysql数据库, 表名"dy_job"
表结构:
/*
Navicat Premium Data Transfer
Source Server : localhost-MAMP
Source Server Type : MySQL
Source Server Version : 50725
Source Host : localhost
Source Database : dydata
Target Server Type : MySQL
Target Server Version : 50725
File Encoding : utf-8
Date: 08/09/2019 00:19:41 AM
*/
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `dy_job`
-- ----------------------------
DROP TABLE IF EXISTS `dy_job`;
CREATE TABLE `dy_job` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`position` varchar(200) DEFAULT NULL,
`count` int(11) DEFAULT '0',
`place` varchar(200) DEFAULT NULL,
`deal` varchar(200) DEFAULT NULL,
`addtime` date DEFAULT NULL,
`useful_life` int(11) DEFAULT NULL,
`content` longtext,
`access` int(11) DEFAULT '0',
`no_order` int(11) DEFAULT '0',
`wap_ok` int(1) DEFAULT '0',
`top_ok` int(1) DEFAULT '0',
`email` varchar(255) DEFAULT NULL,
`filename` varchar(255) DEFAULT NULL,
`lang` varchar(50) DEFAULT NULL,
`displaytype` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1021 DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
4.2. 编写相关代码
4.2.1. 项目代码结构
以上4个是核心的。
4.2.2. 写一个Entity实体类
@Data
@EqualsAndHashCode(callSuper=false)
@TableName(value = "dy_job")
public class Job {
//主键,指定自增策略
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
//职位
private String position;
//招聘人数
private Integer count;
//工作地点
private String place;
//待遇
private String deal;
//日期
private LocalDateTime addtime;
//备注信息
private String content;
//email
private String email;
@TableField(exist=false)
private String remark;
}
4.2.3. 写一个Mapper映射接口
package com.mptest.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mptest.entity.Job;
public interface JobMapper extends BaseMapper{
}
4.2.4. 写一个SpringBoot主程序
package com.mptest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @SpringBoot主程序
* @author ming
*
*/
@SpringBootApplication
@MapperScan("com.mptest.mapper")
public class MPApplication {
public static void main(String[] args) {
SpringApplication.run(MPApplication.class, args);
}
}
4.2.5. 创建application.yml配置文件
server:
port: 8018
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3309/dydata
username: root
password: ming821215
mybatis-plus:
#信息输出设置
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#配置mapper xml文件,自定义sql语句
#mapper-locations: classpath*:mpProject/mp/mapper/*.xml
#日志级别设置
#logging:
# level:
# root: WARN
# org:
# springframework:
# security: DEBUG
# web: ERROR
4.2.6. 启动工程,测试是否运行成功
运行成功后,显示如下日志
4.3. 注意事项 ️
1)实体类中,如果类名和数据库表明名称不一样,必须指定 @TableName(value = "dy_job"),否则启动报错找不到数据库表
2)实体类中,至少定义id,否则报错。如:
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
3)必须定义mapper接口,否则启动主程序时,扫描不到映射接口会报错。
4)主程序要加上 @MapperScan("com.mptest.mapper")。
5)application.yml中要配置数据库连接,否则启动会报错
6)想让程序能跑起来,需要注意以上5点
5.准备就绪,开始真正体验Mybatis-Plus
5.1. 三种调用模式介绍
Mybatis-Plus有多种调用模式。例如:
1)ActiveRecord模式调用
普及:Active Record 是一种数据访问设计模式,它可以帮助你实现数据对象Object到关系数据库的映射。
应用Active Record 时,每一个类的实例对象唯一对应一个数据库表的一行(一对一关系),更多介绍看百度百科
https://baike.baidu.com/item/Active%20Record/3106858。
要使用它,需要Entity实体类继承Model即可,如:
@Data
@TableName(value = "dy_job")
public class Job extends Model {
}
调用例子:
/**
* 新增
*/
@Test
public void add() {
//创建job对象
Job job = new Job();
//设置job相关值
job.setPosition("前端工程师");
job.setDeal("9k/月");
job.setPlace("重庆");
job.setCount(5);
job.setContent("技能要求:vue、jq、JavaScript、html、css等");
job.setAddtime(LocalDateTime.now());
//直接调用insert方法
boolean rs = job.insert();
//打印结果
System.out.println("新增结果:"+rs);
}
通用Model中所有的方法:
2)继承通用Mapper接口方式调用
如:public interface JobMapper extends BaseMapper{
}
调用例子:
@Autowired
private JobMapper jobMapper;
/**
* 查询全部
*/
@Test
public void getJobList() {
//查询所有
List list = jobMapper.selectList(null);
//输出结果
list.forEach(System.out::println);
}
通用Mapper中所有方法:
3)继承通用IService接口方式调用
如:public interface JobService extends IService {
}
如果是定义接口继承通用IService,那么需要写实现类,如:
@Service
public class JobServiceImpl extends ServiceImpl implements JobService{
}
调用例子:
@Autowired
private JobService jobService;
/**
* 查询所有
*/
@Test
public void getList()
{
List list = jobService.list();
//打印输出
list.forEach(System.out::println);
}
通用IService中所有的方法:
)经验及建议
一般正式的项目中,建议采用第三种方式,第三种比较全面,可以结合第一种,因为第一种最简单。
5.2. 插入、更新操作
如果包名、类名跟我的命名一样,可以直接贴过去。
package com.mptest.test;
import java.io.Serializable;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.swing.plaf.synth.SynthSeparatorUI;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.UpdateChainWrapper;
import com.mptest.entity.Job;
import com.mptest.mapper.JobMapper;
/**
* spring boot测试类
* @author ming
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class JobInsertOrUpdateTest {
@Autowired
private JobMapper jobMapper;
/**
* 查询全部
*/
@Test
public void getJobList() {
//查询所有
List list = this.jobMapper.selectList(null);
//输出结果
list.forEach(System.out::println);
}
/**
* 新增单条记录
* @throws ParseException
*/
@Test
public void add() throws ParseException {
//创建job对象
Job job = new Job();
//设置job相关值
job.setPosition("Python");
job.setDeal("25k/月");
job.setPlace("深圳");
job.setCount(1);
job.setContent("技能要求:精通Python常用算法,会大数据架构Hadoop");
job.setAddtime(LocalDateTime.now());
//调用插入方法
int rs = this.jobMapper.insert(job);
//打印结果
System.out.println("执行结果:"+rs);
}
/**
* 更新记录
* @throws ParseException
*/
@Test
public void updateByID() throws ParseException {
//创建job对象
Job job = new Job();
job.setId(9);
//设置job相关值
job.setPosition("PHP工程师");
job.setDeal("12k/月");
job.setPlace("北京");
job.setCount(8);
job.setContent("技能要求:熟悉使用PHP");
//调用更新方法
int rs = this.jobMapper.updateById(job);
//打印结果
System.out.println("更新结果:"+rs);
}
/**
* 更新记录
* @throws ParseException
*/
@Test
public void updateByWrapper() throws ParseException {
LambdaUpdateWrapper updateWrapper = new UpdateWrapper().lambda();
updateWrapper.eq(Job::getId, 10);
//创建job对象
Job job = new Job();
//job.setId(9);
//设置job相关值
job.setPosition("C++工程师");
job.setDeal("18k/月");
job.setPlace("广州");
job.setCount(3);
job.setContent("技能要求:精通C++");
//调用更新方法
int rs = this.jobMapper.update(job, updateWrapper);
//打印结果
System.out.println("更新结果:"+rs);
}
/**
* 更新记录
* @throws ParseException
*/
@Test
public void updateByWrapperAndByEntity() throws ParseException {
Job jobWhere = new Job();
jobWhere.setId(10);
//System.out.println(jobWhere.toString());
//updateWrapper
LambdaUpdateWrapper updateWrapper = new UpdateWrapper(jobWhere).lambda();
//updateWrapper.eq(Job::getId, 10);
//创建job对象
Job job = new Job();
//job.setId(9);
//设置job相关值
job.setPosition("C++工程师");
job.setDeal("20k/月");
job.setPlace("广州");
job.setCount(3);
job.setContent("技能要求:精通C++");
//调用更新方法
int rs = this.jobMapper.update(job, updateWrapper);
//打印结果
System.out.println("更新结果:"+rs);
}
/**
* 更新记录
* @throws ParseException
*/
@Test
public void updateByWrapperSg() throws ParseException {
//updateWrapper
LambdaUpdateWrapper updateWrapper = new UpdateWrapper().lambda();
//设置
updateWrapper
.set(Job::getPosition, "Python算法工程师")
.set(Job::getCount, 2)
.eq(Job::getId, 13);
//执行update更新方法
int rs = this.jobMapper.update(null, updateWrapper);
//打印结果
System.out.println("更新结果:"+rs);
}
/**
* 更新记录Chain
* @throws ParseException
*/
@Test
public void updateByWrapperChain() throws ParseException {
//updateWrapper
LambdaUpdateChainWrapper updateWrapper = new LambdaUpdateChainWrapper(jobMapper);
//设置
boolean rs = updateWrapper
.set(Job::getPosition, "Python工程师")
.set(Job::getCount, 5)
.eq(Job::getId, 13)
.update();
System.out.println("更新结果:"+rs);
}
/**
* 通过id删除数据
*/
@Test
public void deleteById() {
Integer id = 3 ;
//调用删除方法deleteById
int rs = this.jobMapper.deleteById(id);
//打印结果
System.out.println("更新结果:"+rs);
}
/**
* 通过多个id删除数据
*/
@Test
public void deleteByIds() {
//调用删除方法deleteById
Collection idList = new ArrayList() ;
idList.add(2);
idList.add(4);
//第一种传递参数
//int rs = this.jobMapper.deleteBatchIds(idList);
//第二种传递参数
int rs = this.jobMapper.deleteBatchIds(Arrays.asList("2","4","12"));
//打印结果
System.out.println("更新结果:"+rs);
}
/**
* 通过Wrapper删除数据
*/
@Test
public void deleteByWrapper() {
//外部传来的逗号分割id
String params = "2,4,6,7";
List paramsList = Arrays.asList(params.split(","));
//LambdaQueryWrapper对象
LambdaQueryWrapper wrapper = new QueryWrapper().lambda();
//条件
wrapper
.like(Job::getPosition,"工程师")
.in(Job::getId, paramsList);
//调用删除方法
int rs = this.jobMapper.delete(wrapper);
//打印结果
System.out.println("更新结果:"+rs);
}
}
5.4. 查询语句、查询条件
package com.mptest.test;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.plaf.synth.SynthSeparatorUI;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.UpdateChainWrapper;
import com.mptest.entity.Job;
import com.mptest.mapper.JobMapper;
/**
* spring boot测试类
* @author ming
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class JobSelectTest {
@Autowired
private JobMapper jobMapper;
/**
* 查询全部
*/
@Test
public void getJobList() {
//查询所有
List list = jobMapper.selectList(null);
//输出结果
list.forEach(System.out::println);
}
/**
* 以map作为条件查询
*/
@Test
public void getByMap() {
//定义map
Map columnMap = new HashMap();
//设置id值
columnMap.put("id", 1);
//调用查询方法
List list = this.jobMapper.selectByMap(columnMap);
//打印输出
list.forEach(System.out::println);
}
/**
* 以Wrapper作为条件查询
*/
@Test
public void getByWrapper() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper
.like("position", "工程")
.lt("id", 10);
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 以Wrapper作为复杂条件查询
*/
@Test
public void getByWrapper2() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper
.like("position", "工")
.between("count", 1, 2)
.isNull("email");
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 以Wrapper作为复杂条件查询
*/
@Test
public void getByWrapper3() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper
.likeRight("position", "软")
.or().ge("count", 3)
.orderByDesc("addtime")
.orderByAsc("id");
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 带子查询
*/
@Test
public void getByWrapper4() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper
.apply("date_format(addtime,'%Y-%m-%d')={0}", "2019-08-02")
.inSql("id", "select id from dy_job where count>1");
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* and lambda表达式查询
*/
@Test
public void getByWrapper5() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper
.like("position", "工程师")
.and(
sql->sql.le("count", 10).or().isNull("email")
)
.ge("id", 2);
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* or lambda表达式查询
*/
@Test
public void getByWrapper6() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper
.like("position", "工程师")
.or(
sql->sql.le("count", 10).isNull("email")
)
.ge("id", 2);
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 前面是带() lambda表达式查询
*/
@Test
public void getByWrapper7() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper
.nested(sql->sql.like("position", "java").or().ge("count", 3))
.apply("date_format(addtime,'%Y-%m-%d')={0}", "2019-08-02")
.last("limit 2");
//.in("id", Arrays.asList(1,2,3,5,8));
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 查询指定字段
*/
@Test
public void getByWrapper8() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//开始设置查询条件
queryWrapper.select("id","position","addtime")
.nested(sql->sql.like("position", "java").or().ge("count", 3))
.apply("date_format(addtime,'%Y-%m-%d')={0}", "2019-08-02")
.in("id", Arrays.asList(1,2,3,5,6,7,8,9,10))
.last("limit 2");
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 判断参数是否为空
*/
@Test
public void getByWrapper9() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
String positionKey = "C#";
String countKey = null;
//开始设置查询条件
queryWrapper
.like(StringUtils.isNotEmpty(positionKey),"position", positionKey)
.ge(StringUtils.isNotEmpty(countKey),"count", countKey)
.orderByDesc("addtime")
.orderByAsc("id")
.select("id","position","addtime");
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 实体Entity作为参数查询
*/
@Test
public void getByWrapperEntity() {
Job whereJob = new Job();
whereJob.setId(11);
whereJob.setPosition("C#架构师");
//查询条件
QueryWrapper queryWrapper = Wrappers.query(whereJob);
//queryWrapper.eq("", "C#");
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* map押入条件
*
*/
@Test
public void getByWrapperAllEq() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
//创建map对象,并装入条件列
Map whereMap = new HashMap();
whereMap.put("position", "C#架构师");
queryWrapper.allEq(whereMap);
//调用查询
List list = this.jobMapper.selectList(queryWrapper);
//打印输出
list.forEach(System.out::println);
}
/**
* 返回map类型
*
*/
@Test
public void getByWrapperMaps() {
//查询条件
QueryWrapper queryWrapper = Wrappers.query();
queryWrapper
.select("addtime as 招聘时间","count(*) as 职位数量")
.gt("id", 1)
.like("position", "师")
.groupBy("招聘时间")
.having("职位数量>{0} and 职位数量<{1}", 1,10);
//调用查询
List