<dependencies>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.3version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
dependencies>
springboot_mybatisplus_quickstart\src\main\resources\application.yml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/jdbc
username: root
password: 5508769123
# 开启mp的日志(输出到控制台)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
springboot_mybatisplus_quickstart\src\main\java\com\mercurows\domain\Student.java
package com.mercurows.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
@Data
public class Student {
// 数据库默认的主键自增方式
@TableId(type = IdType.AUTO)
private Integer id;
private String nameCh;
private String nameEn;
private String sex;
private Integer age;
}
springboot_mybatisplus_quickstart\src\main\java\com\mercurows\mapper\StudentMapper.java
package com.mercurows.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mercurows.domain.Student;
@Mapper
public interface StudentMapper extends BaseMapper<Student>{
}
springboot_mybatisplus_quickstart\src\main\java\com\mercurows\service\StudentService.java
package com.mercurows.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mercurows.domain.Student;
public interface StudentService extends IService<Student>{
}
springboot_mybatisplus_quickstart\src\main\java\com\mercurows\service\impl\StudentServiceImpl.java
package com.mercurows.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mercurows.domain.Student;
import com.mercurows.mapper.StudentMapper;
import com.mercurows.service.StudentService;
public class StudentServiceImpl extends ServiceImpl<StudentMapper,Student> implements StudentService{
}
见Mybatis控制层部分
例如实体类名字为Student
,数据库名字为sstudent
。则需要在实体类前面加上@TableName("sstudent")
注解:
// 当类名与数据库名字不一致时使用该注解
@TableName("sstudent")
public class Student {
}
例如实体类中存在private boolean isGraduate
的成员变量而数据库中不存在,这样SQL查询数据库时将会报错。则需要在该变量前加上@TableField(exist = false)
注解:
// 这是数据库没有而实体类独有的,为了防止Java查询数据库
// 试图查询该数据时报错需要标记其不存在
@TableField(exist = false)
private boolean isGraduate;
类似于电话号码、密码之类的信息是不应该在查询时显示出来的。则需要在该变量前加上@TableField(value = "tell",select = false)
注解:
// 将telephone对应数据库中的tell字段,并且由于这是隐私数据,所以不参与查询
@TableField(value = "tell",select = false)
private Integer telephone;
当一个表关联多个表时,该表数据就不能随便删除就得要先删除其他的表数据才能删除该表的数据。因此就可以引入一个标记位,用来逻辑标记该表的数据已被删除而不进行真正的物理删除。
// 默认值与数据库中的一样为0 被删除标记为1
// @TableLogic(value = "0",delval = "1")
// 也可以写在mp配置文件中
private Integer deleted;
数据库设计部分:
这样就可以让删除之后deleted信息(删除前默认为0)为1而不会物理上删除且deleted为1时不参与查询。
package com.mercurows;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.mercurows.domain.Student;
import com.mercurows.mapper.StudentMapper;
@SpringBootTest(classes = { SpringbootMybatisplusQuickstartApplication.class })
class SpringbootMybatisplusQuickstartApplicationTests {
@Autowired
private StudentMapper studentMapper;
@Test
void testDelete(){
// 单一删除
studentMapper.deleteById(23);
}
@Test
void tsetGetById() {
// 单一查找
Student student = studentMapper.selectById(23);
System.out.println(student);
System.out.println("tsetGetById");
}
}
事实上SQL执行的删除语句为UPDATE sstudent SET deleted=1 WHERE id=? AND deleted=0
执行的查找语句为SELECT id,name_ch,name_en,sex,age,deleted,version FROM sstudent WHERE id=? AND deleted=0
给成员类添加private Integer version
变量,且前面加上@Version
注解。
// 乐观锁所需要的变量,同时也存在于数据库
@Version
private Integer version;
数据库设计:
添加乐观锁拦截器
package com.mercurows.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
// 使拦截器能被扫描
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mpInterceptor() {
// 创建mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
// 往mp拦截器中添加乐观锁拦截器(具体拦截器)
mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mpInterceptor;
}
}
测试
package com.mercurows;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
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.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mercurows.domain.Student;
import com.mercurows.domain.query.StudentQuery;
import com.mercurows.mapper.StudentMapper;
// @MapperScan("com.mercurows.dao")
@SpringBootTest(classes = { SpringbootMybatisplusQuickstartApplication.class })
// @SpringBootTest()
class SpringbootMybatisplusQuickstartApplicationTests {
@Autowired
private StudentMapper studentDao;
@Test
void testUpdate() {
Student student = studentDao.selectById(1); //此时version=3
Student student2 = studentDao.selectById(1); //此时version=3
student.setNameCh("小黄黄888");
studentDao.updateById(student); //更新之后version++=4
student2.setNameCh("小黄黄999");
studentDao.updateById(student2); //version=3的条件已经不成立
System.out.println("testUpdate");
}
}
SQL :
第一次updateById操作
==> Preparing: UPDATE sstudent SET name_ch=?, name_en=?, sex=?, age=?, version=? WHERE id=? AND version=? AND deleted=0
==> Parameters: 小黄黄888(String), xiaohuanghuang(String), 女(String), 12(Integer), 4(Integer), 1(Integer), 3(Integer)
<== Updates: 1
第二次updateById操作
==> Preparing: UPDATE sstudent SET name_ch=?, name_en=?, sex=?, age=?, version=? WHERE id=? AND version=? AND deleted=0
==> Parameters: 小黄黄999(String), xiaohuanghuang(String), 女(String), 12(Integer), 4(Integer), 1(Integer), 3(Integer)
<== Updates: 0
void testGetAll() {
StudentMapper studentDao;
// 查询所有
List<Student> students = studentDao.selectList(null);
System.out.println("查询所有====>");
System.out.println(students);
students.clear();
// 单条件查询查询
// 注意:lt-小于;le-小于等于;gt-大于;ge-大于等于;eq-等于;between-范围左闭右闭
// 方式一:
QueryWrapper<Student> qw = new QueryWrapper<>();
students = studentDao.selectList((Wrapper<Student>) qw.lt("age", 12));
System.out.println("单条件查询age<12 方式一 ====>");
System.out.println(students);
students.clear();
// 方式二:lambda格式条件查询
QueryWrapper<Student> qw1 = new QueryWrapper<>();
// 将原本的第一个参数:列名,改用getAge方式获取预防写错
qw1.lambda().lt(Student::getAge, 12);
students = studentDao.selectList(qw1);
System.out.println("单条件查询age<12 方式二 ====>");
System.out.println(students);
students.clear();
// 方式三:lambda格式条件查询 (推荐)
LambdaQueryWrapper<Student> lqw = new LambdaQueryWrapper<>();
lqw.lt(Student::getAge, 12);
students = studentDao.selectList(lqw);
System.out.println("单条件查询age<12 方式三 ====>");
System.out.println(students);
students.clear();
// 多条件查询
// 且关系:
LambdaQueryWrapper<Student> lqw1 = new LambdaQueryWrapper<>();
lqw1.gt(Student::getAge, 10);
lqw1.lt(Student::getAge, 13);
students = studentDao.selectList(lqw1);
// List studentss = studentDao.selectList(lqw1.between(Student::getAge, 11, 12));
System.out.println("多条件查询10" );
System.out.println(students);
students.clear();
// 或关系:
LambdaQueryWrapper<Student> lqw2 = new LambdaQueryWrapper<>();
lqw2.lt(Student::getAge, 12);
lqw2.or().gt(Student::getAge, 13);
students = studentDao.selectList(lqw2);
System.out.println("多条件查询age<12 or age>13 ====>");
System.out.println(students);
students.clear();
// 模拟页面传递过来的查询数据
StudentQuery sq = new StudentQuery();
// 设置为多条件查询下限
sq.setAge(10);
// 设置为多条件查询上限
sq.setAge2(13);
// 条件查询null判定
LambdaQueryWrapper<Student> lqw3 = new LambdaQueryWrapper<>();
lqw3.lt(sq.getAge2() != null, Student::getAge, sq.getAge2());
lqw3.gt(sq.getAge() != null, Student::getAge, sq.getAge());
students = studentDao.selectList(lqw3);
System.out.println("多条件查询10" );
System.out.println(students);
students.clear();
// 查询投影:只显示结果集合中的指定字段
LambdaQueryWrapper<Student> lqw4 = new LambdaQueryWrapper<>();
lqw4.select(Student::getNameCh, Student::getNameEn);
students = studentDao.selectList(lqw4);
System.out.println("查询投影");
System.out.println(students);
students.clear();
// 聚合函数:count
// 注意:LambdaQueryWrapper的select查询结果包含模型类中部分属性
// QueryWrapper查询结果包含模型类中未定义的属性
QueryWrapper<Student> qw2 = new QueryWrapper<>();
qw2.select("count(*) as count,sex");
qw2.groupBy("sex");
List<Map<String, Object>> studenList = studentDao.selectMaps(qw2);
System.out.println("聚合函数");
System.out.println(studenList);
// 查询条件设置
LambdaQueryWrapper<Student> lqw5 = new LambdaQueryWrapper<>();
lqw5.eq(Student::getNameCh, "小黄黄").eq(Student::getNameEn, "xiaohuanghuang");
Student student = studentDao.selectOne(lqw5);
System.out.println("查询条件设置");
System.out.println(student);
// 模糊匹配 like
LambdaQueryWrapper<Student> lqw6 = new LambdaQueryWrapper<>();
lqw6.like(Student::getNameCh, "小");
students = studentDao.selectList(lqw6);
System.out.println("模糊匹配");
System.out.println(students);
}