【MybatisPlus】最全面的MybatisPlus通关教程

news2024/12/22 20:25:51

前言

在这里插入图片描述

本文为最全面的MybatisPlus通关教程相关介绍,下边将对MyBatisPlus概述MyBatisPlus快速入门CRUD扩展(包括:插入操作主键生成策略更新操作自动填充乐观锁查询操作分页查询删除操作逻辑删除性能分析插件条件构造器代码自动生成器)等进行详尽介绍~

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)


目录

文章标题

  • 前言
  • 目录
  • 一、MyBatisPlus概述
  • 二、MyBatisPlus快速入门
  • 三、CRUD扩展
    • 1️⃣插入操作
    • 2️⃣主键生成策略
    • 3️⃣更新操作
    • 4️⃣自动填充
    • 5️⃣乐观锁
    • 6️⃣查询操作
    • 7️⃣分页查询
    • 8️⃣删除操作
    • 9️⃣逻辑删除
    • 🔟性能分析插件
    • 1️⃣1️⃣条件构造器
    • 1️⃣2️⃣代码自动生成器
  • 后记

在这里插入图片描述

一、MyBatisPlus概述

需要MyBatisPlus前需要具备的基础: MyBatis、Spring、SpringMVC

为什么要学习MyBatisPlus呢? MyBatisPlus可以节省我们大量工作时间,所有的CRUD代码它都可以自动化完成! MyBatisPlus 本来就是简化 JDBC 操作的!

与MyBatisPlus类似的其它工具: JPA 、 tk-mapper

MyBatisPlus官网: https://baomidou.com/
在这里插入图片描述

MyBatisPlus特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作, BaseMapper
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD操作,更有强大的条件构造器,满足各类使用需求, 以后简单的CRUD操作,它不用自己编写 了!
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配 置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller层代码,支持模板引擎,更有超多自定义配置等您来使用(自动帮你生成代码)
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同 于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢 查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、MyBatisPlus快速入门

准备:

  • 拥有 Java 开发环境以及相应 IDE
  • 熟悉 Spring Boot
  • 熟悉 Maven

🍀(1)创建数据库表

现有一张 User 表,其表结构如下:

idnameageemail
1Jone18test1@baomidou.com
2Jack20test2@baomidou.com
3Tom28test3@baomidou.com
4Sandy21test4@baomidou.com
5Billie24test5@baomidou.com

其对应的数据库 Schema 脚本如下:

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)
);

其对应的数据库 Data 脚本如下:

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');

🍀(2)初始化工程

创建一个空的 Spring Boot 工程

🍀(3)添加依赖

<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- mybatis-plus -->
<!-- mybatis-plus 是自己开发,并非官方的! -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>

说明:使用 mybatis-plus 可以帮助我们节省大量的代码,尽量不要同时导入 mybatis 和 mybatis-plus!

🍀(4)连接数据库

这一步和 mybatis的相关操作相同!

# mysql 5 驱动不同 com.mysql.jdbc.Driver
# mysql 8 驱动不同com.mysql.cj.jdbc.Driver、需要增加时区的配置
serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?
useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

🍀(5)连接mybatis,配置mapper.xml文件

采用传统的方式:pojo-dao-service-controller

🍀(6)编码

编写实体类 User.java(此处使用了 Lombok (opens new window)简化代码):

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

编写 Mapper 包下的 UserMapper接口:

public interface UserMapper extends BaseMapper<User> {

}

🍀(7)编写测试类,进行功能测试

@SpringBootTest
public class SampleTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        Assert.assertEquals(5, userList.size());
        userList.forEach(System.out::println);
    }

}

控制台输出:

User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)

三、CRUD扩展

1️⃣插入操作

Insert 插入:

// 测试插入
@Test
public void testInsert(){
User user = new User();
user.setName("小新要变强");
user.setAge(22);
user.setEmail("1518313516@qq.com");
int result = userMapper.insert(user); // 帮我们自动生成id
System.out.println(result); // 受影响的行数
System.out.println(user); // 发现,id会自动回填
}

数据库插入的id的默认值为:全局的唯一id

2️⃣主键生成策略

🍀默认 ID_WORKER 全局唯一id

分布式系统唯一ID生成方案汇总,参考:https://www.cnblogs.com/haoxinyue/p/5208136.html

雪花算法:

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为
毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味
着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯
一!

🍀主键自增

我们需要配置主键自增:

// 测试插入
@Test
public void testInsert(){
User user = new User();
user.setName("小新要变强");
user.setAge(22);
user.setEmail("1518313516@qq.com");
int result = userMapper.insert(user); // 帮我们自动生成id
System.out.println(result); // 受影响的行数
System.out.println(user); // 发现,id会自动回填
}
  • (1)实体类字段上 @TableId(type = IdType.AUTO)
  • (2)数据库字段一定要是自增!
  • (3)再次测试插入即可!
    在这里插入图片描述

🍀其余的源码解释

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

3️⃣更新操作

// 测试更新
@Test
public void testUpdate(){
User user = new User();
// 通过条件自动拼接动态sql
user.setId(2L);
user.setName("小新一直很强");
user.setAge(23);
// 注意:updateById 但是参数是一个 对象!
int i = userMapper.updateById(user);
System.out.println(i);
}

4️⃣自动填充

创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!

阿里巴巴开发手册中指出:所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!

🍀方式一:数据库级别(工作中不允许你修改数据库)

  • (1)在表中新增字段 create_time, update_time
    在这里插入图片描述

  • (2)再次测试插入方法,我们需要先把实体类同步!

private Date createTime;
private Date updateTime;
  • (3)再次更新查看结果即可

🍀方式二:代码级别

  • (1)删除数据库的默认值、更新操作!

在这里插入图片描述

  • (2)实体类字段属性上需要增加注解
// 字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
  • (3)编写处理器来处理这个注解即可!
package com.wang.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Slf4j
@Component // 一定不要忘记把处理器加到IOC容器中!
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill.....");
// setFieldValByName(String fieldName, Object fieldVal, MetaObject
metaObject
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);
}
}
  • (4)测试插入
  • (5)测试更新、观察时间即可!

5️⃣乐观锁

  • 乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题, 再次更新值测试
  • 悲观锁: 故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

我们这里主要讲解 乐观锁机制!

乐观锁实现方式:

  • 取出记录时,获取当前 version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
乐观锁:1、先查询,获得版本号 version = 1
-- A
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1
-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1

🍀测试一下MP的乐观锁插件

  • (1)给数据库中增加version字段!
  • (2)我们实体类加对应的字段
@Version //乐观锁Version注解
private Integer version;
  • (3)注册组件
// 扫描我们的 mapper 文件夹
@MapperScan("com.wang.mapper")
@EnableTransactionManagement
@Configuration // 配置类
public class MyBatisPlusConfig {
// 注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
  • (4)测试一下
// 测试乐观锁成功!
@Test
public void testOptimisticLocker(){
// 1、查询用户信息
User user = userMapper.selectById(1L);
// 2、修改用户信息
user.setName("小新要不断变强");
user.setEmail("1111111111@qq.com");
// 3、执行更新操作
userMapper.updateById(user);
}
// 测试乐观锁失败!多线程下
@Test
public void testOptimisticLocker2(){
// 线程 1
User user = userMapper.selectById(1L);
user.setName("小新要不断变强111");
user.setEmail("1111111111@qq.com");
// 模拟另外一个线程执行了插队操作
User user2 = userMapper.selectById(1L);
user2.setName("小新要不断变强222");
user2.setEmail("222222222@qq.com");
userMapper.updateById(user2);
// 自旋锁来多次尝试提交!
userMapper.updateById(user); // 如果没有乐观锁就会覆盖插队线程的值!
}

6️⃣查询操作

// 测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
// 测试批量查询!
@Test
public void testSelectByBatchId(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
// 按条件查询之一使用map操作
@Test
public void testSelectByBatchIds(){
HashMap<String, Object> map = new HashMap<>();
// 自定义要查询
map.put("name","小新要变强");
map.put("age",22);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}

7️⃣分页查询

  • 分页在网站使用的十分之多!
  • 原始使用 limit 进行分页
  • 还有pageHelper 第三方插件
  • MP 其实也内置了分页插件!

🍀如何使用

(1)配置拦截器组件即可

// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}

(2)直接使用Page对象即可!

// 测试分页查询
@Test
public void testPage(){
// 参数一:当前页
// 参数二:页面大小
// 使用了分页插件之后,所有的分页操作也变得简单的!
Page<User> page = new Page<>(2,5);
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}

8️⃣删除操作

根据 id 删除记录:

// 测试删除
@Test
public void testDeleteById(){
userMapper.deleteById(1240620674645544965L);
}
// 通过id批量删除
@Test
public void testDeleteBatchId(){
userMapper.deleteBatchIds(Arrays.asList(1240620674645544961L,124062067464554496
2L));
}
// 通过map删除
@Test
public void testDeleteMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","小新要变强");
userMapper.deleteByMap(map);
}

9️⃣逻辑删除

  • 物理删除 : 从数据库中直接移除
  • 逻辑删除 : 再数据库中没有被移除,而是通过一个变量来让他失效! deleted = 0 => deleted = 1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

测试一下:

  • (1)在数据表中增加一个 deleted 字段

在这里插入图片描述

  • (2)实体类中增加属性
@TableLogic //逻辑删除
private Integer deleted;
  • (3)配置
// 逻辑删除组件!
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
  • (4)测试一下删除
// 测试删除
@Test
public void testDeleteById(){
userMapper.deleteById(1240620674645544965L);
}
// 通过id批量删除
@Test
public void testDeleteBatchId(){
userMapper.deleteBatchIds(Arrays.asList(1240620674645544961L,124062067464554496
2L));
}
// 通过map删除
@Test
public void testDeleteMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","小新要变强");
userMapper.deleteByMap(map);
}

结果发现:记录依旧在数据库,但是值确已经变化了!

🔟性能分析插件

我们在平时的开发中,会遇到一些慢sql。测试! druid,

作用:性能分析拦截器,用于输出每条 SQL 语句及其执行时间

MP也提供性能分析插件,如果超过这个时间就停止运行!

  • (1)导入插件
/**
* SQL执行效率插件
*/
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启,保证我们的效率
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new
PerformanceInterceptor();
performanceInterceptor.setMaxTime(100); // ms设置sql执行的最大时间,如果超过了则不
执行
performanceInterceptor.setFormat(true); // 是否格式化代码
return performanceInterceptor;
}

记住,要在SpringBoot中配置环境为dev或者 test 环境!

(2)测试使用

@Test
void contextLoads() {
// 参数是一个 Wrapper ,条件构造器,这里我们先不用 null
// 查询全部用户
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}

只要超过了规定的时间就会抛出异常!

使用性能分析插件,可以帮助我们提高效率!

1️⃣1️⃣条件构造器

我们写一些复杂的sql就可以使用它来替代!

🍀(1)测试一,记住查看输出的SQL进行分析

@Test
void contextLoads() {
// 查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于12
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",12);
userMapper.selectList(wrapper).forEach(System.out::println); // 和我们刚才学习
的map对比一下
}

🍀(2)测试二,记住查看输出的SQL进行分析

@Test
void test2(){
// 查询名字狂神说
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","小新要变强");
User user = userMapper.selectOne(wrapper); // 查询一个数据,出现多个结果使用List或者 Map
System.out.println(user);
}

🍀(3)测试三,记住查看输出的SQL进行分析

@Test
void test3(){
// 查询年龄在 20 ~ 30 岁之间的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",20,30); // 区间
Integer count = userMapper.selectCount(wrapper);// 查询结果数
System.out.println(count);
}

🍀(4)测试四,记住查看输出的SQL进行分析

// 模糊查询
@Test
void test4(){
// 查询年龄在 20 ~ 30 岁之间的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 左和右 t%
wrapper
.notLike("name","e")
.likeRight("email","t");
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}

🍀(5)测试五

// 模糊查询
@Test
void test5(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
// id 在子查询中查出来
wrapper.inSql("id","select id from user where id<3");
List<Object> objects = userMapper.selectObjs(wrapper);
objects.forEach(System.out::println);
}

🍀(6)测试六

//测试六
@Test
void test6(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 通过id进行排序
wrapper.orderByAsc("id");
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

1️⃣2️⃣代码自动生成器

dao、pojo、service、controller都给我自己去编写完成!

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

测试:

package com.kuang;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
// 代码自动生成器
public class KuangCode {

public static void main(String[] args) {
    // 需要构建一个 代码自动生成器 对象
    AutoGenerator mpg = new AutoGenerator();
    // 配置策略
    // 1、全局配置
    GlobalConfig gc = new GlobalConfig();
    String projectPath = System.getProperty("user.dir");
    gc.setOutputDir(projectPath+"/src/main/java");
    gc.setAuthor("狂神说");
    gc.setOpen(false);
    gc.setFileOverride(false); // 是否覆盖
    gc.setServiceName("%sService"); // 去Service的I前缀
    gc.setIdType(IdType.ID_WORKER);
    gc.setDateType(DateType.ONLY_DATE);
    gc.setSwagger2(true);
    mpg.setGlobalConfig(gc);
    //2、设置数据源
    DataSourceConfig dsc = new DataSourceConfig();
    dsc.setUrl("jdbc:mysql://localhost:3306/kuang_community?
        useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
    dsc.setDriverName("com.mysql.cj.jdbc.Driver");
    dsc.setUsername("root");
    dsc.setPassword("123456");
    dsc.setDbType(DbType.MYSQL);
    mpg.setDataSource(dsc);
    //3、包的配置
    PackageConfig pc = new PackageConfig();
    pc.setModuleName("blog");
    pc.setParent("com.kuang");
    pc.setEntity("entity");
    pc.setMapper("mapper");
    pc.setService("service");
    pc.setController("controller");
    mpg.setPackageInfo(pc);
    //4、策略配置
    StrategyConfig strategy = new StrategyConfig();
    strategy.setInclude("blog_tags","course","links","sys_settings","user_record","user_say");    // 设置要映射的表名
    strategy.setNaming(NamingStrategy.underline_to_camel);
    strategy.setColumnNaming(NamingStrategy.underline_to_camel);
    strategy.setEntityLombokModel(true); // 自动lombok;
    strategy.setLogicDeleteFieldName("deleted");
    // 自动填充配置
    TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
    TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
    ArrayList<TableFill> tableFills = new ArrayList<>();
    tableFills.add(gmtCreate);
    tableFills.add(gmtModified);
    strategy.setTableFillList(tableFills);
    // 乐观锁
    strategy.setVersionFieldName("version");
    strategy.setRestControllerStyle(true);
    strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2
    mpg.setStrategy(strategy);
    mpg.execute(); //执行
}
}

后记

在这里插入图片描述

👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/100060.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我学python的那段日子(四)选择结构和循环结构

1.选择结构 总所周知&#xff0c;Java里面也有选择结构&#xff0c;分别是if单分支选择结构、if-else结构多重if结构和switch结构&#xff0c;同样的&#xff0c;Python里也有选择结构&#xff0c;分别是是if单分支选择结构、if-else结构多重if结构。 1.1 if选择结果 ​ if选…

Servlet生命周期和线程安全

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;JAVA开发者…

CANoe-是如何对ECU和网络进行测试的

CANoe工具是汽车仿真测试开发中使用最广泛的工具 Test Module/Test Unit 除了仿真模块和分析模块,CANoe还引入了另一个组件进行测试:Test Module(测试模块)和Test Unit(测试单元) test module调用的是capl脚本、.net脚本或xml文件,而test unit用的是vTESTstudio插件 实…

12.18

一.加强练习promise 1.fs模块 const fs require(fs) const p new Promise((resolve,reject) > {fs.readFile(./resource/context.txt, (err,data) > {if (err) reject(err)resolve(data)}) }) p.then((value) > {console.log(value.toString()) }, (reason) > …

前端炫酷特效合集

我们经常在抖音上看到一些前端很酷的特效&#xff0c;诸如&#xff1a;快叫你学编程的朋友给你写一个圣诞树&#xff0c;看着是不是很酷炫呢&#xff1f;其实只要有源码&#xff0c;你也可以拥有哦&#xff01; 跟大家分享多款前端特效源码&#xff0c;需要的朋友可以去在这里…

Java : 多态,包装类的面试题:

Java &#xff1a; 多态&#xff0c;包装类的面试题&#xff1a; 每博一文案 有人说&#xff1a;小孩子才会仰天大哭&#xff0c;成年人的世界早就调成了静音模式&#xff0c;连崩溃也很懂事。 一路走来&#xff0c;我们一边受伤&#xff0c;也一边变得更坚强&#xff0c;慢慢…

数据库原理及MySQL应用 | 日志管理

数据库系统管理维护阶段需要通过日志对数据库的性能进行监督、分析和改进。 日志是数据库系统的重要组成部分&#xff0c;记录了数据库的运行状态、数据的变更历史、错误信息及用户操作等信息。在日常管理中&#xff0c;数据库管理员可通过日志监控数据库的运行状态、优化数据库…

国内外文献镜像网站

一、常用的国内外文献镜像网站 维普网&#xff1a;http://lib.cqvip.com/ idata&#xff1a;https://www.cn-ki.net/ 独秀&#xff1a;https://www.duxiu.com/ 中国知网&#xff1a;https://www.cnki.net/ 龙源期刊网&#xff1a;http://www.qikan.com.cn/ 万方数据&#xff1…

计算机毕业设计HTML+CSS+JavaScript仿大型购物商城(1页)

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

毕业设计 单片机GPS定位位置记录系统 - 物联网 嵌入式 stm32

文章目录0 前言1 简介2 主要器件3 实现效果4 硬件设计概述硬件模块的连接**AB32VG1主控MCU**5 软件说明6 部分核心代码7 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩…

基于asp.net人力资源管理系统-计算机毕业设计

基于asp.net的人力资源管理的内容和人事管理日常管理所遇到的问题&#xff0c;整个系统可以分为下面几个子模块&#xff0c;分别为员工档案信息管理、工资信息管理、考勤信息管理、消息信息管理、账号信息管理等几个大的功能模块,开发环境:Visual studio,sqlserver数据库.资料有…

非零基础自学Golang 第9章 结构体 9.4 初始化结构体

非零基础自学Golang 文章目录非零基础自学Golang第9章 结构体9.4 初始化结构体9.4.1 键值对格式初始化9.4.2 列表格式初始化第9章 结构体 9.4 初始化结构体 上一小节我们讲解了在结构体实例化后&#xff0c;再使用“.”的方式对成员变量进行赋值。另外&#xff0c;我们还可以…

Junit5 架构、新特性及基本使用(常用注解与套件执行)

什么是 Junit5&#xff0c;在 Junit5 的官方介绍文档中这写到&#xff1a; Junit5 由JUnit Platform JUnit Jupiter JUnit Vintage3部分构成&#xff0c;借用 IBM Developer 的一张图来说明 JUnit 5 的架构&#xff1a; JUnit Platform: JUnit Jupiter: JUnit Vintage: 嵌套单…

Spring Cloud 总结 - 调用远程服务的三种方式及原理分析

一个简单的微服务架构图 本文设计的 Spring Cloud 版本以及用到的 Spring Cloud 组件 Spring Cloud Hoxton.SR5eurekafeignribbon 后面的内容都将围绕上面的图来分析. 调用远程服务的三种方式 在 Spring Cloud 服务架构中, 一个服务可能部署多个实例, 通常情况下, 这个时候…

好玩的网站安利

好玩的网站安利 1、EGOUZ https://www.egouz.com/ 授人以鱼不如授人以渔&#xff0c;先给大家分享两个可以找国外优质网站的地方。EGOUZ是一个高质量的导航站&#xff0c;内容主要是外国网站&#xff0c;并且做了很详细的分类&#xff0c;网站资源非常丰富。 EGOUZ按照国家分…

50450-80-1,Ala-Ala-Ala-对硝基苯胺

AAA-pNA, chromogenic substrate for porcine pancreatic elastase and for astacin, a crayfish zinc-endopeptidase.3a - pna&#xff0c;猪胰腺弹性酶和阿斯塔星的显色底物&#xff0c;阿斯塔星是一种小龙虾锌内肽酶。 编号: 163840中文名称: 三肽Pancreatic elastase subst…

1573_AURIX_TC275_SCU中的急停功能以及overlay

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 急停功能是不需要软件进行干预的&#xff0c;至少&#xff0c;这个事件的动作触发是不需要软件进行干预的。急停事件的触发因素&#xff1a;外部的输入事件、SMU的警报信息。外部的输入事件…

概率论 ‖ Machine Learning必备知识

概率论&#xff01;Machine Learning必备知识 文章目录概率论&#xff01;Machine Learning必备知识1 什么是概率1.1 最简单的例子1.2 概率论与数理统计的关系2 大数定律和中心极限定理2.1 大数定律是什么&#xff1f;2.2 代码直观理解大数定律2.3 中心极限定理2.4 大数定律和中…

Java基础开发之编译异常和运行异常

一、getProperties()方法 1.System类提供一个getProperties()方法用来**当前系统的全部属性&#xff0c;它会返回一个Properties对象&#xff0c;也封装了系统的全部属性&#xff0c;这些属性的存在是以键值对的形式。 2.getProperties()方法使用例子&#xff1a; public cl…

《数字电子技术》笔记

《数字电子技术》笔记绪论第一章 信息和编码第二章 逻辑代数第三章 门电路第四章 组合电路的逻辑与分析第五章 触发器第七章 可编程逻辑器件绪论 什么是电子技术&#xff1f;是研究电子器件及电子器件应用的学科。EDA&#xff1a;Electronic Design Automation电子电路用处&am…