IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> MybatisPlus学习笔记 -> 正文阅读

[Java知识库]MybatisPlus学习笔记

MybatisPlus学习笔记

一、简单测试MybatisPlus

1_1.导入数据库脚本

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

1_2.创建一个springboot项目并导入依赖

不用jdbc???

    <dependencies>
<!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
<!--        Mybatis-plus是自己开发的-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

        <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>
    </dependencies>

1_3.application连接数据库

spring.datasource.username=root
spring.datasource.password=3333
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisPlus?useSSl=true&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8

1_4.建立pojo类(和数据库列名相一致)

-------------pojo/user

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
	private Long id;
	private String name;
	private Integer age;
	private String email;
}

1_5.在main函数处开启mapper接口扫描

扫描我们的mapper文件夹,相当于以往在xml文件中绑定mapper接口和xml文件

@MapperScan("com.junjun.mapper")//扫描到我们的mapper文件夹
@SpringBootApplication
public class MybatisPlusApplication {
	public static void main(String[] args) {
		SpringApplication.run(MybatisPlusApplication.class, args);
	}
}

1_6.创建UserMapper接口

---------mapper/UserMapper

1.在对应的Mapper接口上面继承BaseMapper类,这样所有的crud已经编写完成了,而不用再写xml文档来实现UserMapper接口

@Repository//代表是持久层的bean
public interface UserMapper extends BaseMapper<User> {
}

1_7.测试类

@SpringBootTest
class MybatisPlusApplicationTests {
	@Autowired
	private UserMapper userMapper;

	@Test//查找测试
	void testSelectAll() {
		//查询所有的用户(传入条件构造器Wrapper)
		List<User> users = userMapper.selectList(null);
		users.forEach(System.out::println);//lamda表达式
		//插入功能实现
	}
	@Test//插入测试
	public void testInsert(){
		User user=new User();
		user.setName("junjun");
		user.setAge(12);
		user.setEmail("3124992817@qq.com");
		//会自动生成id
		//Parameters: 1440230999140052994(Long), junjun(String), 12(Integer), 3124992817@qq.com(String)
		//1440230999140052994是什么?主键的生成策略:uuid,自增id,snowflake雪花算法。
		int insert = userMapper.insert(user);
		System.out.println(insert);
	}
		@Test//更新测试
	public void testUpdate(){
		User user=new User();
		user.setId(1440230999140052997L);
		user.setName("junjun4");
		user.setAge(16);
		user.setEmail("3124992817@qq.com");
		int insert = userMapper.updateById(user);//传入参数是一个对象而不是字符串
	}
}

二、主键生成策略

1.Auto:1.该属性在数据库中是自增,2.使用@TableId(type = IdType.AUTO)注解
2.input:可以手动输入id,但是如果不输入id,当数据库存在自增时,就会自增,否则为空(当id为主键时,主键为空就会报错)。

public enum IdType {
    AUTO(0),//自增
    NONE(1),//未设置主键
    INPUT(2),//手动输入
    ID_WORKER(3),//默认的全球唯一id
    UUID(4),//使用uuid(全球唯一id)
    ID_WORKER_STR(5);//ID_WORKER的字符串表示法
    private int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}

2_1.实现自增

只需要修改pojo和数据库就行了
-----------mysql数据库

alter table user change id id bigint  auto_increment;

----------pojo/User

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
	@TableId(type = IdType.AUTO)//1.数据库中是自增策略,2.使用@TableId(type = IdType.AUTO)注解
	private Long id;
	private String name;
	private Integer age;
	private String email;
}

三、自动填充

3_1 数据库级别自动填充

1.当创建这两列时会(通过默认值)自动填充内容create_time和update_time。且当插入数据时也会通过默认值自动填充

3_1_1数据库添加列并配置默认值

alter table user add create_time datetime default current_timestamp;
alter table user add update_time datetime default current_timestamp;

3_1_2 java插入值(不输入time会自动填充)

	@Test
	public void testInsert(){
		User user=new User();
		user.setName("junjun100");
		user.setAge(12);
		user.setEmail("3124992817@qq.com");
		int insert = userMapper.insert(user);
		System.out.println(insert);
	}

??

3_1 代码级别的自动填充

3_1_1在pojo需要自动填充的属性上添加注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
	@TableId(type = IdType.AUTO)//1.数据库中是自增策略,2.使用@TableId(type = IdType.AUTO)注解
	private Long id;
	private String name;
	private Integer age;
	private String email;
	@TableField(fill = FieldFill.INSERT)//在更新时会自动填充默认值
	private Date createTime;
	@TableField(fill = FieldFill.INSERT_UPDATE)//在插入和更新时会自动填充默认值
	private Date updateTime;
}

3_1_2配置填充策略

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
	@Override//插入时填充策略
	public void insertFill(MetaObject metaObject) {
		log.info("start insert fill ......");
		this.setFieldValByName("createTime",new Date(),metaObject);
		this.setFieldValByName("updateTime",new Date(),metaObject);
	}
	@Override//更新时填充策略
	public void updateFill(MetaObject metaObject) {
		log.info("start update fill ......");
		this.setFieldValByName("updateTime",new Date(),metaObject);
	}
}

3_1_3测试

	@Test
	public void testInsert(){
		User user=new User();
		user.setName("junjun100");
		user.setAge(12);
		user.setEmail("3124992817@qq.com");
		int insert = userMapper.insert(user);
		System.out.println(insert);
	}

-----------结果如下

??

四、乐观锁和悲观锁(多线程防止出现安全问题)

4_1 乐观锁???没学懂

总是默认不出现问题,当出现问题(上锁失败)时就更新

4_1_1 给数据库添加version字段

SELECT * FROM mybatisplus.user;

4_1_2配置乐观锁的插件

@MapperScan("com.junjun.mapper")
@EnableTransactionManagement
@Configuration//配置类
public class MybatisPlusConfig {
	//注册乐观锁插件
	@Bean
	public OptimisticLockerInterceptor optimisticLockerInterceptor(){
		return new OptimisticLockerInterceptor();
	}
}

4_1_3给user类添加Version字段和@Version注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
	@TableId(type = IdType.AUTO)//1.数据库中是自增策略,2.使用@TableId(type = IdType.AUTO)注解
	private Long id;
	private String name;
	private Integer age;
	private String email;
	@TableField(fill = FieldFill.INSERT)//在更新时会自动填充默认值
	private Date createTime;
	@TableField(fill = FieldFill.INSERT_UPDATE)//在插入和更新时会自动填充默认值
	private Date updateTime;
	@Version
	private Integer Version;
}

4_1_4测试

	@Test//测试乐观锁处理单线程
	public void testOptimisticLocker(){
		//1.查询用户信息
		User user=userMapper.selectById(1L);
		//2.修改用户信息
		user.setName("root");
		user.setEmail("111111111@qq.com");
		//3.执行更新操作
		userMapper.updateById(user);
	}
	@Test//模拟乐观锁处理多线程
	public void testOptimisticLocker2(){
		//线程1
		User user1=userMapper.selectById(1L);
		user1.setName("root1111");
		user1.setEmail("111111111@qq.com");
		//线程2
		User user2=userMapper.selectById(1L);
		user2.setName("root2222");
		user2.setEmail("111111111@qq.com");
		//模拟另外一个线程插队操作
		userMapper.updateById(user1);//如果没有乐观锁就会覆盖插队线程的值
		//自旋锁来多次尝试提交!
		userMapper.updateById(user2);//
	}

4_2 悲观锁

总是默认会出现问题,更新时就一定要上锁

五、常用查表

5_1 按数据库中顺序测试批量查询

	@Test//按数据库中顺序测试批量查询
	public void tesSelectByBatchId(){
		List<User> users=userMapper.selectBatchIds(Arrays.asList(1,2,3,7));
		users.forEach(System.out::println);
	}

5_2 条件查询(除了id之外的条件查询)

	@Test//测试条件查询(除了id之外的条件查询)
	public void tesSelectByName(){
		HashMap<String,Object> map=new HashMap<>();
		//自定义查询
		map.put("name","junjun");
		List<User> users=userMapper.selectByMap(map);
		users.forEach(System.out::println);
	}

5_3 分页查询

测试分页查询:1.原生limit 2.pageHelper第三方插件(MP内置了插件)

5_3_1配置拦截器

@Configuration//配置类
public class MybatisPlusConfig {
	@Bean//导入分页插件
	public PaginationInterceptor PaginationInterceptor(){
		return  new PaginationInterceptor();
	}
}

5_3_2直接用page来查询(效率较低)

	@Test//测试分页查询:1.原生limit 2.pageHelper第三方插件(MP内置了插件)
	public void tesPage(){
		Page<User> page=new Page<>(2,5);//参数一是当前页,参数二是页面大小
		userMapper.selectPage(page,null);
		page.getRecords().forEach(System.out::println);
	}

五、常用删表

5_1通过id删除

	@Test//通过id删除
	public void testDeleteById(){
		userMapper.deleteById(1440230999140053005L);
	}

5_2 批量删除

	@Test//批量删除
	public void testDeleteBatchId(){
		userMapper.deleteBatchIds(Arrays.asList(1440230999140053004L,1440230999140052997L));
	}

5_3通过map删除

	@Test//通过map删除
	public void testDeleteMap(){
		HashMap<String,Object> map=new HashMap<>();
		map.put("name","junjun");
		userMapper.deleteByMap(map);
	}

5_4逻辑删除

物理删除:
逻辑删除:数据库中没有移除,但是我们查看不到他(如:回收站原理)

5_4_1在数据库中添加一个delete字段

默认0为未删除,1为已删除

alter table user add deleted int(1) not null default 0;

5_4_2导入逻辑删除插件

@Configuration
public class MybatisPlusConfig {
	//导入逻辑删除插件
	@Bean
	public ISqlInjector sqlInjector(){
		return new LogicSqlInjector();
	}
}

5_4_3使用上述任意删除方式删除

低版本要在application.properties中导入

#mybatis-plus.global-config.db-config.logic-not-delete-value=0
#mybatis-plus.global-config.db-config.logic-delete-value=1

六、附加功能

6_1性能分析插件

用于输出每条sql及其执行的时间

6_1_1导入性能分析插件

@Configuration//配置类
public class MybatisPlusConfig {
	@Bean
	@Profile({"dev","test"})//保证效率,不再开发境下运行
	public PerformanceInterceptor performanceInterceptor(){
		PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
		//在工作中非常常用
		performanceInterceptor.setMaxTime(100);//sql执行的最大时间1ms,超过就不执行
		performanceInterceptor.setFormat(true);//开启格式化支持
		return performanceInterceptor;
	}
}

6_1_2在application.properties开启dev环境

spring.profiles.active=dev

spring.datasource.username=root
spring.datasource.password=3333
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisPlus?useSSl=true&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8
#serverTimezeno=GMT%2B8

#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

6_1_3任意查询测试结果

6_2 条件构造器wrap

在测试函数中使用wrapper来限制复杂条件

@SpringBootTest
public class WrapperTest {
	@Autowired
	private UserMapper userMapper;

	@Test//查询name不为空的用户,并且邮箱不为空的用户,且年龄大于12岁
	void contextLoads1(){
		QueryWrapper<User> wrapper=new QueryWrapper<>();
		wrapper
				.isNotNull("name")
				.isNotNull("email")
				.ge("age",12);//ge是大于号
		userMapper.selectList(wrapper).forEach(System.out::println);
	}
	@Test//查询名字为jack
	void test2(){

		QueryWrapper<User> wrapper= new QueryWrapper<>();
		wrapper.eq("name","jack");//名字等于jack
		System.out.println(userMapper.selectOne(wrapper));//查询一个数据,查询到多个会报错,要用selectList
	}
	@Test	//查询年龄在10-20岁之间的用户
	void test3(){

		QueryWrapper<User> wrapper= new QueryWrapper<>();
		wrapper.between("age",10,20);
		System.out.println(userMapper.selectCount(wrapper));//查询一个数据,查询到多个会报错,要用selectList
	}
	@Test//模糊查询:名字里有j无e的
	void test4(){
		QueryWrapper<User> wrapper= new QueryWrapper<>();
		wrapper//xxx%:以xxx开头和以xxx结尾:%xxx
				.notLike("name","e")
				.like("name","j");
		List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
		maps.forEach(System.out::println);//查询一个数据,查询到多个会报错,要用selectList
	}
	@Test//子查询
	void test5(){
		QueryWrapper<User> wrapper= new QueryWrapper<>();
		wrapper//xxx%:以xxx开头和以xxx结尾:%xxx
				.inSql("id","select id from user where id<3");
		List< Object> objects= userMapper.selectObjs(wrapper);
		objects.forEach(System.out::println);//查询一个数据,查询到多个会报错,要用selectList
	}
	@Test//升序降序
	void test6(){
		QueryWrapper<User> wrapper= new QueryWrapper<>();
		wrapper//xxx%:以xxx开头和以xxx结尾:%xxx
				.orderByDesc("id","name");
		List< Object> objects= userMapper.selectObjs(wrapper);
		objects.forEach(System.out::println);//查询一个数据,查询到多个会报错,要用selectList
	}
}

6_3 代码生成器(根据数据库直接生成java代码)

你已经是个成熟的框架了,是时候学会自己写代码了

6_3_1创建一个数据库并连接数据库

创建项目的数据库

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

6_3_2 导入依赖

    <dependencies>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>

        <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>
    </dependencies>

6_3_3 使用代码生成器生成基本代码

能根据你数据库的内容生成java文件包和代码

//代码自动生成器
public class junCode {
	public static void main(String[] args) {
//		构造代码自动生成器对象
		AutoGenerator mpg=new AutoGenerator();
//		配置策略
		//1.全局配置
		GlobalConfig globalConfig = new GlobalConfig();
		String projectPath=System.getProperty("user.dir");//"user.dir"是指用户当前工作目录(即根目录)
		globalConfig
				.setOutputDir(projectPath+"/src/main/java")
				.setAuthor("君哥")
				.setOpen(false)
				.setFileOverride(true)//是否覆盖
				.setServiceName("%sService")//去掉Service的I前缀
				.setIdType(IdType.ID_WORKER)
				.setDateType(DateType.ONLY_DATE)
				.setSwagger2(true);
		mpg.setGlobalConfig(globalConfig);
		//2.设置数据源
		DataSourceConfig dsc = new DataSourceConfig();
		dsc
				.setUrl("jdbc:mysql://localhost:3306/mybatisPlus?useSSl=true&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8")
				.setDriverName("com.mysql.cj.jdbc.Driver")//这里要和项目一致,不然会因为因为模块不和main程序(MybatisPlusTest02Application.java)在同一级目录而报错
				.setUsername("root")
				.setPassword("3333")
				.setDbType(DbType.MYSQL);
		mpg.setDataSource(dsc);
		//3.配置包名、包位置、包内容
		PackageConfig pc = new PackageConfig();
		pc
				.setParent("com.mybatisplus_test_02")
				.setModuleName("blog")
				.setEntity("entity")
				.setMapper("mapper")
				.setService("service")
				.setController("controler");
		mpg.setPackageInfo(pc);
		//4、策略配置:自动配置时间(会自动添加注解,但需要自己导入依赖)
		StrategyConfig sc = new StrategyConfig();
		TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
		TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT);
		ArrayList<TableFill> tableFills=new ArrayList<>();
		tableFills.add(gmtCreate);
		tableFills.add(gmtModified);
		sc
				.setInclude("user")//设置要映射的表名
				.setNaming(NamingStrategy.underline_to_camel)//包命名支持下划线转驼峰命名法
				.setColumnNaming(NamingStrategy.underline_to_camel)//列命名支持下划线转驼峰命名法
				.setSuperEntityClass("")//你自己的父亲实体,没有就不用设置
				.setEntityLombokModel(true)//不会自动生成setter和getter方法,要women自己调用lombok
				.setLogicDeleteFieldName("deleted")//逻辑删除字段
				.setTableFillList(tableFills)//插入数据策略
				.setVersionFieldName("version")//乐观锁
				.setRestControllerStyle(true);//在url中开启驼峰命名法localhost:8080//hello_id_2
		mpg.setStrategy(sc);
		mpg.execute();//执行
	}
}

6_3_4 在java文件下得到一个文件夹

??

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-24 10:24:23  更:2021-09-24 10:24:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:24:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码