MyBatis Plus
介绍
国产的开源框架,基于mybatis
核心功能就是简化mybatis的开发,提高效率。
用springboot+mybatisplus来讲解
1.创建工程
2.pom.xml中插入MybatisPlus依赖(springboot)
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
3.配置application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
4.创建user表
USE mybatis;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(11),
age INT
)
5.创建实体类
package com.zsj.mybatisplus.entity;
import lombok.Data;
/**
* @author zsj
* @create 2023-02-20 23:04
*/
@Data //自动帮你生成getset方法
public class User {
private Integer id;
private String name;
private Integer age;
}
6.创建mapper接口
package com.zsj.mybatisplus.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsj.mybatisplus.entity.User;
public interface UserMapper extends BaseMapper<User> {
}
7.创建测试类
/**
* @author zsj
* @create 2023-02-20 23:14
*/
@SpringBootTest //启动springbootioc容器
@MapperScan("com.zsj.mubatisplus.mapper") //路径
class UserMapperTest {
@Autowired
private UserMapper mapper;
@Test
void test(){
mapper.selectList(null).forEach(System.out::println);
}
}
注意:启动类MybatisplusApplication中要加注解:
@MapperScan("com.zsj.mubatisplus.mapper")
8:结果
ps:如果你希望可以看到sql语句可以展示出来可以在配置文件中添加:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
常用注解
1.@TableName :映射数据库的表名字
@TableName(value = "user") //使实体类名字跟表明对应
2.@TableId(只适用于主键):
- value:映射主键字段名
// private Integer id;
@TableId(value = "id")
private Integer num;
- tape:设置主键类型,主键生成策略
public enum IdType {
AUTO(0),
NONE(1),
INPUT(2),
ASSIGN_ID(3),
ASSIGN_UUID(4),
/** @deprecated */
@Deprecated
ID_WORKER(3),
/** @deprecated */
@Deprecated
ID_WORKER_STR(3),
/** @deprecated */
@Deprecated
UUID(4);
private final int key;
private IdType(int key) {
this.key = key;
}
public int getKey() {
return this.key;
}
}
| 值 | 描述 |
|---|---|
| Auto | 数据库自增 |
| NONE(默认) | MP set主键,雪花算法实现 |
| INPUT | 需要开发者手动赋值 |
| ASSIGN_ID | MP分配ID,Long、Integer、String |
| ASSIGN_UUID | 分配UUID,Strinig |
①.测试NONE(默认):
@Data //自动帮你生成getset方法
@TableName(value = "user")
public class User {
@TableId
private Long id;
@TableField(value = "name")
private String title;
private Integer age;
}
===================================================================================================================
@Test
void save(){
User user = new User();
user.setTitle("小明");
user.setAge(78);
mapper.insert(user);
}
如果出现错误:查看数据库表的id字段,如果是int,改为bigint即可解决。
结果:
②.测试INPUT:如果开发者没有手动赋值,则数据库通过自增的方式给主键赋值。
@TableId(type = IdType.INPUT)
private Long id;
结果
==> Preparing: INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )
==> Parameters: null, 小明(String), 78(Integer)
③.Auto:默认就是数据库自增,开发者无需赋值。
④.ASSIGN_ID:自动赋值,雪花算法
⑤.ASSIGN_UUID:主键的数据类型必须是string类型,才能自动生成uuid进行赋值。
3.@TableField:映射非主键字段,value映射字段名 ,exist表示是否为数据库字段false,如果实体类中的成员变量在数据库中没有对应的字段,则可以使用exist,VO、DTO ; select 表示是否查询该字段 ;
fill 表示是否自动填充,将对象存入数据库的时候,由mybatis plus 自动给某些字段赋值。例如 create_time;
1.给表添加 create_time字段
@Data //自动帮你生成getset方法
@TableName(value = "user")
public class User {
@TableId(type = IdType.INPUT)
private Long id;
// @TableId(value = "id")
// private Integer num;
// private String name;
@TableField(value = "name")
private String title;
private Integer age;
@TableField(exist = false) //数据库不查询
private String gender;
@TableField(fill = FieldFill.INSERT) //第一次的时间
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) //
private Date updateTime;
}
=====================================================================================
//创建自动填充处理器
package com.zsj.mybatisplus.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author zsj
* @create 2023-02-21 23:11
*/
@Component
public class MyMateObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
========================================================================
//测试
@Test
void save(){
User user = new User();
user.setTitle("c罗");
user.setAge(23);
mapper.insert(user);
System.out.println(user);
}
@Test
void update(){
User user = mapper.selectById(5);
user.setTitle("梅西");
mapper.updateById(user);
}
}
3.@Version:
标记乐观锁:通过version字段来包装数据的安全性,当修改数据的时候会以version作为条件,当条件成立的时候才会修改成功。
演示:
1.数据库加version字段,默认值为1
2.实体类添加version成员变量,并添加@Version
@Version
private Integer version;
3.注册配置类
//乐观锁:主要做修改操作
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
4.测试
@Test
void update(){
User user = mapper.selectById(5);
user.setTitle("乐观");
mapper.updateById(user);
}
5.结果
4.EnumValue
通用枚举类注解,将数据库字段映射成实体类的枚举类型成员变量
演示:
1.数据库加字段
2.枚举类
package com.zsj.mybatisplus.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
/**
* @author zsj
* @create 2023-02-22 0:08
*/
//枚举类
public enum StatusEnum {
WORK(1,"上班"),
REST(0,"休息");
StatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
@EnumValue
private Integer code;
private String msg;
}
3.实体类
private StatusEnum status;
4.application.yml
type-enums-package: com.zsj.mybatisplus.enums
5.运行
5.@TableLogic:映射逻辑删除(不是真正的删掉)
演示
1.数据库添加字段:0表示未删除,
2.实体类
@TableLogic
private Integer deleted;
3.application.yml
global-config:
db-config:
logic-not-delete-value: 0
logic-delete-value: 1
4.测试
@Test
void delete(){
mapper.deleteById(1);
}
5.结果
6.查询:没有了id=1
增删改查功能:
查询
@Test
void select(){
// 不加任何条件全部查询
// -------- mapper.selectList(null);
/*
结果
Columns: id, title, age, create_time, update_time, version, status, deleted
<== Row: 2, 李四, 24, null, null, 1, 1, 0
<== Row: 3, 王五, 33, null, null, 1, 1, 0
<== Row: 5, 乐观, 23, 2023-02-21 23:27:34, 2023-02-21 23:57:34, 2, 0, 0
*/
//用Wrapper 查询 一个条件
/* QueryWrapper Wrapper =new QueryWrapper<>();
Wrapper.eq("name","李四");
mapper.selectList(Wrapper);*/
/* <== Columns: id, title, age, create_time, update_time, version, status, deleted
<== Row: 2, 李四, 24, null, null, 1, 1, 0
<== Total: 1*/
// 用Wrapper 多条件查询
QueryWrapper Wrapper =new QueryWrapper<>();
Map<String,Object> map = new HashMap<>();
map.put("name","李四");
map.put("age",24);
Wrapper.allEq(map);
// 年龄小于20岁的
Wrapper.lt("age",20);
//年龄大于20
Wrapper.gt("age",20);
//年龄不等于20
Wrapper.ne("age",20);
//年龄大于等于20
Wrapper.ge("age",20);
//模糊查询 :名字里带李的
Wrapper.like("name","李");
//模糊查询 :名字结尾李的 “%李”
Wrapper.likeLeft("name","李");
//insql 嵌套查询
Wrapper.inSql("id","select id from user where id<10");
// 排序 按年龄升序
Wrapper.orderByAsc("age");
Wrapper.having("id>8"); //在年龄升序的情况下展示id>8的;
}
@Test
void select(){
// 按id查
mapper.selectById(7);
// 多个id
mapper.selectBatchIds(Arrays.asList(1,2,3)).forEach(System.out::println);
// 用map 只能做等值判断,逻辑判断需要使用 Wrapper 来处理
Map<String,Object> map = new HashMap<>();
map.put("id",3);
mapper.selectByMap(map).forEach(System.out::println);
//查id大于1的记录条数
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.gt("id",1);
mapper.selectCount(wrapper);
// 将查询的结果封装到map中
mapper.selectMaps(wrapper).forEach(System.out::println);
System.out.println("------------------------------");
//分页查询
Page<User> page = new Page<>(1,2);
Page<User> result = mapper.selectPage(page,null);
result.getSize(); //每页几条
result.getTotal(); //总条数
result.getRecords().forEach(System.out::println);
//
mapper.selectObjs(null).forEach(System.out::println);
// 只查询一条
mapper.selectOne(null); //报错
}
添加
@Test
void save(){
User user = new User();
user.setTitle("c罗");
user.setAge(23);
mapper.insert(user);
System.out.println(user);
}
删除
@Test
void delete(){
mapper.deleteById(1);
// 删除两个
mapper.deleteBatchIds(Arrays.asList(1,2));
//删除年龄为14的
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("age",14);
mapper.delete(wrapper);
Map<String,Object> map = new HashMap<>();
map.put("id",10);
mapper.deleteByMap(map);
}
修改
@Test
void update(){
User user = mapper.selectById(5);
user.setTitle("乐观");
mapper.updateById(user);
//追加
User user2 = mapper.selectById(5);
user.setTitle("乐观");
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("age",22);
mapper.update(user2,wrapper);
自定义sql,多表关联
1.新建一个数据库
2.实体类
package com.zsj.mybatisplus.entity;
import lombok.Data;
/**
* @author zsj
* @create 2023-02-21 21:33
*/
@Data
public class ProductVO {
private Integer category;
private Integer count;
private String description;
private Integer userId;
private String userName;
}
3.mapper配置
public interface UserMapper extends BaseMapper<User> {
@Select("SELECT p.*,u.name userName FROM product p,USER u WHERE p.user_id = u.id AND u.id = #{id}")
List<ProductVO> productList(Integer id);
}
4.测试
@Test
void product(){
mapper.productList(2);
}
5.结果
MyBatis Plus 自动生成
根据数据表自动生成实体类,Mapper,Service,ServiceImpl,Controller
1.pom.xml导入MyBatis Plus Generator
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
velocity(默认),Freemarker,Beetl;
2.main:生成的主要代码
package com.zsj.mybatisplus;
import com.baomidou.mybatisplus.annotation.DbType;
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;
/**
* @author zsj
* @create 2023-02-22 13:24
*/
public class Main {
public static void main(String[] args) {
// 创建generator对象
AutoGenerator autoGenerator = new AutoGenerator();
// 数据源
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL);
dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8");
dataSourceConfig.setUsername("root");
dataSourceConfig.setPassword("root");
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
autoGenerator.setDataSource(dataSourceConfig);
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
// System.getProperty("user.dir") ==拿到工程的绝对路径
globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
globalConfig.setServiceName("%sService"); //生成前面没有i
globalConfig.setOpen(false); //不会自动打开文件夹
globalConfig.setAuthor("zsj");
autoGenerator.setGlobalConfig(globalConfig);
// 包信息
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.zsj.mybatisplus"); //父包
packageConfig.setModuleName("generator"); //新创建一个包
packageConfig.setController("controller");
packageConfig.setService("service");
packageConfig.setServiceImpl("service.impl");
packageConfig.setMapper("mapper");
packageConfig.setEntity("entity");
autoGenerator.setPackageInfo(packageConfig);
// 配置策略
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setEntityLombokModel(true);//lombok
strategyConfig.setInclude("表名");//只生成某个表
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel); //下划线转驼峰
autoGenerator.setStrategy(strategyConfig);
autoGenerator.execute(); //执行
}
}