pom依赖
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.5.6version>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>demoname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.3.4version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.27version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.22version>
dependency>
dependencies>
project>
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
server:
port: 9090
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
@Data
public class User {
//定义属性,属性名和表中的列名一样
/**
* 指定主键的方式:
* value:主键字段的名称,如果是id,可以不用写
* type:指定主键的类型,主键的值如何生成,
* IdType.AUTO表示自动增长
*/
@TableId(value = "id",type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
Mapper
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
/**
* 自定义Maper,就是Dao接口
* 1、要实现BaseMapper
* 2、指定实体类
* BaseMapper是MP框架中的对象,定义17个操作方法(CRUD)
*/
public interface UserMapper extends BaseMapper<User> {
}
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @MapperScan 注解,扫描器,指定Mapper类所在的包
*/
@SpringBootApplication
@MapperScan(value = "com.example.demo.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
在测试类或service注入Dao接口,框架实现动态代理创建Dao的实体类对象,
调用BaseMapper中的方法,完成CRUD
测试
package com.example.demo;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.List;
@SpringBootTest
class DemoApplicationTests {
//使用自动注入,注入Mapper对象(Dao)
@Autowired
private UserMapper userMapper;
@Test
public void testUser(){
User user =new User();
user.setName("张三");
user.setAge(2);
user.setEmail("[email protected]");
//调用userMapper的方法,也就是父接口BaseMapper中提供的方法
int rows = userMapper.insert(user);
System.out.println("insert的结果:"+rows);
}
}
输出insert的结果:1
控制台输出正在执行的sql语句
application.yml
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
public void testUser(){
User user =new User();
user.setName("zhangsan");
user.setAge(2);
user.setEmail("[email protected]");
//调用userMapper的方法,也就是父接口BaseMapper中提供的方法
int rows = userMapper.insert(user);
System.out.println("insert的结果:"+rows);
}
//添加数据后,获取主键值
@Test
public void testInsertGetId(){
User user =new User();
user.setName("李斯");
user.setAge(2);
user.setEmail("[email protected]");
int rows=userMapper.insert(user);
System.out.println("insert的结果:"+rows);
//获取刚添加到数据库中的数据的主键id
System.out.println("主键id="+user.getId());
}
/**
* 更新操作update
*/
@Test
public void testUpdate(){
User user =new User();
user.setName("修改的数据");
user.setEmail("[email protected]");
user.setId(6L);;
/**
* 执行更新,根据主键值更新
* UPDATE user SET name=?, email=? WHERE id=?
* 更新了所有非null属性值,根据WHERE id=主键值
*/
int rows=userMapper.updateById(user);
System.out.println("update rows: " +rows);
}
/**
* 控制更新的属性
*/
@Test
public void testUpdate2(){
User user =new User();
user.setId(2L);;
user.setName("张三");
/**
* 更新属性
* UPDATE user SET name=? WHERE id=?
*/
int i = userMapper.updateById(user);
System.out.println("i="+i);
}
/**
* 更新数据,实体类的属性是基本类型-int age
* 实体类属性:推荐使用包装类型,可以判断是否为null
* 基本数据类型都有默认值,在不赋值的情况下,会在数据库中插入默认的值,
*/
@Test
public void testUpdate3(){
User user =new User();
user.setId(3L);
user.setEmail("[email protected]");
/**
* 实体对象user:{name=null,email=”[email protected]“,age=0,
* 没有修改name,age
* 判断字段是否要修改,加入到set语句,是根据属性值是否为null
* UPDATE user SET age=?, email=? WHERE id=?
*/
int rows = userMapper.updateById(user);
System.out.println("rows="+rows);
}
/**
* 根据id删除
* 按主键删除一条数据
* 方法是deleteById()
* 参数:主键值
* 返回值:是删除的成功记录数
*/
@Test
public void testDelete(){
//DELETE FROM user WHERE id=?
int rows =userMapper.deleteById(3);
System.out.println("rows="+rows);
}
/**
* 按条件删除数据,条件是封装到Map对象中
* 方法:deleteByMap(map对象)
* 返回值:删除成功的记录数
*/
@Test
public void testDeleteMap(){
//创建Map对象,保存条件值
Map<String,Object> map=new HashMap<>();
//put("表的字段名",条件值)
map.put("name","zhangsan");
map.put("age",2);
//调用删除方法
// DELETE FROM user WHERE name = ? AND age = ?
int rows=userMapper.deleteByMap(map);
System.out.println("rows="+rows);
}
/**
* 批处理方式:使用多个主键值,删除数据
* 方法民初:deleteBatchIds()
* 参数:Collection extends Serializable> idList
* 返回值是删除的记录数
*/
@Test
public void testDeleteBatchIds(){
List<Integer>ids=new ArrayList<>();
ids.add(1);
ids.add(5);
ids.add(6);
//DELETE FROM user WHERE id IN ( ? , ? , ? )
int rows=userMapper.deleteBatchIds(ids);
System.out.println("rows="+rows);
}
/**
* 批处理方式:使用多个主键值,删除数据
* 方法民初:deleteBatchIds()
* 参数:Collection extends Serializable> idList
* 返回值是删除的记录数
*/
@Test
public void testDeleteBatchIds(){
//使用lamda表达式创建list集合
List<Integer>ids= Stream.of(2,4).collect(Collectors.toList());
//DELETE FROM user WHERE id IN ( ? , ? , ? )
int rows=userMapper.deleteBatchIds(ids);
System.out.println("rows="+rows);
}
/**
*实现查询selectById,根据主键值查询
* 参数:主键值
* 返回值:实体对象(唯一的一个对象)
*/
@Test
public void testSelectById(){
User user =userMapper.selectById(1);
/**
* SELECT id,name,age,email FROM user WHERE id=?
* 如果根据主键没有查找到数据,得到的返回值是null
*/
// 在使用对象之前,需要判断对象是否为null
if(user!=null){
//业务方法的调用
}
System.out.println("user="+user);
}
/**
* 实现批处理查询,根据多个主键值查询,获取到list
* 方法:selectBatchIds
* 参数:id的集合
* 返回值List
*/
@Test
public void testSelectBatchIds(){
//lambda表达式
//SELECT id,name,age,email FROM user WHERE id IN ( ? , ? , ? )
List<Integer>ids=Stream.of(4,8,9).collect(Collectors.toList());
List<User>users=userMapper.selectBatchIds(ids);
for (User user:users){
System.out.println(user);
}
}
/**
* 使用Map做条件查询
* 方法:selectMap()
* 参数:Mapkey为参数名,value为条件
* 返回值:List
*/
@Test
public void testSelectMap(){
//创建Map,封装查询条件
Map<String,Object>map=new HashMap<>();
//key是字段名,value:字段值,多个key,and连接
map.put("name","zhangsan");
map.put("age",20);
List<User>users=userMapper.selectByMap(map);
//SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
users.forEach(user -> {
System.out.println(user);
});
}
mybatis-plus的CRUD底层源码调用的是mybatis的SqlSession的方法
ActiveRecord
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
/**
* 必须继承Model,Model定义了表的CRUD方法,Dept属性名和列名是一样的
*/
@Data
public class Dept extends Model<Dept> {
@TableId(value = "id",type = IdType.AUTO)//自动增长,数据库中的字段为id
private Integer id;
private String name;
private String mobile;
private Integer manager;
}
3、Mapper
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Dept;
/**
* 不使用DeptMapper,也需要定义这个类,MP通过mapper获取表的结构
* 不定义DeptMapper,MP会报错,找不到表的定义信息
*/
public interface DeptMapper extends BaseMapper<Dept> {
}
4、测试AR
package com.example.demo;
import com.example.demo.entity.Dept;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class DeptARTest {
@Test
public void testARInsert(){
Dept dept = new Dept();
dept.setName("销售部");
dept.setMobile("010-12345678");
dept.setManager(1);
//调用实体对象自己的方法,完成对象自身到数据库的操作
boolean flag = dept.insert();
System.out.println("insert="+flag);
}
}
@Test
public void testUpdateById(){
Dept dept =new Dept();
dept.setId(3);
dept.setManager(2);
/**
* 根据主键id更新数据
* UPDATE dept SET manager=? WHERE id=?
* 主键不能为空,否则更新失败
* 主键在数据库中不存在,更新返回false
* null的属性值不做更新处理,在update中没有null的字段
*/
boolean flag =dept.updateById();
System.out.println("update flag="+flag);
}
@Test
public void testARDelete(){
Dept dept =new Dept();
dept.setId(1);
/**
* DELETE FROM dept WHERE id=?
* deleteById()删除操作即使没有从数据库中删除数据,也返回是true
* deleteById(1)传参,没有删除成功返回的是false
*/
boolean flag = dept.deleteById();//拿实体自身的id作为删除的主键
boolean result=dept.deleteById(1);
System.out.println("删除是否成功:"+flag);
System.out.println("result="+result);
}
@Test
public void testSelectById(){
Dept dept =new Dept();
dept.setId(1);
/**
* SELECT id,name,mobile,manager FROM dept WHERE id=?
* selectById
* 1.按实体的主键能查出数据,返回对象
* 2.按实体的主键不能查出数据,返回null,不报错
*/
Model model=dept.selectById();
System.out.println(model);
}
/**
* selectById(主键)
* 1.主键有记录,返回实体对象
* 2.主键没有记录,返回是null,不报错
* 3.主键参数为null,返回是null
*/
@Test
public void testSelect(){
Dept dept =new Dept();
Dept dept2=dept.selectById(null);
System.out.println(dept2);
}
主键,TableName,TableId
IdType枚举类,主键定义如下:
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @TableName(value = "表名")
*/
@Data
@TableName(value = "address")
public class Address {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
/**
* @TableField:指定属性和列名的对应关系
* 属性:value指定列名(数据库里对应的列名)
*/
@TableField(value = "city")
private String city;
private String street;
private String zipcode;
}
Mapper
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Address;
public interface AddressMapper extends BaseMapper<Address> {
}
测试
package com.example.demo;
import com.example.demo.entity.Address;
import com.example.demo.mapper.AddressMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class AddressTest {
@Resource
public AddressMapper addressMapper;
@Test
public void testInsert(){
Address address = new Address();
address.setCity("北京");
address.setStreet("长安大街");
address.setZipcode("010");
int rows=addressMapper.insert(address);
System.out.println("rows="+rows);
}
}
package com.example.demo.entity;
import lombok.Data;
@Data
public class Customer {
private Integer id;
private String custName;
private String custEmail;
private Integer custAge;
}
Mapper
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Customer;
public interface CustomerMapper extends BaseMapper<Customer> {
}
测试
package com.example.demo;
import com.example.demo.entity.Customer;
import com.example.demo.mapper.CustomerMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class CustomerTest {
@Resource
public CustomerMapper dao;
@Test
public void test(){
Customer customer =new Customer();
customer.setCustName("张三");
customer.setCustAge(28);
customer.setCustEmail("[email protected]");
int rows=dao.insert(customer);
System.out.println("rows="+rows);
/**
* INSERT INTO customer ( cust_name, cust_email, cust_age ) VALUES ( ?, ?, ? )
* Parameters: 张三(String), [email protected](String), 28(Integer)
* rows=1
*/
}
}
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
@Data
public class Student {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String name;
private Integer age;
private String email;
private Integer status;
}
Mapper
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Student;
import java.util.List;
public interface StudentMapper extends BaseMapper<Student> {
List<Student > selectByName();
public int insertStudent(Student student);
public Student selectStudentByName(String name);
}
新建sq映射文件
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.StudentMapper">
<select id="selectByName" resultType="com.example.demo.entity.Student">
select id,name,age,email,status from student order by id limit 10
select>
<insert id="insertStudent" parameterType="com.example.demo.entity.Student">
insert into student (name,age,email,status) values(#{name},#{age},#{email},#{status})
insert>
<select id="selectStudentByName" resultType="com.example.demo.entity.Student">
select id,name,age,email,status from student where name =#{name}
select>
mapper>
package com.example.demo;
import com.example.demo.entity.Student;
import com.example.demo.mapper.StudentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class StudentTest {
@Resource
private StudentMapper mapper;
@Test
public void testInsert(){
/**
* insert into student (name,age,email,status) values(?,?,?,?)
*/
Student student = new Student();
student.setName("李四");
student.setEmail("[email protected]");
student.setAge(20);
student.setStatus(1);
mapper.insertStudent(student);
}
@Test
public void testSeectById(){
/**
* select id,name,age,email,status from student where name =?
*/
Student student = mapper.selectStudentByName("李四");
/**
* SELECT id,name,age,email,status FROM student WHERE id=?
*/
Student stu = mapper.selectById(2);
System.out.println(stu);
if(stu!=null){
//其他业务操作
}
System.out.println(student);
}
}
在idea中ctr+N搜索Wrapper,鼠标选中Wrapper,ctrl+f12查看当前类的结构信息
条件 | 说明 |
---|---|
allEq | 基于map的相等 |
eq | 等于= |
ne | 不等于<> |
gt | 大于> |
ge | 大于等于 |
lt | 小于 |
le | 小于等于 |
betwen | betwen 值1 and 值2 |
notBetween | not betwen 值1 and 值2 |
like | Like ‘%值%’ |
notLike | not like ‘%值%’ |
likeLeft | like’%值’ |
likeRight | like ‘值%’ |
isNull | 字段 is null |
isNotNull | 字段 is not null |
in | 字段 in (value1,value2,…) |
notIn | 字段 not in (value1,value2,…) |
inSql | 字段 in (sql语句) |
notInSql | 字段 NOT IN ( sql语句 ) |
groupBy | GROUP BY 字段 |
orderByAsc | ORDER BY 字段, … ASC |
orderByDesc | ORDER BY 字段, … DESC |
orderBy | ORDER BY 字段, …例: orderBy(true, true, “id”, “name”)—>order by id ASC,name ASC |
having | HAVING ( sql语句 ) 条件分组 |
or | or 语句,拼接 +OR 字段=值 |
and | And语句,拼接+AND 字段=值 |
apply | 拼接sql |
last | 在sql语句后拼接自定义条件 |
exists | 拼接exists(sql语句)exists(“select id from table where age = 1”)—>exists (select id from table where age = 1) |
notExists | 拼接 NOT EXISTS ( sql语句 ) |
nested | 正常嵌套不带and或者or |
方法 | 说明 |
---|---|
select | 设置 查询字段select后面的内容 |
方法 | 说明 |
---|---|
set | 设置要更新的字段,MP拼接sql语句 |
setSql | 参数是sql语句,MP不在处理语句 |
以Map为参数条件
1、条件:name是张三,age=22
@Test
public void testAllEq(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
Map<String,Object>map=new HashMap<>();
map.put("name","张三");
map.put("age",22);
//组装条件
queryWrapper.allEq(map);
/**
* Map,key:对应列名,value:查询的值
* SELECT id,name,age,email,status FROM student WHERE (name = ? AND age = ?)
* Parameters: 张三(String), 22(Integer)
*输出
* Student(id=3, name=张三, age=22, [email protected], status=1)
*/
List<Student>students=mapper.selectList(queryWrapper);//调用mp自己的查询方法
students.forEach(student -> {
//循环遍历输出
System.out.println(student);
});
}
@Test
public void testAllEq2(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
Map<String,Object>map=new HashMap<>();
map.put("name","张三");
map.put("age",null);
//组装条件
/**
* Map对象中有key的value是null
* 使用的是queryWrapper.allEq(map,true)
* 结果:
* SELECT id,name,age,email,status FROM student WHERE (name = ? AND age IS NULL)
* 如果使用的是使用的是queryWrapper.allEq(map,false)
* 结果:
* SELECT id,name,age,email,status FROM student WHERE (name = ?)
* 结论:
* allEq(map,boolean)
* true:处理null值,where条件加入字段 is null
* false:忽略null,不作为where条件
*/
queryWrapper.allEq(map,false);
List<Student>students=mapper.selectList(queryWrapper);//调用mp自己的查询方法
students.forEach(stu-> System.out.println(stu));
}
等于 =
name等于李四
@Test
public void testEq(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
/**
* eq使用
* eq("列名",值)
* SELECT id,name,age,email,status FROM student WHERE (name = ?)
*/
//组成条件
queryWrapper.eq("name","张三");
List<Student>students=mapper.selectList(queryWrapper);//调用mp自己的查询方法
students.forEach(stu-> System.out.println(stu));
}
ne 不等于
@Test
public void testNe(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
/**
* ne(列名,值)
* ne不等于
* SELECT id,name,age,email,status FROM student WHERE (name <> ?)
*/
queryWrapper.ne("name","张三");
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
gt大于
@Test
public void testGt(){
/**
*SELECT id,name,age,email,status FROM student WHERE (age > ?)
*/
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",20);
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
ge大于等于
@Test
public void testGe(){
/**
*SELECT id,name,age,email,status FROM student WHERE (age >= ?)
*/
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age",30);
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
lt小于
@Test
public void testLt(){
/**
*SELECT id,name,age,email,status FROM student WHERE (age < ?)
*/
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.lt("age",30);
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
le小于等于
@Test
public void testLe(){
/**
*SELECT id,name,age,email,status FROM student WHERE (age <= ?)
*/
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.le("age",30);
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
between 在两个值范围之间(包括开始区间和结束区间)
@Test
public void testBetween(){
/**
*SELECT id,name,age,email,status FROM student WHERE (age BETWEEN ? AND ?)
* 等于SELECT id,name,age,email,status FROM student WHERE age>=18 and age<=28
* between("列名",开始值,结束值)
*/
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.between("age",18,28);
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
不在范围区间内
@Test
public void testNotBetween(){
/**
* SELECT id,name,age,email,status FROM student WHERE (age NOT BETWEEN ? AND ?)
* 等于
* SELECT id,name,age,email,status FROM student WHERE age<18 or age>28
*/
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.notBetween("age",18,28);
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
like 匹配值 “%值”
notLike 不匹配"%值"
@Test
public void testLike(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.like("name","张");
/**
* ==> Preparing: SELECT id,name,age,email,status FROM student WHERE (name LIKE ?)
* ==> Parameters: %张%(String)
* <== Columns: id, name, age, email, status
* <== Row: 3, 张三, 22, [email protected], 1
* <== Total: 1
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
@Test
public void testNotLike(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.notLike("name","张");
/**
Preparing: SELECT id,name,age,email,status FROM student WHERE (name NOT LIKE ?)
Parameters: %张%(String)
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
likeLeft:LIKE ‘%值’
likeRight:LIKE ‘值%’
@Test
public void testLikeLeft(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.likeLeft("name","张");
/**
SELECT id,name,age,email,status FROM student where name like '%张'
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
@Test
public void testLikeRight(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name","张");
/**
SELECT id,name,age,email,status FROM student where name like '张%'
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
isNull:字段 IS NULL
isNotNull:字段 IS NOT NULL
@Test
public void testIsNull(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
/**
SELECT id,name,age,email,status FROM student WHERE (email IS NULL)
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
@Test
public void testIsNotNull(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.isNotNull("email");
/**
SELECT id,name,age,email,status FROM student WHERE (email IS NOT NULL)
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
in后面值列表,在列表中都是符合条件的
notIn 不在列表中的
@Test
public void testIn(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.in("name","张三","李四");
/**
Preparing: SELECT id,name,age,email,status FROM student WHERE (name IN (?,?))
Parameters: 张三(String), 李四(String)
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
@Test
public void testNotIn(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.notIn("name","张三","李四");
/**
Preparing: SELECT id,name,age,email,status FROM student WHERE (name NOT IN (?,?))
Parameters: 张三(String), 李四(String)
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
inSql常用来做子查询类似 in()
notInSql 类似notIn()
@Test
public void testInSql(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("age","select age from student where id = 1");
/**
SELECT id,name,age,email,status FROM student WHERE (age IN (select age from student where id = 1))
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
@Test
public void testNotInSql(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.notInSql("age","select age from student where id = 1");
/**
SELECT id,name,age,email,status FROM student WHERE (age not IN (select age from student where id = 1))
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
groupBy基于多个字段分组
@Test
public void testGroupBy(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.select("name,count(*) personNumbers");
queryWrapper.groupBy("name");
/**
* groupBy 分组
* SELECT name,count(*) personNumbers FROM student GROUP BY name
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
orderByAsc 按字段降序
orderBy 每个字段指定排序方向
@Test
public void testOrderBy(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
//orderBy(条件内容是否添加到sql语句后面,true为添加,false为不添加)
queryWrapper.orderBy(true,true,"name");
/**
* orderBy 指定字段和排序方向
*SELECT id,name,age,email,status FROM student ORDER BY name ASC
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
@Test
public void testOrderBy2(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
//添加多个排序字段
queryWrapper.orderBy(true,true,"name")
.orderBy(true,true,"email");
/**
* orderBy 指定字段和排序方向
*SELECT id,name,age,email,status FROM student ORDER BY name ASC,email ASC
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
or 连接条件用or
and 连接条件用and
@Test
public void testOr(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name","张三")
.or()
.eq("age",20);
/*
SELECT id,name,age,email,status FROM student WHERE (name = ? OR age = ?)
Parameters: 张三(String), 20(Integer)
*/
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
last拼接sql语句
@Test
public void testLst(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
/*
在sql语句最后面拼接sql语句
Preparing: SELECT id,name,age,email,status FROM student WHERE (name = ? OR age = ?) limit 1
Parameters: 张三(String), 20(Integer)
*/
queryWrapper.eq("name","张三")
.or()
.eq("age",20)
.last("limit 1");
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
exists 拼接 EXISTS ( sql语句 )
notExists:是相反的操作
@Test
public void testExist(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
/*
SELECT id,name,age,email,status FROM student WHERE (EXISTS (select id from student where age>20))
*/
queryWrapper.exists("select id from student where age>20");
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
@Test
public void testNotExist(){
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
/*
SELECT id,name,age,email,status FROM student WHERE (NOT EXISTS (select id from student where age>20))
*/
queryWrapper.notExists("select id from student where age>20");
List<Student>students=mapper.selectList(queryWrapper);
students.forEach(student -> System.out.println(student));
}
前提:配置分页插件,实现物理分页。默认是内存分页
由于springBoot启动类本身也是一个配置类(@Configuration修饰的类)
可以在springBoot启动类里main方法下面配置分页
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @MapperScan 注解,扫描器,指定Mapper类所在的包
*/
@SpringBootApplication
@MapperScan(value = "com.example.demo.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
mybatis-plus 3.4.3.4配置分页插件如下
package com.example.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Configuration标注的类相当于xml配置文件
*/
@Configuration
public class Config {
/**
* 定义方法,方法的返回值是java对象,这个对象是放入到spring容器中
* @Bean 等同于
*/
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//DbType.MYSQL:分页使用的语句是mysql类型
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
测试
@Test
public void testPage(){
/**
* 分页:
* 1.统计记录数,使用count(1)
* select count(1) from student
* 2.实现分页,在sql语句的末尾加入limit 0,3
* SELECT id,name,age,email,status FROM student LIMIT 3
* 要点!! 分页返回的对象与传入的对象是同一个
*@Param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
*/
QueryWrapper<Student>queryWrapper = new QueryWrapper<>();
IPage<Student>page =new Page<>();
//设置分页的数据
page.setCurrent(1);//设置当前页为第一页
page.setSize(3);//每页的记录数为3
IPage<Student> result = mapper.selectPage(page,queryWrapper);
//获取分页后的记录
List<Student>students = result.getRecords();
students.forEach(student -> {
System.out.println(student);
});
//分页的信息
System.out.println("size="+result.getSize());
System.out.println(result.getPages());
System.out.println("页数:"+result.getPages());
System.out.println("总记录数:"+result.getTotal());
System.out.println("当前的页码:"+result.getCurrent());
System.out.println("每页的记录数:"+result.getSize());
/**
* 输出如下结果
* size=3
* 3
* 页数:3
* 总记录数:7
* 当前的页码:1
* 每页的记录数:3
*/
}
mybati-plus官网分页的介绍
package com.example.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.Student;
/**
* mybatis-plus封装的service层的crud接口:IService
*/
public interface StudentService extends IService<Student> {
}
package com.example.demo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.Student;
import com.example.demo.mapper.StudentMapper;
import com.example.demo.service.StudentService;
import org.springframework.stereotype.Service;
/**
* service实现类
* 继承mp提供通用的service基类
* ServiceImpl
* 2个泛型 1.StudentMapper Mapper接口
* 2.Student 对应的实体类对象
*/
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper,Student> implements StudentService{
}
测试
package com.example.demo;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SpringBootTest
public class serviceTest {
@Resource
private StudentService studentService;
@Test
public void getList(){
/*
SELECT id,name,age,email,status FROM student
*/
List<Student> list=studentService.list();
list.forEach(student -> System.out.println(student));
}
@Test
public void query(){
/*
SELECT id,name,age,email,status FROM student WHERE id=?
*/
Student student = studentService.getById(1);
System.out.println(student);
}
@Test
public void insetBath(){
/*
==> Preparing: INSERT INTO student ( name, age, email, status ) VALUES ( ?, ?, ?, ? )
==> Parameters: 测试1(String), 23(Integer), [email protected](String), 1(Integer)
==> Parameters: 测试2(String), 24(Integer), [email protected](String), 1(Integer)
*/
List<Student>list =new ArrayList<>();
Student student = new Student();
student.setName("测试1");
student.setEmail("[email protected]");
student.setAge(23);
student.setStatus(1);
Student student2 = new Student();
student2.setName("测试2");
student2.setEmail("[email protected]");
student2.setAge(24);
student2.setStatus(1);
list.add(student);
list.add(student2);
boolean rows = studentService.saveBatch(list);
System.out.println("rows="+rows);
}
@Test
public void testSaveOrUpdate(){
/**
* 执行的sql语句
* SELECT id,name,age,email,status FROM student WHERE id=8
* 返回 Total:1
* 执行的sql语句
* UPDATE student SET name=?, age=?, email=?, status=? WHERE id=?
* Parameters: 测试2(String), 22(Integer), [email protected](String), 1(Integer), 8(Integer)
* 会根据主键先查询,如果存在就更新,不存在就插入
*/
Student stu = new Student(8,"测试2",22,"[email protected]",1);
boolean flag = studentService.saveOrUpdate(stu);
System.out.println("flag="+flag);
}
@Test
public void testSaveOrUpdate2(){
/**
* 执行的sql语句
* SELECT id,name,age,email,status FROM student WHERE id=8
* 返回 Total:0
* 执行的sql语句
* INSERT INTO student ( id, name, age, email, status ) VALUES ( ?, ?, ?, ?, ? )
* Parameters: 11(Integer), 测试11(String), 11(Integer), [email protected](String), 1(Integer)
*/
Student stu = new Student(11,"测试11",11,"[email protected]",1);
boolean flag = studentService.saveOrUpdate(stu);
System.out.println("flag="+flag);
}
@Test
public void removeById(){
/**
* 执行的sql语句
* DELETE FROM student WHERE id IN ( ? , ? )
* Parameters: 8(Integer), 9(Integer)
*/
List<Integer>ids = Arrays.asList(8,9);
boolean flag = studentService.removeByIds(ids);
System.out.println("flag="+flag);
}
}
在配置好分页插件之后,分页查询才会生效
package com.example.demo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SpringBootTest
public class serviceTest {
@Resource
private StudentService studentService;
@Test
public void page(){
/*
执行的sql语句
SELECT COUNT(*) AS total FROM student
SELECT id,name,age,email,status FROM student LIMIT 2
*/
IPage<Student>iPage =new Page<>(1,2);
IPage<Student>page = studentService.page(iPage);
List<Student>list =page.getRecords();
System.out.println(list);//[Student(id=1, name=丽斯, age=20, [email protected], status=1), Student(id=2, name=李四, age=20, [email protected], status=1)]
System.out.println(page.getPages());//4
}
}
package com.example.demo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SpringBootTest
public class serviceTest {
@Resource
private StudentService studentService;
@Test
public void contextLoad(){
QueryWrapper<Student>queryWrapper=new QueryWrapper<>();
/*
select():设置查询字段
执行的sql语句:
SELECT id,name,age,email,status FROM student WHERE age=0
*/
queryWrapper.select("id","name","age","email","status")
.eq("age",20);
studentService.list(queryWrapper).forEach(student -> System.out.println(student));
}
@Test
public void updateWrapperTest(){
UpdateWrapper<Student>updateWrapper =new UpdateWrapper<>();
updateWrapper.set("age",20)
.eq("name","张三");
boolean flag = studentService.update(updateWrapper);
/*
执行的sql语句:
UPDATE student SET age=? WHERE (name = ?)
Parameters: 20(Integer), 张三(String)
*/
System.out.println("flag="+flag);
}
@Test
public void queryWrapperTest() {
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().select(Student::getId, Student::getName, Student::getAge, Student::getEmail, Student::getStatus)
.eq(Student::getAge, 20);
studentService.list(queryWrapper).forEach(student -> System.out.println(student));
/*
lamda表达式
执行的sql语句:
SELECT id,name,age,email,status FROM student WHERE (age = ?)
Parameters: 20(Integer)
*/
}
}
全局id生成策略配置:
在全局配置文件中,配置id生成策略,就不需要在每个实体类上添加主键配置了
mybatis-plus:
global-config:
db-config:
id-type: auto
物理删除:在删除的时候,直接将数据从数据库中删除
逻辑删除:从逻辑层面控制删除,通常会在表里添加一个逻辑删除的字段比如enabled,is_delete,数据默认是有效的(值为1),当用户删除时将数据修改
update 0,在查询的时候就只查where enabled = 1,
1.需要添加逻辑删除的字段
2.局部单表逻辑删除,需要在对应的pojo类加入对应的逻辑删除标识字段
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String name;
private Integer age;
private String email;
@TableLogic //代表逻辑删除
private Integer status;
}
全局逻辑删除,如果进行了全局逻辑删除配置并且指定了,就可以不用在每个实体类中配置了 @TableLogic
mybatis-plus:
global-config:
db-config:
logic-delete-field: status # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
测试
有逻辑删除,mp封装的list()会自动过滤逻辑删除状态为已删除的字段
package com.example.demo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SpringBootTest
public class serviceTest {
@Resource
private StudentService studentService;
@Test
public void logicDel(){
/**
* 执行sql语句:
* UPDATE student SET status=1 WHERE id=1 AND status=0
*/
studentService.removeById(1);
}
@Test
public void listTest(){
/**
* 执行的sql语句
* SELECT id,name,age,email,status FROM student WHERE status=0
*/
List<Student>list=studentService.list();
list.forEach(student -> System.out.println(student));
}
}
官网介绍
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String name;
private Integer age;
private String email;
@TableLogic //代表逻辑删除
private Integer status;
// 创建时间:希望在添加是数据的时候填充:当前时间
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//修改时间:希望在修改数据的时候填充当前时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
package com.example.demo.component;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* mybatis-plus自动填充功能自定义接口
*/
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 插入时:创建时间字段为当前时间
this.setFieldValByName("createTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
// 修改时:修改时间字段为当前时间
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
测试
package com.example.demo;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class AutoTest {
@Resource
private StudentService studentService;
@Test
public void test(){
Student student = new Student();
student.setName("张三");
student.setAge(23);
student.setStatus(0);
student.setEmail("[email protected]");
/**
* 执行sql语句
* INSERT INTO student ( name, age, email, status, create_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ? )
* Parameters: 张三(String), 23(Integer), [email protected](String), 0(Integer), 2021-11-22 21:35:43.928(Timestamp), null
*/
studentService.save(student);
}
@Test
public void update(){
/**
* 执行sql语句
* PDATE student SET name=?, age=?, email=?, update_time=? WHERE id=? AND status=0
* Parameters: 张三(String), 22(Integer), [email protected](String), 2021-11-22 21:14:41.971(Timestamp), 1(Integer)
*/
Student student = new Student();
student.setId(1);
student.setName("张三");
student.setAge(22);
student.setStatus(0);
student.setEmail("[email protected]");
boolean flag = studentService.updateById(student);
System.out.println("flag="+flag);
}
}
添加maven依赖
<dependency>
<groupId>p6spygroupId>
<artifactId>p6spyartifactId>
<version>3.9.1version>
dependency>
mysql中sql分析打印配置
spring:
datasource:
#url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
#driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
在resources目录下添加spy.properties,配置如下:
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
执行测试语句
@Test
public void update(){
/**
* 执行sql语句
* PDATE student SET name=?, age=?, email=?, update_time=? WHERE id=? AND status=0
* Parameters: 张三(String), 22(Integer), [email protected](String), 2021-11-22 21:14:41.971(Timestamp), 1(Integer)
*/
Student student = new Student();
student.setId(1);
student.setName("张三");
student.setAge(22);
student.setStatus(0);
student.setEmail("[email protected]");
boolean flag = studentService.updateById(student);
System.out.println("flag="+flag);
}
防止删库跑路
1.得到16位随机密钥
package com.example.demo;
import com.baomidou.mybatisplus.core.toolkit.AES;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class randomKeyTest {
@Test
public void test(){
String randomKey = AES.generateRandomKey();
}
}
2.根据密钥加密数据库连接信息
package com.example.demo;
import com.baomidou.mybatisplus.core.toolkit.AES;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class randomKeyTest {
@Test
public void test(){
String randomKey = AES.generateRandomKey();
String username = AES.encrypt("root",randomKey);
String pwd = AES.encrypt("root",randomKey);
System.out.println(username);
System.out.println(pwd);
}
}
3.修改配置文件
username: mpw:3vOuDLOc1ZjXczflw9LCYA==
password: mpw:3vOuDLOc1ZjXczflw9LCYA==
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
4.在部署的时候需要解密
java -jar xxx.jar --mpw.key=你的16位随机密钥
官网介绍
官网介绍
1.修改表结构,添加version字段,默认为1
2.在实体类的字段上加上@Version注解
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String name;
private Integer age;
private String email;
@TableLogic //代表逻辑删除
private Integer status;
// 创建时间:希望在添加是数据的时候填充:当前时间
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//修改时间:希望在修改数据的时候填充当前时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
@Version
private Integer version;
}
3.配置乐观锁插件
package com.example.demo.config;
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.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Configuration标注的类相当于xml配置文件
*/
@Configuration
public class Config {
/**
* 定义方法,方法的返回值是java对象,这个对象是放入到spring容器中
* @Bean 等同于
*/
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
测试
package com.example.demo;
import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class StudentVersionTest {
@Resource
private StudentService studentService;
@Test
public void testCAS(){
// 线程1 age:50,version:1
Student student1 = studentService.getById(1);
student1.setAge(50);
//线程2 age:100 version:1
Student student2 = studentService.getById(1);
student2.setAge(100);
//update 50 version:2 where version1 = 数据库version
System.out.println(studentService.updateById(student1));/true
//update 100 version:2 where version1 = 数据库version
System.out.println(studentService.updateById(student2));//false
if(studentService.updateById(student1)){
System.out.println("更新成功");
}
if(studentService.updateById(student2)){
System.out.println("更新失败,请重新刷新页面并更新");
}
}
}
更新时候,需要设置version字段
官网教程
引入依赖
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.5.1version>
dependency>
Generator源码地址
GitHub
Gitee
官方文档
Maven仓库坐标
maven依赖
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.5.6version>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>demoname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.2.8version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.27version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.3.4version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.3version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.22version>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
<pluginRepositories>
<pluginRepository>
<id>alimaven spring pluginid>
<name>alimaven spring pluginname>
<url>https://maven.aliyun.com/repository/spring-pluginurl>
pluginRepository>
pluginRepositories>
project>
package com.example.demo.builder;
import lombok.Getter;
import lombok.Setter;
/**
* 测试构建者模式代码生成器
*/
@Setter
@Getter
public class CodeGenerator {
/**
* 数据源配置
*/
private String datasource;
/**
* 包配置
*/
private String packageConfig;
/**
* 策略配置
*/
private String strategyConfig;
/**
* 执行代码生成
*/
public void execute(){
System.out.println(datasource+" "+packageConfig+" "+strategyConfig);
}
}
package com.example.demo.builder;
/**
* 代码生成器构建者模式
*/
public class CodeGeneratorBuilder {
private CodeGenerator codeGenerator;
public CodeGeneratorBuilder(CodeGenerator codeGenerator){
this.codeGenerator=codeGenerator;
}
public static CodeGeneratorBuilder create(String datasource){
CodeGenerator cg = new CodeGenerator();
cg.setDatasource(datasource);
return new CodeGeneratorBuilder(cg);
}
public CodeGeneratorBuilder packageConfig(String packageConfig){
codeGenerator.setPackageConfig(packageConfig);
return this;
}
public CodeGeneratorBuilder strategyConfig(String strategyConfig){
this.codeGenerator.setStrategyConfig(strategyConfig);
return this;
}
public void execute(){
codeGenerator.execute();
}
}
测试
package com.example.demo.builder;
public class Test {
public static void main(String[] args) {
//普通模式
CodeGenerator codeGenerator = new CodeGenerator();
codeGenerator.setDatasource("mysql");
codeGenerator.setPackageConfig("com.baomidou");
codeGenerator.setStrategyConfig("驼峰命名");
codeGenerator.execute();
//构建者模式
CodeGeneratorBuilder.create("mysql").packageConfig("com.baomidou").strategyConfig("驼峰命名").execute();
}
}
数据表创建语句
drop table if exists `t_simple`;
create table `t_simple`
(
id int primary key auto_increment comment 'id',
name varchar(50) comment '姓名',
age int comment '年龄',
delete_flag tinyint(1) comment '删除标识1',
deleted tinyint(1) comment '删除标识2',
version bigint comment '版本',
create_time datetime comment '创建时间',
update_time datetime comment '更新时间'
) COMMENT = '测试表';
package com.example.demo.generator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
public class CodeGenerator {
static final String URL = "jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8";
public static void main(String[] args) {
FastAutoGenerator.create(URL, "root", "root")
// 全局配置
.globalConfig(builder -> builder.outputDir("D:\\code"))
// 策略配置
.strategyConfig(builder -> builder.addInclude("t_simple"))
/*
模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker
.templateEngine(new BeetlTemplateEngine())
.templateEngine(new FreemarkerTemplateEngine())
*/
//执行
.execute();
}
}
输出实体类,Mapper,Service,Controller如下
package com.baomidou.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
* 测试表
*
*
* @author 作者
* @since 2021-11-29
*/
@TableName("t_simple")
public class TSimple implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 删除标识1
*/
private Boolean deleteFlag;
/**
* 删除标识2
*/
private Boolean deleted;
/**
* 版本
*/
private Long version;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(Boolean deleteFlag) {
this.deleteFlag = deleteFlag;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "TSimple{" +
"id=" + id +
", name=" + name +
", age=" + age +
", deleteFlag=" + deleteFlag +
", deleted=" + deleted +
", version=" + version +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}
package com.baomidou.mapper;
import com.baomidou.entity.TSimple;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
*
* 测试表 Mapper 接口
*
*
* @author 作者
* @since 2021-11-29
*/
public interface TSimpleMapper extends BaseMapper<TSimple> {
}
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baomidou.mapper.TSimpleMapper">
mapper>
package com.baomidou.service;
import com.baomidou.entity.TSimple;
import com.baomidou.mybatisplus.extension.service.IService;
/**
*
* 测试表 服务类
*
*
* @author 作者
* @since 2021-11-29
*/
public interface ITSimpleService extends IService<TSimple> {
}
package com.baomidou.service.impl;
import com.baomidou.entity.TSimple;
import com.baomidou.mapper.TSimpleMapper;
import com.baomidou.service.ITSimpleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
*
* 测试表 服务实现类
*
*
* @author 作者
* @since 2021-11-29
*/
@Service
public class TSimpleServiceImpl extends ServiceImpl<TSimpleMapper, TSimple> implements ITSimpleService {
}
package com.baomidou.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
/**
*
* 测试表 前端控制器
*
*
* @author 作者
* @since 2021-11-29
*/
@Controller
@RequestMapping("/tSimple")
public class TSimpleController {
}
package com.example.demo.generator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import java.util.Collections;
public class CodeGenerator {
static final String URL = "jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false";
public static void main(String[] args) {
FastAutoGenerator.create(URL, "root", "root")
.globalConfig(builder -> {
builder.author("baomidou") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
.moduleName("system") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_simple") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
}).execute();
}
}
package com.baomidou.mybatisplus.samples.generator.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
*
* 测试表
*
*
* @author baomidou
* @since 2021-11-29
*/
@TableName("t_simple")
@ApiModel(value = "Simple对象", description = "测试表")
public class Simple implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty("姓名")
private String name;
@ApiModelProperty("年龄")
private Integer age;
@ApiModelProperty("删除标识1")
private Boolean deleteFlag;
@ApiModelProperty("删除标识2")
private Boolean deleted;
@ApiModelProperty("版本")
private Long version;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(Boolean deleteFlag) {
this.deleteFlag = deleteFlag;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "Simple{" +
"id=" + id +
", name=" + name +
", age=" + age +
", deleteFlag=" + deleteFlag +
", deleted=" + deleted +
", version=" + version +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}