Springboot系列之:创建Springboot项目,Springboot整合MyBatis-plus
- 一、快速创建Spring boot项目
- 二、项目完整目录
- 三、pom.xml
- 四、application.yaml
- 五、实体类
- 六、mapper
- 七、IService接口
- 八、Service实现类
- 九、配置类
- 十、枚举
- 十一、增删改查测试类
- 十二、服务测试类
- 十三、分页测试类
- 十四、枚举测试类
- 十五、乐观锁测试类
一、快速创建Spring boot项目
二、项目完整目录
三、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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lovejava.boot</groupId>
<artifactId>learnjava</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>learnjava</name>
<properties>
<java.version>8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
四、application.yaml
spring:
application:
name: learnjava
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.129.88.141:3306/data_entry_test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
username: datasight
password: datasight123456!A
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# log-impl: org.apache.ibatis.logging.log4j.Log4jImpl
# global-config:
# db-config:
# table-prefix: t_
# id-type: AUTO
type-enums-package: com.lovejava.boot.enums
五、实体类
import com.baomidou.mybatisplus.annotation.*;
import com.lovejava.boot.enums.SexEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@TableName("user")
public class User {
@TableId(value = "id",type=IdType.AUTO)
private Long id;
// @TableField("sname")
private String name;
private Integer age;
private SexEnum sex;
private String email;
@TableField("isDeleted")
@TableLogic
private Integer isDeleted;
@Version
private Integer version;
}
六、mapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lovejava.boot.pojo.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
}
七、IService接口
IService 是 MyBatis-Plus 提供的一个通用 Service 层接口,它封装了常见的 CRUD 操作,包括插入、删除、查询和分页等。通过继承 IService 接口,可以快速实现对数据库的基本操作,同时保持代码的简洁性和可维护性。
IService 接口中的方法命名遵循了一定的规范,如 get 用于查询单行,remove 用于删除,list 用于查询集合,page 用于分页查询,这样可以避免与 Mapper 层的方法混淆。
import com.baomidou.mybatisplus.extension.service.IService;
import com.lovejava.boot.pojo.User;
public interface UserService extends IService<User> {
}
八、Service实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lovejava.boot.mapper.UserMapper;
import com.lovejava.boot.pojo.User;
import com.lovejava.boot.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
九、配置类
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.lovejava.boot.mapper")
public class MybatisPlusConfig {
/**
* 添加分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 如果配置多个插件, 切记分页最后添加
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
}
十、枚举
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum SexEnum {
MALE(1,"男"),
FEMALE(2,"女");
@EnumValue //将注解所标识的属性的值存储到数据库中
private Integer sex;
private String sexName;
}
十一、增删改查测试类
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.lovejava.boot.mapper.UserMapper;
import com.lovejava.boot.pojo.User;
import net.minidev.json.JSONUtil;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class MyBatisPlusTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList(){
List<User> users = userMapper.selectList(null);
System.out.println(users);
users.forEach(System.out::println);
}
@Test
public void testInsert(){
User user = new User();
user.setName("刘备");
user.setAge(23);
user.setEmail("fy@qq.com");
int result = userMapper.insert(user);
System.out.println("result:"+result);
System.out.println("id:"+user.getId());
}
@Test
public void testDelete(){
int result = userMapper.deleteById(1860576442045870081L);
System.out.println(result);
}
//DELETE FROM user WHERE name = ? AND age = ?
@Test
public void testDeleteByMap(){
Map<String,Object> map = new HashMap<>();
map.put("name","刘备");
map.put("age",23);
int result = userMapper.deleteByMap(map);
System.out.println("result:"+result);
}
//通过多个id实现批量删除
@Test
public void testDeleteBatchIds(){
List<Integer> list = Arrays.asList(1, 2, 3);
int result = userMapper.deleteBatchIds(list);
System.out.println("result:"+result);
}
@Test
public void testUpdate(){
User user = new User();
user.setId(1860579637015023618l);
user.setName("刘备");
user.setEmail("lb@qq.com");
int result = userMapper.updateById(user);
System.out.println("result: " + result);
}
@Test
public void testSelectById(){
List<Long> list = Arrays.asList(1l, 2l, 3l);
List<User> users = userMapper.selectBatchIds(list);
users.forEach(System.out::println);
}
@Test
public void testSelectByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","诸葛亮");
map.put("age",20);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
@Test
public void testConditionSelect(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name","刘备")
.between("age",10,50)
.isNotNull("email");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
@Test
public void testConditionOrder(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age")
.orderByAsc("id");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
@Test
public void deleteCondition(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
int result = userMapper.delete(queryWrapper);
System.out.println("result:" + result);
}
@Test
public void updateCondition(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",20)
.like("name","刘备")
.or()
.isNull("email");
User user = new User();
user.setName("诸葛亮");
user.setEmail("zhugeliang@qq.com");
int result = userMapper.update(user, queryWrapper);
System.out.println("result: "+result);
}
//UPDATE user SET name=?, email=? WHERE isDeleted=0 AND (name LIKE ? AND (age > ? OR email IS NULL))
@Test
public void updateCondition2(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name","诸葛亮")
.and(i -> i.gt("age",20).or().isNull("email"));
User user = new User();
user.setName("张飞");
user.setEmail("zhangfei@qq.com");
int result = userMapper.update(user, queryWrapper);
System.out.println("result:"+result);
}
//UPDATE user SET name=?,email=? WHERE isDeleted=0 AND (name LIKE ? AND (age > ? OR email IS NULL))
@Test
public void updateCondition3(){
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.like("name","诸葛亮")
.and(i -> i.gt("age",20).or().isNull("email"));
updateWrapper.set("name","孙权").set("email","sunquan@qq.com");
int result = userMapper.update(null,updateWrapper);
System.out.println("result:" + result);
}
@Test
public void selectCondition(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("name","age","email");
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
maps.forEach(System.out::println);
}
//子查询
//SELECT id,name,age,email,isDeleted FROM user WHERE isDeleted=0 AND (id IN (select id from user where id < 10))
@Test
public void selectCondition2(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("id","select id from user where id < 10");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
//模拟实际条件
//SELECT id,name,age,email,isDeleted FROM user WHERE isDeleted=0 AND (age >= ? AND age <= ?)
@Test
public void getCondition(){
String username = "";
Integer startage = 20;
Integer endage = 35;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if(StringUtils.isNotBlank(username)){
queryWrapper.like("name",username);
}
if(startage!=null){
queryWrapper.ge("age",startage);
}
if(endage!=null){
queryWrapper.le("age",endage);
}
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
//SELECT id,name,age,email,isDeleted FROM user WHERE isDeleted=0 AND (age >= ? AND age <= ?)
@Test
public void getCondition2(){
String username = "";
Integer startage = 20;
Integer endage = 35;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username),"name","孙权")
.ge(startage!=null,"age",startage)
.le(endage!=null,"age",endage);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
@Test
public void testSelectLambda(){
String username = "";
Integer startage = 20;
Integer endage = 35;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username),User::getName,username)
.ge(startage!=null,User::getAge,startage)
.le(endage!=null,User::getAge,endage);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
//UPDATE user SET name=?,age=?,email=? WHERE isDeleted=0 AND (age >= ? AND age <= ?)
@Test
public void testUpdateLambda(){
String username = "";
Integer startage = 20;
Integer endage = 35;
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.like(StringUtils.isNotBlank(username),User::getName,username)
.ge(startage!=null,User::getAge,startage)
.le(endage!=null,User::getAge,endage);
updateWrapper.set(User::getName,"诸葛亮回来了").set(User::getAge,16).set(User::getEmail,"诸葛亮@qq" +
".com");
int result = userMapper.update(null, updateWrapper);
System.out.println("result: "+result);
}
@Test
public void testOptimisticLocker2(){
// 线程1
//1.查询用户信息
User user1 = userMapper.selectById(2);
//2.修改用户信息
user1.setName("马超1");
user1.setAge(20);
user1.setEmail("machao1@qq.com");
//模拟另外一个线程执行了插队操作
User user2 = userMapper.selectById(2);
//2.修改用户信息
user2.setName("马超2");
user2.setAge(20);
user2.setEmail("machao2@qq.com");
userMapper.updateById(user2);
//如果没有乐观锁就会覆盖插队线程的值
//可以使用自旋锁来多次尝试提交
userMapper.updateById(user1);
}
}
十二、服务测试类
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
public class MyBatisPlusServiceTest {
@Autowired
private UserService userService;
@Test
public void testGetCount(){
int count = userService.count();
System.out.println("总记录数: "+count);
}
@Test
public void testInsertBatch(){
List<User> list = new ArrayList<>();
for (int i = 1; i<= 10; i++){
User user = new User();
user.setName("fy"+i);
user.setAge(20+i);
user.setEmail("fy"+i+"qq.com");
list.add(user);
}
boolean b = userService.saveBatch(list);
System.out.println("操作结果:"+b);
}
}
十三、分页测试类
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lovejava.boot.mapper.UserMapper;
import com.lovejava.boot.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MybatisPlusPluginsTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectPage(){
Page<User> page = new Page<>(1,1);
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}
//SELECT COUNT(*) FROM user WHERE isDeleted = 0 AND (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
@Test
public void testSelectConditionPage(){
Page<User> page = new Page<>(1,1);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name","刘备")
.between("age",10,50)
.isNotNull("email");
userMapper.selectPage(page,queryWrapper);
System.out.println(page);
System.out.println(page.getTotal());
System.out.println(page.getRecords());
System.out.println(page.getPages());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
}
十四、枚举测试类
import com.lovejava.boot.enums.SexEnum;
import com.lovejava.boot.mapper.UserMapper;
import com.lovejava.boot.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MyBatisPlusEnumTest {
@Autowired
private UserMapper userMapper;
@Test
public void test(){
User user = new User();
user.setName("admin");
user.setAge(23);
user.setSex(SexEnum.MALE);
user.setEmail("admin@qq.com");
int result = userMapper.insert(user);
System.out.println("result:" + result);
}
}
十五、乐观锁测试类
实体类添加字段:
@Version
private Integer version;
添加乐观锁插件
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.lovejava.boot.mapper")
public class MybatisPlusConfig {
/**
* 添加分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 如果配置多个插件, 切记分页最后添加
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
}
乐观锁实现
@Test
public void testOptimisticLocker2(){
// 线程1
//1.查询用户信息
User user1 = userMapper.selectById(2);
//2.修改用户信息
user1.setName("马超1");
user1.setAge(20);
user1.setEmail("machao1@qq.com");
//模拟另外一个线程执行了插队操作
User user2 = userMapper.selectById(2);
//2.修改用户信息
user2.setName("马超2");
user2.setAge(20);
user2.setEmail("machao2@qq.com");
userMapper.updateById(user2);
//如果没有乐观锁就会覆盖插队线程的值
//可以使用自旋锁来多次尝试提交
userMapper.updateById(user1);
}