MyBatis Plus 是国内人员开发的 MyBatis 增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
MyBatis Plus 的核心功能有:支持通用的 CRUD、代码生成器与条件构造器。
BaseMapper
接口即可获得通用的增删改查功能,无需编写任何接口方法与配置文件EntityWrapper
(实体包装类),可以用于拼接 SQL 语句,并且支持排序、分组查询等复杂的 SQL/***
* 通用删除操作 deleteBatchIds 通过多个ID进行删除
*/
@Test
public void testDeleteBatchIds() {
List idList = new ArrayList();
idList.add(5);
idList.add(6);
int result = employeeMapper.deleteBatchIds(idList);
System.out.println("*******************" + result);
}
public void selectIn() {
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.setSqlSelect(WinAgent.COL_ID);
wrapper.in(WinAgent.COL_AG_NUM, new String[]{"11","22","33","44"});
userMapper.selectList(wrapper);
}
/**
* 根据条件构造器删除
*/
public void testDeleteByWrapper(){
QueryWrapper wrapper = new QueryWrapper<>();
// 参数1-字段名,参数2-匹配的值
wrapper.eq("user_name", "lisi");
// count代表删除成功的记录数
int count = userMapper.delete(wrapper);
}
/***
* 通用更新操作
*/
@Test
public void testUpdateOrInsert() {
Employee entity = new Employee();
entity.setId(1);
entity.setName("更新测试成功");
int result = employeeMapper.updateById(entity);
//int result = employeeMapper.insert(entity);
}
public void testUpdate() {
Employee entity = new Employee();
entity.setName("更新测试成功");
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", "1");
int result = employeeMapper.update(entity, queryWrapper);
}
/**
* 查询所有数据
* UserMapper 中的 selectList() 方法的参数
* 为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件(条件构造器)
*/
@Test
public void selectList() {
List list = userMapper.selectList(null);
list.forEach(System.out::println);
}
/**
* 根据 entity 条件,查询一条记录
* 其实 QueryWrapper 条件构造器(相当于给SQL的条件语句)
* selectOne() 方法查询必须有且只能查询一条记录,多一条会报错。
*/
@Test
public void selectOne() {
QueryWrapper queryWrapper = new QueryWrapper<>();
//查询名字为 Tom 的一条记录
queryWrapper.eq("name", "Tom");
User user = userMapper.selectOne(queryWrapper);
System.out.println(user);
}
/**
* 根据主键ID查询数据
* 查询主键id=2 的一条数据,只能查询一个主键的数据不能多个
*/
@Test
public void selectById() {
User user = userMapper.selectById(2);
System.out.println(user);
}
/**
* 根据 List 的 ID 集合 查询对应的用户list
*/
@Test
public void selectBatchIds() {
List list = userMapper.selectBatchIds(Arrays.asList(5, 3, 1));
list.forEach(System.out::println);
}
/**
* 查询(根据 columnMap 条件),查询年龄为20岁的所有记录
*
* 注意:建议尽量减少使用map这种方式。
* 因为可能字段名可能存在修改的情况,
* 如果,项目开发一段时间后,再修改,影响太大
*/
@Test
public void selectByMap() {
Map map = new HashMap<>();
map.put("age", "20");
List list = userMapper.selectByMap(map);
list.forEach(System.out::println);
}
/**
* 查询大于20岁的学生,名称中包含“J”的人,带条件判断的,可以采用这种方式
* SELECT * FROM user WHERE (name LIKE ? AND age > ?)
* gt()方法 相当于:大于 > 但没有等于=
*/
@Test
public void selectListWrapper() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "J");//格式:(字段,值)
queryWrapper.gt("age", "19"); //查询不小于20岁
List list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
/**
* 根据 Wrapper 条件,查询全部记录。
* 查询名字含有 a 的,且年龄大于等于20。
* ge()方法 相当于: 大于等于 >= 。
* like()方法 相当于: NOT LIKE '%值%' 。
*/
@Test
public void selectMaps() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "a");
queryWrapper.ge("age", "20");
List
queryWrapper是mybatis plus中实现查询的对象封装操作类.。注意这是因为我的mybatisplus的版本是3.2版本,只有3.x的版本才有QueryWrapper,而如果是2.x版本,是没有QueryWrapper的,如果找不到QueryWrapper,可以在配置里将mybatisplus的版本改为3.x
2.2.0
或者使用EntityWrapper,两者的功能其实差不多。
数据表结构
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
创建一个 SpringBoot 项目。
方式一:去官网 https://start.spring.io/ 初始化一个,然后导入 IDE 工具即可。
方式二:直接使用 IDE 工具创建一个。 Spring Initializer。
添加 MyBatis-Plus 依赖(mybatis-plus-boot-starter)
com.baomidou
mybatis-plus-boot-starter
3.3.1
使用 mysql,需要引入 mysql 相关依赖。为了简化代码,引入 lombok 依赖
mysql
mysql-connector-java
org.projectlombok
lombok
1.18.10
org.mapstruct
mapstruct
org.mapstruct
mapstruct-jdk8
org.springframework.boot
spring-boot-starter-test
test
完整pom.xml
文件
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.6.RELEASE
com.lyh.test
test-mybatis-plus
0.0.1-SNAPSHOT
test-mybatis-plus
测试 -- 测试 MyBatis-Plus 功能
1.8
com.baomidou
mybatis-plus-boot-starter
mysql
mysql-connector-java
org.projectlombok
lombok
1.18.10
org.springframework.boot
spring-boot-starter
3.3.1
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.springframework.boot
spring-boot-maven-plugin
在 resources/application.yml 文件中配置 mysql 数据源信息。
server:
port: 2525
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/testMyBatisPlus?useUnicode=true&characterEncoding=utf8
mybatis-plus:
mapper-locations: classpath:mappers/*.xml
实体类
package entity;
import lombok.Data;
@Data
public class User {
private Long id;
private String name;
private int age;
private String email;
}
mapper 接口,这是 mybatis-plus 封装好的类。
package mapper;
import entity.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import java.util.List;
public interface UserMapper extends BaseMapper {
//@Select("SELECT * FROM user where name = #{name}")
//List selectByName(@Param("name") String name);
//传入对象参数xml方式
//List selectAllUsers(@Param("user") User user, @Param("bm") String bm);
}
实体类、Mapper 类都写好了,就可以使用了。接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上@Select@Update 等注解里面包含 Sql 语句来绑定,另外一种就是通过xml 里面写 SQL 来绑定,在这种情况下,要指定 xml 映射文件里面的namespace 必须为接口的全路径名。当 Sql 语句比较简单时候,用注解绑定;当 SQL 语句比较复杂时候,用 xml 绑定,一般用 xml 绑定的比较多
添加UserMapper.xml
文件(可省略)
简单来说 #{} 会在将参数加上引号,而${}并不会在给参数加上引号。mybatis对参数没有进行任何的处理。通常${}用于GROUP BY,ORDER BY,IN等的后面
但是,实际应用中,并不提倡使用 ${},因为使用 #{} 写法,除了可以防止sql注入以外,还能在参数里含有单引号的时候自动转义
ServiceImpl层
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
public Integer getUserNum() {
return userMapper.findUserCount();
}
// 增
@Override
public int insertUser(User user) {
return baseMapper.insert(user);
}
// 改
@Override
public int updateUser(User user) {
return baseMapper.updateById(user);
}
// 删
@Override
public int deleteUser(User user) {
return baseMapper.deleteById(user.getUserId());
}
// 查
@Override
public User findUserByName(String userName) {
return baseMapper.getUserByName(userName);
}
// 分页查
@Override
public IPage getUserPage(Page page, User user) {
return baseMapper.getUsersPage( page, user );
}
}
Service层
public interface UserService extends IService {
Integer getUserNum();
int insertUser( User user );
int updateUser( User user );
int deleteUser( User user );
User findUserByName( String userName );
IPage getUserPage( Page page, User user );
Step1:先得在启动类里扫描 Mapper 类,即添加 @MapperScan 注解
package com.lyh.test.testmybatisplus;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("mapper")
//@MapperScan({"com.kfit.*.mapper","org.kfit.*.mapper"})
@SpringBootApplication
public class TestMybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(TestMybatisPlusApplication.class, args);
}
}
多module项目扫描失败解决: Consider defining a bean of type 'xxx' in your configuration
@SpringBootApplication(scanBasePackages = {"com.xx.xx.xx.A", "com.xx.xx.common"})
Step2:写一个测试类测试一下。
package com.lyh.test.testmybatisplus;
import entity.User;
import mapper.UserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class TestMybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List userList = userMapper.selectList(null);
for(User user:userList) {
System.out.println(user);
}
}
@Test
public void testSelectBySql() {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper();
wrapper.like("name" , "k").lt("age", 40).last("limit 4");
List userList = userMapper.selectBySql(wrapper);
userList.forEach(System.out::println);
}
}
上面几个例子中,并没有在 UserMapper 接口中定义任何方法,也没有在配置文件中编写 SQL 语句,而是通过继承 BaseMapper 接口获得通用的的增删改查方法,复杂的 SQL 也可以使用条件构造器拼接。通过这两种方式已经能够满足很多的开发需求了,不过复杂的业务需求还是要编写 SQL 语句的,流程和 MyBatis 一样。
想要查看执行的 sql 语句,可以在 application.yml 文件中添加配置信息,如下。
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
若遇到 @Autowired 标记的变量出现 红色下划线,但是不影响 正常运行。可以进入 Settings,找到 Inspection,并选择其中的 Spring Core -> Code -> Autowiring for Bean Class,将 Error 改为 Warning,即可。
package com.example.demo;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
/**
* MybatisPlus代码生成器
*/
public class MybatisPlusGeneratorRunner {
public static final String MYSQL_DRIVER = "com.mysql.cj.jdbc.Driver";
//模块名 如果有模块名,则需在模块名前加. 例:log
public static final String MODULE_NAME = "";
public static final String AUTHOR = "danny";
public static final String MYSQL_URL = "jdbc:mysql://locallhost:3306/test?serverTimezone=UTC";
public static final String USERNAME = "root";
public static final String PASSWORD = "0rb!t";
public static final String[] DB_TABLE_NAMES = {"user", "role"};
public static final String PACKAGE_NAME = "cn.kerninventory.mybatis";
public static void main(String[] args) {
AutoGenerator generator = new AutoGenerator();
//配置数据库连接参数
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDriverName(MYSQL_DRIVER);
dataSourceConfig.setUrl(MYSQL_URL);
dataSourceConfig.setUsername(USERNAME);
dataSourceConfig.setPassword(PASSWORD);
generator.setDataSource(dataSourceConfig);
//配置文件生成路径参数
PackageConfig packageConfig = new PackageConfig();
packageConfig.setModuleName(MODULE_NAME);
packageConfig.setParent(PACKAGE_NAME);
packageConfig.setEntity("entity");
packageConfig.setXml("xml");
packageConfig.setMapper("mapper");
//packageConfig.setServiceImpl("serviceimpl");
packageConfig.setService("service");
packageConfig.setController("controller");
generator.setPackageInfo(packageConfig);
//策略配置
StrategyConfig strategyConfig = new StrategyConfig();
//表名转驼峰
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
//字段驼峰命名
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
//set方法builder模式
strategyConfig.setChainModel(true);
//使用lombok注解
strategyConfig.setEntityLombokModel(true);
//不生成serial version uuid
//strategyConfig.setEntitySerialVersionUID(false);
//要生成的表名
strategyConfig.setInclude(DB_TABLE_NAMES);
//rest风格
strategyConfig.setRestControllerStyle(true);
//是否生成字段常量
strategyConfig.setEntityColumnConstant(true);
//是否生成实体时,生成字段注解
strategyConfig.setEntityTableFieldAnnotationEnable(true);
generator.setStrategy(strategyConfig);
//全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setServiceName("%sService");
globalConfig.setXmlName("mapper");
globalConfig.setBaseResultMap(true); //XML中的ResultMap标签
globalConfig.setBaseColumnList(true); //XML标签
globalConfig.setOpen(false); //不弹出生成目录
//输出目录
globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
globalConfig.setAuthor(AUTHOR);
generator.setGlobalConfig(globalConfig);
generator.execute();
}
}
StopWatch 是位于 org.springframework.util 包下的一个工具类,通过它可方便的对程序部分代码进行计时(ms级别),适用于同步单线程代码块。简单总结一句,Spring提供的计时器StopWatch对于秒、毫秒为单位方便计时的程序,尤其是单线程、顺序执行程序的时间特性的统计输出支持比较好。也就是说假如我们手里面有几个在顺序上前后执行的几个任务,而且我们比较关心几个任务分别执行的时间占用状况,希望能够形成一个不太复杂的日志输出,StopWatch提供了这样的功能。而且Spring的StopWatch基本上也就是仅仅为了这样的功能而实现。
想要使用它,首先你需要在你的 Maven 中引入 Spring 核心包,当然 Spring MVC 和 Spring Boot 都已经自动引入了该包:
org.springframework
spring-core
${spring.version}
对一切事物的认知,都是从使用开始,那就先来看看它的用法,会如下所示:
public static void main(String[] args) throws InterruptedException {
StopWatch stopWatch = new StopWatch();
// 任务一模拟休眠3秒钟
stopWatch.start("TaskOneName");
Thread.sleep(1000 * 3);
System.out.println("当前任务名称:" + stopWatch.currentTaskName());
stopWatch.stop();
// 任务一模拟休眠10秒钟
stopWatch.start("TaskTwoName");
Thread.sleep(1000 * 10);
System.out.println("当前任务名称:" + stopWatch.currentTaskName());
stopWatch.stop();
// 任务一模拟休眠10秒钟
stopWatch.start("TaskThreeName");
Thread.sleep(1000 * 10);
System.out.println("当前任务名称:" + stopWatch.currentTaskName());
stopWatch.stop();
// 打印出耗时
System.out.println(stopWatch.prettyPrint());
System.out.println(stopWatch.shortSummary());
// stop后它的值为null
System.out.println(stopWatch.currentTaskName());
// 最后一个任务的相关信息
System.out.println(stopWatch.getLastTaskName());
System.out.println(stopWatch.getLastTaskInfo());
// 任务总的耗时 如果你想获取到每个任务详情(包括它的任务名、耗时等等)可使用
System.out.println("所有任务总耗时:" + sw.getTotalTimeMillis());
System.out.println("任务总数:" + sw.getTaskCount());
System.out.println("所有任务详情:" + sw.getTaskInfo());
}
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅。Hutool是对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类。
在项目的pom.xml的dependencies中加入以下内容:
cn.hutool
hutool-all
5.5.2
eureka.client.enabled=false