MyBatis-Plus框架学习笔记

news2024/11/15 10:51:54

先赞后看,养成习惯!!!❤️ ❤️ ❤️
文章码字不易,如果喜欢可以关注我哦!
​如果本篇内容对你有所启发,欢迎访问我的个人博客了解更多内容:链接地址

MyBatisPlus

(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在==简化开发、提高效率==

MP的特性:

  • 无侵入:只做增强不做改变,不会对现有工程产生影响
  • 强大的 CRUD 操作:内置通用 Mapper,少量配置即可实现单表CRUD 操作
  • 支持 Lambda:编写查询条件无需担心字段写错
  • 支持主键自动生成
  • 内置分页插件

标准增删查改

分页功能

基础的增删改查就已经学习完了,刚才我们在分析基础开发的时候,有一个分页功能还没有实现,在MP中如何实现分页功能,就是咱们接下来要学习的内容。

分页查询使用的方法是:

IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper)
  • IPage:用来构建分页查询条件
  • Wrapper:用来构建条件查询的条件,目前我们没有可直接传为Null
  • IPage:返回值,你会发现构建分页条件和方法的返回值都是IPage

IPage是一个接口,我们需要找到它的实现类来构建它,具体的实现类,可以进入到IPage类中按ctrl+h,会找到其有一个实现类为Page。

@Test
void testSelectPage(){
    //1 创建IPage分页对象,设置分页参数,1为当前页码,3为每页显示的记录数
    IPage<User> page=new Page<>(1,3);
    //2 执行分页查询
    userDao.selectPage(page,null);
    //3 获取分页结果
    System.out.println("当前页码值:"+page.getCurrent());
    System.out.println("每页显示数:"+page.getSize());
    System.out.println("一共多少页:"+page.getPages());
    System.out.println("一共多少条数据:"+page.getTotal());
    System.out.println("数据:"+page.getRecords());

DQL编程控制

查询相关的操作

增删改查四个操作中,查询是非常重要的也是非常复杂的操作,这块需要我们重点学习下,这节我们主要学习的内容有:

  • 条件查询方式
  • 查询投影
  • 查询条件设定
  • 字段映射与表名映射

条件查询

lt: 小于(

gt:大于(>)

第一种:==QueryWrapper==

第二种:==QueryWrapper的基础上使用lambda==

第三种:==LambdaQueryWrapper==

多条件查询

  • 构建多条件的时候,可以支持链式编程
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 30).gt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);

查询数据库表中,年龄小于10或年龄大于30的数据

    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }

null判定

> 需求:查询数据库表中,根据输入年龄范围来查询符合条件的记录。用户在输入值的时候,

> ​ 如果只输入第一个框,说明要查询大于该年龄的用户

> ​ 如果只输入第二个框,说明要查询小于该年龄的用户

> ​ 如果两个框都输入了,说明要查询年龄在两个范围之间的用户

思考第一个问题:后台如果想接收前端的两个数据,该如何接收?

新建一个模型类,让其继承User类,并在其中添加age2属性,UserQuery在拥有User属性后同时添加了age2属性。

@Data
public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
}
​
@Data
public class UserQuery extends User {
    private Integer age2;
}
@Test
void testGetAll(){
    //模拟页面传递过来的查询数据
    UserQuery uq = new UserQuery();
    uq.setAge(10);
    uq.setAge2(30);
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2());
    lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge());
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
}

查询投影

查询指定字段

@Test
void getWord() {
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
    lqw.select(User::getId, User::getName);
    List<User> list = userDao.selectList(lqw);
    System.out.println(list);
}

select(...)方法用来设置查询的字段列,可以设置多个

聚合查询

  • 聚合与分组查询,无法使用lambda表达式来完成

需求:聚合函数查询,完成count、max、min、avg、sum的使用

count:总记录数

max:最大值

min:最小值

avg:平均值

sum:求和

分组查询

groupBy为分组

  • 聚合与分组查询,无法使用lambda表达式来完成
  • MP只是对MyBatis的增强,如果MP实现不了,我们可以直接在DAO接口中使用MyBatis的方式实现
@Test
void GroupBy(){
    QueryWrapper<User> lqw = new QueryWrapper<User>();
    lqw.select("count(*) as count,age");
    lqw.groupBy("age");
    List<Map<String, Object>> list = userDao.selectMaps(lqw);
    System.out.println(list);
}

[{count=1, age=55}, {count=1, age=45}, {count=1, age=38}, {count=1, age=42}, {count=1, age=37}]

查询条件

MP的查询条件有很多:

  • 范围匹配(> 、 = 、between)
  • 模糊匹配(like)
  • 空判定(null)
  • 包含性匹配(in)
  • 分组(group)
  • 排序(order

等值查询

eq(): 相当于 =

范围查询

  • gt():大于(>)
  • ge():大于等于(>=)
  • lt():小于(
  • lte():小于等于(
  • between():between ? and ?

模糊查询

  • like():前后加百分号,如 %J%
  • likeLeft():前面加百分号,如 %J
  • likeRight():后面加百分号,如 J%

排序查询

@Test
void testGetAll(){
    LambdaQueryWrapper<User> lwq = new LambdaQueryWrapper<>();
    /**
     * condition :条件,返回boolean,
     当condition为true,进行排序,如果为false,则不排序
     * isAsc:是否为升序,true为升序,false为降序
     * columns:需要操作的列
     */
    lwq.orderBy(true,false, User::getId);

    List<User> list = userDao.selectList(lwq);
    System.out.println(list);
}

映射匹配兼容性

问题1:表字段与编码属性设计不同步

当表的列名和模型类的属性名发生不一致,就会导致数据封装不到模型对象,这个时候就需要其中一方做出修改,那如果前提是两边都不能改又该如何解决?

MP给我们提供了一个注解@TableField,使用该注解可以实现模型类属性名和表的列名之间的映射关系

问题2:编码中添加了数据库中未定义的属性

当模型类中多了一个数据库表不存在的字段,就会导致生成的sql语句中在select的时候查询了数据库不存在的字段,程序运行就会报错,错误信息为:

==Unknown column '多出来的字段名称' in 'field list'==

具体的解决方案用到的还是@TableField注解,它有一个属性叫exist,设置该字段是否在数据库表中存在,如果设置为false则不存在,生成sql语句查询的时候,就不会再查询该字段了。

问题3:采用默认查询开放了更多的字段查看权限

查询表中所有的列的数据,就可能把一些敏感数据查询到返回给前端,这个时候我们就需要限制哪些字段默认不要进行查询。解决方案是@TableField注解的一个属性叫select,该属性设置默认是否需要查询该字段的值,true(默认值)表示默认查询该字段,false表示默认不查询该字段。

@TableField

名称

@TableField

类型

==属性注解==

位置

模型类属性定义上方

作用

设置当前属性对应的数据库表中的字段关系

相关属性

value(默认):设置数据库表字段名称 exist:设置属性在数据库表字段中是否存在,默认为true,此属性不能与value合并使用 select:设置属性是否参与查询,此属性与select()映射配置不冲突

问题4:表名与编码开发设计不同步

该问题主要是表的名称和模型类的名称不一致,导致查询失败,这个时候通常会报如下错误信息:

==Table 'databaseName.tableNaem' doesn't exist==,翻译过来就是数据库中的表不存在。

解决方案是使用MP提供的另外一个注解@TableName来设置表与模型类之间的对应关系。

@TableName

@TableName

名称

@TableName

类型

==类注解==

位置

模型类定义上方

作用

设置当前类对应于数据库表关系

相关属性

value(默认):设置数据库表名称

DML编程控制

对增删改三个内容的讲解。

id生成策略控制

* 不同的表应用不同的id生成策略

* 日志:自增(1,2,3,4,……)

* 购物订单:特殊规则(FQ23948AK3843)

* 外卖单:关联地区日期等信息(10 04 20200314 34 91)

* 关系表:可省略id

* ……

不同的业务采用的ID生成方式应该是不一样的,MP中都提供这些主键生成策略

@TableId

名称

@TableId

类型

==属性注解==

位置

模型类中用于表示主键的属性定义上方

作用

设置当前类中主键属性的生成策略

相关属性

value(默认):设置数据库表主键名称 type:设置主键属性的生成策略,值查照IdType的枚举值

AUTO策略

@TableId(type = IdType.AUTO)

`AUTO`的作用是==使用数据库ID自增==,在使用该策略的时候一定要确保对应的数据库表设置了ID主键自增,否则无效。

  • NONE: 不设置id生成策略
  • INPUT:用户手工输入id @TableId(type = IdType.INPUT)
  • ASSIGN_ID:雪花算法生成id(可兼容数值型与字符串型) @TableId(type = IdType.ASSIGN_ID)
  • ASSIGN_UUID:以UUID生成算法作为id生成策略 @TableId(type = IdType.ASSIGN_UUID)
  • 其他的几个策略均已过时,都将被ASSIGN_ID和ASSIGN_UUID代替掉。

分布式ID是什么?

  • 当数据量足够大的时候,一台数据库服务器存储不下,这个时候就需要多台数据库服务器进行存储
  • 比如订单表就有可能被存储在不同的服务器上
  • 如果用数据库表的自增主键,因为在两台服务器上所以会出现冲突
  • 这个时候就需要一个全局唯一ID,这个ID就是分布式ID。

ID生成策略对比

  • NONE: 不设置id生成策略,MP不自动生成,约等于INPUT,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂
  • AUTO:数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用
  • ASSIGN_UUID:可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符串,长度过长占用空间而且还不能排序,查询性能也慢
  • ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键
  • 综上所述,每一种主键策略都有自己的优缺点,根据自己项目业务的实际情况来选择使用才是最明智的选择。

简化配置

只需要在配置文件中添加如下内容:

mybatis-plus:
  global-config:
    db-config:
        id-type: assign_id

配置完成后,每个模型类的主键ID策略都将成为assign_id.

多记录操作

例子:批量删除的操作

对应的API方法

int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

翻译方法的字面意思为:删除(根据ID 批量删除),参数是一个集合,可以存放多个id值。

除了按照id集合进行批量删除,也可以按照id集合进行批量查询,还是先来看下API

List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

方法名称翻译为:查询(根据ID 批量查询),参数是一个集合,可以存放多个id值。

逻辑删除

标识新增的字段为逻辑删除字段,使用@TableLogic

@TableLogic

名称

@TableLogic

类型

==属性注解==

位置

模型类中用于表示删除字段的属性定义上方

作用

标识该字段为进行逻辑删除的字段

相关属性

value:逻辑未删除值 delval:逻辑删除值

@TableLogic(value="0",delval="1")
//value为正常数据的值,delval为删除数据的值
  • 如果每个表都要有逻辑删除,那么就需要在每个模型类的属性上添加

@TableLogic注解,如何优化?

在配置文件中添加全局配置,如下:

mybatis-plus:
  global-config:
    db-config:
      # 逻辑删除字段名
      logic-delete-field: deleted
      # 逻辑删除字面值:未删除为0
      logic-not-delete-value: 0
      # 逻辑删除字面值:删除为1
      logic-delete-value: 1

介绍完逻辑删除,逻辑删除的本质为:

逻辑删除的本质其实是修改操作。如果加了逻辑删除字段,查询数据时也会自动带上逻辑删除字段。

乐观锁

概念

在讲解乐观锁之前,我们还是先来分析下问题:

业务并发现象带来的问题:==秒杀==

  • 假如有100个商品或者票在出售,为了能保证每个商品或者票只能被一个人购买,如何保证不会出现超买或者重复卖
  • 对于这一类问题,其实有很多的解决方案可以使用
  • 第一个最先想到的就是锁,锁在一台服务器中是可以解决的,但是如果在多台服务器下锁就没有办法控制,比如12306有两台服务器在进行卖票,在两台服务器上都添加锁的话,那也有可能会导致在同一时刻有两个线程在进行卖票,还是会出现并发问题
  • 我们接下来介绍的这种方式是针对于小型企业的解决方案,因为数据库本身的性能就是个瓶颈,如果对其并发量超过2000以上的就需要考虑其他的解决方案了。

简单来说,乐观锁主要解决的问题是当要更新一条记录的时候,希望这条记录没有被别人更新。

实现思路

  1. 在模型类中添加对应的属性@Version
  2. 添加乐观锁的拦截器
  3. 执行更新操作

MP快速开发-代码生成器

代码生成器原理分析

观察我们之前写的代码,会发现其中也会有很多重复内容,比如:

那我们就想,如果我想做一个Book模块的开发,是不是只需要将红色部分的内容全部更换成Book即可,如:

所以我们会发现,做任何模块的开发,对于这段代码,基本上都是对红色部分的调整,所以我们把去掉红色内容的东西称之为==模板==,红色部分称之为==参数==,以后只需要传入不同的参数,就可以根据模板创建出不同模块的dao代码。

除了Dao可以抽取模块,其实我们常见的类都可以进行抽取,只要他们有公共部分即可。再来看下模型类的模板:

  • ① 可以根据数据库表的表名来填充
  • ② 可以根据用户的配置来生成ID生成策略
  • ③到⑨可以根据数据库表字段名称来填充

所以只要我们知道是对哪张表进行代码生成,这些内容我们都可以进行填充。

分析完后,我们会发现,要想完成代码自动生成,我们需要有以下内容:

  • 模板: MyBatisPlus提供,可以自己提供,但是麻烦,不建议
  • 数据库相关配置:读取数据库获取表和字段信息
  • 开发者自定义配置:手工配置,比如ID生成策略

代码生成器实现

步骤1:创建一个Maven项目

代码2:导入对应的jar包

步骤3:编写引导类

码2:导入对应的jar包
步骤3:编写引导类
@SpringBootApplication
public class Mybatisplus04GeneratorApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(Mybatisplus04GeneratorApplication.class, args);
    }
​
}

步骤4:创建代码生成类

public class CodeGenerator {
    public static void main(String[] args) {
        //1.获取代码生成器的对象
        AutoGenerator autoGenerator = new AutoGenerator();
​
        //设置数据库相关配置
        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        autoGenerator.setDataSource(dataSource);
​
        //设置全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/mybatisplus_04_generator/src/main/java");    //设置代码生成位置
        globalConfig.setOpen(false);    //设置生成完毕后是否打开生成代码所在的目录
        globalConfig.setAuthor("黑马程序员");    //设置作者
        globalConfig.setFileOverride(true);     //设置是否覆盖原始生成的文件
        globalConfig.setMapperName("%sDao");    //设置数据层接口名,%s为占位符,指代模块名称
        globalConfig.setIdType(IdType.ASSIGN_ID);   //设置Id生成策略
        autoGenerator.setGlobalConfig(globalConfig);
​
        //设置包名相关配置
        PackageConfig packageInfo = new PackageConfig();
        packageInfo.setParent("com.aaa");   //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
        packageInfo.setEntity("domain");    //设置实体类包名
        packageInfo.setMapper("dao");   //设置数据层包名
        autoGenerator.setPackageInfo(packageInfo);
​
        //策略设置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tbl_user");  //设置当前参与生成的表名,参数为可变参数
        strategyConfig.setTablePrefix("tbl_");  //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名  例如: User = tbl_user - tbl_
        strategyConfig.setRestControllerStyle(true);    //设置是否启用Rest风格
        strategyConfig.setVersionFieldName("version");  //设置乐观锁字段名
        strategyConfig.setLogicDeleteFieldName("deleted");  //设置逻辑删除字段名
        strategyConfig.setEntityLombokModel(true);  //设置是否启用lombok
        autoGenerator.setStrategy(strategyConfig);
        //2.执行生成操作
        autoGenerator.execute();
    }
}

对于代码生成器中的代码内容,我们可以直接从官方文档中获取代码进行修改,

https://mp.baomidou.com/guide/generator.html

步骤5:运行程序

运行成功后,会在当前项目中生成很多代码,代码包含controller,service,mapper和entity

MP中Service的CRUD

回顾我们之前业务层代码的编写,编写接口和对应的实现类:

public interface UserService{
    
}
​
@Service
public class UserServiceImpl implements UserService{
}

接口和实现类有了以后,需要在接口和实现类中声明方法

public interface UserService{
    public List<User> findAll();
}
​
@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDao userDao;
    
    public List<User> findAll(){
        return userDao.selectList(null);
    }
}

MP看到上面的代码以后就说这些方法也是比较固定和通用的,那我来帮你抽取下,所以MP提供了一个Service接口和实现类,分别是:IService和ServiceImpl,后者是对前者的一个具体实现。

以后我们自己写的Service就可以进行如下修改:

public interface UserService extends IService<User>{
    
}
​
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService{
​
}

修改以后的好处是,MP已经帮我们把业务层的一些基础的增删改查都已经实现了,可以直接进行使用。

编写测试类进行测试:

@SpringBootTest
class Mybatisplus04GeneratorApplicationTests {
​
    private IUserService userService;
​
    @Test
    void testFindAll() {
        List<User> list = userService.list();
        System.out.println(list);
    }
}

注意:mybatisplus_04_generator项目中对于MyBatis的环境是没有进行配置,如果想要运行,需要提取将配置文件中的内容进行完善后在运行。

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

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

相关文章

CodeWave智能开发平台--03--目标:应用创建--03页面子页面设计

摘要 本文是网易数帆CodeWave智能开发平台系列的第06篇&#xff0c;主要介绍了基于CodeWave平台文档的新手入门进行学习&#xff0c;实现一个完整的应用&#xff0c;本文主要完成页面子页面设计 CodeWave智能开发平台的06次接触 CodeWave参考资源 网易数帆CodeWave开发者社…

【算法】链表-20240105

这里写目录标题 一、LCR 023. 相交链表二、142. 环形链表 II 一、LCR 023. 相交链表 给定两个单链表的头节点 headA 和 headB &#xff0c;请找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 提示&#xff1a; listA 中节点数目为 m list…

如何在 ChatGPT 上使用 Wolfram 插件回答数学问题

这里写自定义目录标题 写在最前面Wolfram是什么&#xff1f;ChatGPT 如何与 Wolfram 相结合&#xff0c;为什么有效&#xff1f;如何在 ChatGPT 上安装 Wolfram 插件&#xff1f; 写在最前面 参考&#xff1a;https://clickthis.blog/zh-CN/how-to-answer-math-questions-usin…

老师必备的办公AI工具

随着人工智能技术的不断发展&#xff0c;越来越多的AI工具开始进入教育领域&#xff0c;为老师的教学工作带来了极大的便利。本文将介绍一些老师必备的办公AI工具&#xff0c;帮助老师更好地进行教学工作。 ​一、智能发布成绩 智能发布成绩工具可以帮助老师快速发布学生的成绩…

霍尔传感器测速测距实验——STM32驱动(课程设计)

———————实验效果——————— &#x1f384;图片演示测距 &#x1f384;视频演示测速 基于STM32单片机 霍尔传感器测速度&#xff0c;测圈数 &#x1f384;模块介绍 测距使用HC-SR04模块 测距使用测速使用霍尔传感器 ———————代码获取查看下方———————…

Linux离线安装MySQL(rpm)

目录 下载安装包安装MySQL检测安装结果服务启停MySQL用户设置 下载安装包 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 下载全量包如&#xff1a;(mysql-8.1.0-1.el7.x86_64.rpm-bundle.tar) 解压&#xff1a;tar -xzvf mysql-8.1.0-1.el7.x86_64.…

软件验收测试计划、验收测试报告案例模板参考

1. 概述 1.1. 编写目的 1.2. 测试背景 1.3. 测试依据 1.4. 测试对象 1.5. 测试资源 2. 测试方式与环境 2.1. 测试方式 2.2. 测试环境 3. 测试结果 3.1. 功能适合性和准确性 3.1.1. 总体统计 3.1.2. 详细结果 3.2. 安全性 3.3. 可靠性和性能 4. 总体分析 5. 测试…

J2 - ResNet-50v2实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 环境步骤环境设置数据准备图像信息查看 模型设计ResidualBlock块stack堆叠resnet50v2模型 模型训练模型效果展示 总结与心得体会 环境…

第四节-MAC地址+网络层

MAC地址由两部分组成&#xff0c;分别是供应商代码和序列号。其中前24位代表该供应商代码&#xff0c;由IEEE管理和分配。剩下的24位序列号由厂商自己分配。 mac地址显示16进制12个16进制数 二进制&#xff08;逢2进1&#xff09; 102 113 1004 二进制4位数最大代表15 十…

【AI视野·今日CV 计算机视觉论文速览 第281期】Tue, 2 Jan 2024

AI视野今日CS.CV 计算机视觉论文速览 Tue, 2 Jan 2024 Totally 95 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Refining Pre-Trained Motion Models Authors Xinglong Sun, Adam W. Harley, Leonidas J. Guibas考虑到在视频中手动注释运…

【管理篇 / 恢复】❀ 08. 文件权限对macOS下用命令刷新固件的影响 ❀ FortiGate 防火墙

【简介】虽然上篇文章中成功的在macOS下刷新了固件&#xff0c;但是很多小伙伴在实际操作中碰到了无法成功的状况&#xff0c;我们来看看最常见的一种。 在/private/tftpboot目录拷贝另一个版本的固件文件&#xff0c;具体拷贝过程不再详述。 打开终端&#xff0c;输入命令 sud…

Linux引导过程与服务控制

目录 一、操作系统引导过程 1. 过程图示 2. 步骤解析 2.1 bios 2.2 mbr 2.3 grup 2.4 加载内核文件 3. 过程总结 4. centos6和centos7启动区别 5. 小结 二、服务控制及切换运行级别 1. systemd核心概念 2. 运行级别 3. 运行级别所对应的Systemd目标 4. Systemd…

只会用 xxl-job?更强大的新一代分布式任务调度框架来了!

前言 PowerJob是新一代分布式任务调度与计算框架&#xff0c;支持CRON、API、固定频率、固定延迟等调度策略&#xff0c;提供工作流来编排任务解决依赖关系&#xff0c;能让您轻松完成作业的调度与繁杂任务的分布式计算。 文章来源&#xff1a;https://blog.csdn.net/LY_624/…

虾皮、Lazada店铺流量怎么提升?自养号优势及测评系统如何搭建?

虾皮、Lazada是东南亚地区最大的购物平台之一&#xff0c;吸引了大量的买家和卖家。在竞争激烈的虾皮市场上&#xff0c;如何提升店铺的流量成为许多卖家关注的问题。以下是关于如何提升虾皮、Lazada店铺流量的一些建议。 一、店铺流量怎么提升? 首先&#xff0c;进行优质的…

Redis 给集合元素单独设置过期

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、场景 1.1 消费队列 1.2 Redis实现 二、常见的方案 2.1 为单独的 field 设置过期 2.2 设置整体过期时间 2.3 zset 结合 sc…

java spring mvc 初探 web搭建过程详解

提前准备安装tomcat 设备:mac 第一步:下载 进入官网下载压缩包 注意:如果jdk版本是1.8,则tomcat需要v8才行,否则会报错 https://tomcat.apache.org/ 第二步:解压 解压后路径 /Users/you/Library/tomcat/apache-tomcat-8.5.73 进入此目录 修改配置 code setclasspath.…

小白入门基础 - spring Boot 入门

1.简介 spring Boot是为了简化java的开发流程而构建的&#xff0c;即使是使用springMVC框架&#xff0c;也依然需要大量配置和依赖导入&#xff0c; 这无疑是繁琐的&#xff0c;spring Boot采用了”习惯由于配置“的原则&#xff0c;进行一键化部署&#xff0c;这样极大…

延迟加载:提升性能的隐形利器

引言 想象一下&#xff0c;你正在玩一款大型电子游戏。如果游戏在启动的时候就加载了所有的关卡、角色和道具&#xff0c;那玩家可能需要等待很长时间才能开始游戏&#xff0c;而且大部分内容可能在游戏的初期都不会被用到。显然&#xff0c;这样的做法既低效又耗时。 而延迟加…

LeetCode刷题--- 不同路径

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述动…

SESV:通过预测和纠错实现精确的医学图像分割

SESV: Accurate Medical Image Segmentation by Predicting and Correcting Errors SESV&#xff1a;通过预测和纠错实现精确的医学图像分割背景贡献实验方法Thinking SESV&#xff1a;通过预测和纠错实现精确的医学图像分割 286 IEEE TRANSACTIONS ON MEDICAL IMAGING, VOL. …