springboot整合mybatis-plus【详细版】

目录
  • 一,简介
    • 1. 什么是mybatis-plus
    • 2.mybatis-plus特点
  • 二,搭建基本环境
    • 1. 导入基本依赖:
    • 2. 编写配置文件
    • 3. 创建实体类
    • 4. 编写controller层
    • 5. 编写service接口
    • 6. 编写service层
    • 7. 编写mapper层
  • 三,基本知识介绍
    • 1. 基本注解
      • @TableName
      • @TableId
      • @TableFiled
      • @TableLogic
      • @Version
      • @Transient
    • 2. Wrapper的介绍*
      • QueryWrapper
      • UpdateWrapper
      • LambdaQueryWrapper
      • LambdaUpdateWrapper
      • Wrappers
    • 3. 分页查询
      • 1. 配置相应的拦截器
      • 2. 实现分页逻辑
  • 四,结语

一,简介

1. 什么是mybatis-plus

MyBatis-Plus(简称MP)是一个MyBatis的增强工具,旨在在MyBatis的基础上只做增强不做改变,以简化开发、提高效率。MyBatis-Plus保持了MyBatis原有的所有特性,同时增加了一些实用的功能,使得开发者能够更加便捷地进行数据库操作。以下是MyBatis-Plus的一些主要特点和功能:

2.mybatis-plus特点

  1. 无侵入:引入MyBatis-Plus不会对现有的MyBatis工程产生影响,可以无缝集成到现有的项目中。
    损耗小:启动时自动注入基本的CRUD操作,几乎不消耗额外的性能,可以直接面向对象操作数据库。
  2. 强大的CRUD操作:内置通用Mapper、通用Service,通过少量配置即可实现单表的大部分CRUD操作。同时,MyBatis-Plus提供了强大的条件构造器,满足复杂的查询需求。
  3. 支持Lambda形式调用:利用Lambda表达式方便地编写查询条件,避免了字段名称错误的问题。
  4. 支持主键自动生成:提供了多种主键生成策略,包括分布式唯一ID生成器,解决了主键问题。
  5. 支持ActiveRecord模式:通过继承特定的基类,可以像操作对象一样操作数据库。
  6. 支持自定义全局通用操作:允许开发者注入自己的通用方法。
  7. 内置分页插件:基于MyBatis的物理分页,开发者可以轻松实现分页查询。
  8. 支持多种数据库:兼容MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、PostgreSQL、SQL Server等多种数据库。
  9. 内置性能分析插件:可以输出SQL语句及其执行时间,有助于快速定位慢查询。
  10. 内置全局拦截插件:提供全表删除、更新操作的智能分析阻断,防止误操作。

二,搭建基本环境

1. 导入基本依赖:

      <!--mybatis-plus依赖-->
      <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.7</version>
        </dependency>
		<!--mysql连接依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!--连接池依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.18</version>
        </dependency>

2. 编写配置文件

spring:
  data:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_study?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

3. 创建实体类

package org.example.pojo;


import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.util.Date;
@TableName("student")
public class Student {
    @TableId(type = IdType.AUTO)
    private int id;
    
    private String studentNumber;
    
    private String name;
    
    private int gender; 
    // 0 表示女性,1 表示男性
    private Date dateOfBirth;
   // Getters and Setters
    }

4. 编写controller层

package org.example.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/students")
public class StudentController {
    
}

5. 编写service接口

package org.example.service;

import com.baomidou.mybatisplus.extension.service.IService;
import org.example.pojo.Student;

public interface StudentService extends IService<Student> {
}

6. 编写service层

package org.example.service.serviceImpl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.mapper.StudentMapper;
import org.example.pojo.Student;
import org.example.service.StudentService;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

}

7. 编写mapper层

package org.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.pojo.Student;

@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}

三,基本知识介绍

1. 基本注解

@TableName

主要用于指定表名,实现实体类与表名的绑定,作用于类上,适用于表名与实体类名称不统一的情况,统一的情况可以不用写。
在这里插入图片描述

import com.baomidou.mybatisplus.annotation.TableName;
//此处表名称为t_user,实体类名称为User不统一
@TableName("t_user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    // Getters and Setters
}

如果所有的表结构与实体类只是多了一个前缀,可以直接在配置文件里面配置全局的前缀,就可以不使用注解了,两种方式都可以,根据具体场景选择,配置如下:

mybatis-plus:
  global-config:
    db-config:
      table-prefix: t_
@TableId

作用于主键上,指明主键字段,并设置主键的生成方式。

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;

@TableName("user_info") // 指定该实体类对应的数据表名
public class UserInfo {
//此处value也可以作用于映射,当实体类中
//的id字段名和数据库中的字段名不相同时,可以使用其属性做增强
    @TableId(value = "id", type = IdType.AUTO) // 标记为主键,并指定主键生成策略为自增
    private Long id;

    private String username;
    
    private String password;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}


注解属性:
   value:指定表中主键字段,多用于主键字段和实体类字段不同意
    type:id生成策略

对于IdType做出如下说明:

属性

说明

适用场景

AUTO

数据库自增主键

适用于 MySQL、SQL Server 等支持自增主键的数据库

NONE

不使用任何主键生成策略

通常用于主键已经存在的情况

ASSIGN_ID

全局唯一ID(默认基于Snowflake算法生成)

适用于分布式系统,确保全局唯一性

ASSIGN_UUID

全局唯一UUID,生成32位的字符串

适用于需要字符串主键的场景

INPUT

自定义输入主键值

适用于某些特殊场景,如导入数据时需要手动指定主键

@TableFiled

改注解作用众多,多用于表字段和实体类字段名称不统一,做映射处理,也可用于零时字段,不存入数据库,或者是一些字段的填充处理(此处需要编写填充处理器)。
在这里插入图片描述

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;

import java.util.Date;

@TableName("user_info")
public class UserInfo {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @TableField("username")
    private String username;
	//此字段不参与查询
    @TableField("password", select=false )
    private String password;

    @TableField("email")
    private String email;
	//注意,此处应该编写相应的填充逻辑
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(value = "update_time", fill = FieldFill.UPDATE)
    private Date updateTime;

    @TableField(exist = false)
    private String tempField; // 临时字段,不在数据库中

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public String getTempField() {
        return tempField;
    }

    public void setTempField(String tempField) {
        this.tempField = tempField;
    }
}


属性说明:
	value:同上面注解一样,用于字段绑定,单个属性的时候可以不写
	select:在值为false的情况下用于设置不参查询,查询之后不会返回回来
	exist :用于类中的零时变量,数据库中没有该字段,只在java中使用
	fill:用于自动填充,比如create_time,update_time这一类,但需要编写相应的处理器

对应处理器代码:

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }
}
@TableLogic

该字段用于指定逻辑删除的字段,当执行删除语句时,做更新操作,只改变当前字段的值,设置为删除状态,数据不做真实处理,查询时也只查询状态为未删除的数据(此过程不需要手动实现,mybatis-plus已经帮忙实现了,我们只需要添加字段,设置相应的状态值)注:该字段也需要加入到对应的表里

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;

@TableName("user_info")
public class UserInfo {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private String username;

    private String password;

    private String email;

    @TableLogic
    private Integer isDeleted;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getIsDeleted() {
        return isDeleted;
    }

    public void setIsDeleted(Integer isDeleted) {
        this.isDeleted = isDeleted;
    }
}

在配置文件中添加如下配置:

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

用于配置乐观锁字段,配置之后的更新操作都会先去比较版本,然后在去操作,整体采用cas机制实现。注:该字段也需要加入到对应的表里

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.Version;

@TableName("order_info")
public class OrderInfo {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private String orderNo;

    private Double amount;

    @Version
    private Integer version;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public Double getAmount() {
        return amount;
    }

    public void setAmount(Double amount) {
        this.amount = amount;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }
}

此处需加相关的拦截器:

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
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}


乐观锁的作用:
	乐观锁假设在并发环境中冲突较少,因此在操作数据时不立即获取锁,而是等到提交更新时才检查是否有其他事务修改过数据。如果发现数据已被修改,则更新失败,通常会抛出异常。
    特点:在提交更新时检查版本号,如果版本号匹配则更新成功,否则更新失败。
	效果:多个事务可以同时读取和处理数据,但在提交更新时会检查版本号,确保数据的一致性。
@Transient

作用于实体类字段,使其不参与数据库的操作,其中包括(Insert,Update,Select),@TableField(exist=false)作用相同,充当零时变量。

@TableName("user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;

    private String name;

    @Transient
    private String tempField;

    // getters and setters
}	

2. Wrapper的介绍*

概念:MyBatisPlus提供了QueryWrapper、LambdaQueryWrapper、UpdateWrapper和LambdaUpdateWrapper等条件类,大大简化了我们的开发,可以使代码更加清晰和易于管理,其中包括多条件查询、排序、条件优先级以及有条件时才加入条件的场景,并提供了示例代码展示如何进行数据库查询和更新操作。

大致的条件(此处粗略列举):

方法

描述

eq

等于

ne

不等于

gt

大于

ge

大于等于

lt

小于

le

小于等于

like

模糊查询

notLike

反向模糊查询

in

在某集合内

notIn

不在某集合内

isNull

为空

isNotNull

不为空

between

在某个区间内

notBetween

不在某个区间内

set

设置字段值

QueryWrapper

作用于查询设置查询条件。

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public List<User> getUsersByConditions() {
        // 创建 QueryWrapper 对象
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        
        // 添加查询条件
        queryWrapper.eq("name", "张三")
                    .ge("age", 18)
                    .orderByDesc("create_time");

        // 执行查询
        return userMapper.selectList(queryWrapper);
    }
}

此处执行的sql语句:

SELECT * FROM user WHERE name = '张三' AND age >= 18 ORDER BY create_time DESC;
UpdateWrapper

作用于更新设置条件。

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public int updateUserById() {
        // 创建 UpdateWrapper 对象
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        
        // 添加更新条件
        updateWrapper.eq("id", 1);

        // 创建要更新的对象
        User user = new User();
        user.setName("李四");

        // 执行更新
        return userMapper.update(user, updateWrapper);
    }
}

此处执行的sql语句:

UPDATE user SET name = '李四' WHERE id = 1;
LambdaQueryWrapper

在QueryWrapper做了增强,作用一样,用于设置查询条件。

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public List<User> getUsersByLambdaConditions() {
        // 创建 LambdaQueryWrapper 对象
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        lambdaQueryWrapper.eq(User::getName, "张三")
                          .ge(User::getAge, 18)
                          .orderByDesc(User::getCreateTime);

        // 执行查询
        return userMapper.selectList(lambdaQueryWrapper);
    }
}

此处执行的sql语句:

SELECT * FROM user WHERE name = '张三' AND age >= 18 ORDER BY create_time DESC;
LambdaUpdateWrapper

在UpdateWrapper做了增强,作用一样,用于设置跟新条件。

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public int updateUserByIdWithLambda() {
        // 创建 LambdaUpdateWrapper 对象
        LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        
        // 添加更新条件
        lambdaUpdateWrapper.eq(User::getId, 1);

        // 创建要更新的对象
        User user = new User();
        user.setName("李四");

        // 执行更新
        return userMapper.update(user, lambdaUpdateWrapper);
    }
}

此处执行的sql语句:

UPDATE user SET name = '李四' WHERE id = 1;
Wrappers

用于更简便的条件设置

import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public List<User> getUsersByConditionsUsingWrappers() {
        // 创建 QueryWrapper 对象
        QueryWrapper<User> queryWrapper = Wrappers.<User>query()
                                                  .eq("name", "张三")
                                                  .ge("age", 18)
                                                  .orderByDesc("create_time");

        // 执行查询
        return userMapper.selectList(queryWrapper);
    }
}

此处执行的sql语句:

SELECT * FROM user WHERE name = '张三' AND age >= 18 ORDER BY create_time DESC;

3. 分页查询

1. 配置相应的拦截器
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}
2. 实现分页逻辑
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public IPage<User> getUserPage(int current, int size) {
        // 创建 Page 对象,传入当前页码和每页大小
        Page<User> page = new Page<>(current, size);

        // 创建 QueryWrapper 对象,添加查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1)
                    .orderByDesc("create_time");

        // 执行分页查询
        IPage<User> userPage = userMapper.selectPage(page, queryWrapper);
		// 获取分页数据
		List<User> users = userPage.getRecords();

		// 获取总记录数
		long total = userPage.getTotal();

		// 获取当前页码
		int current = userPage.getCurrent();

		// 获取每页大小
		int size = userPage.getSize();

		// 获取总页数
		int pages = userPage.getPages();
        return userPage;
    }
}

执行对应的sql语句是:

-- 分页查询
SELECT * 
FROM user 
WHERE status = 1 
ORDER BY create_time DESC 
LIMIT 0, 10; -- 当前页码为1,每页大小为10

四,结语

在本文中,我们详细介绍了 MyBatis-Plus 的核心功能和使用方法,包括如何配置分页插件、编写分页查询代码、使用各种 Wrapper 构建复杂查询条件等。通过这些内容,相信你已经对 MyBatis-Plus 有了更深入的了解,并能够在实际项目中灵活应用这些功能。
MyBatis-Plus 作为一个强大的 MyBatis 增强工具,不仅简化了数据访问层的开发工作,还提供了许多便捷的功能,如分页查询、链式编程、乐观锁等。它能够显著提升开发效率,减少重复代码,使你的项目更加简洁和高效。
如果你在阅读本文后对 MyBatis-Plus 感兴趣,不妨在自己的项目中尝试一下。实践是最好的老师,通过实际操作,你会更加深刻地理解这些功能的奥妙。同时,也欢迎你在评论区分享你的使用经验和遇到的问题,我们一起探讨和解决。
最后,感谢你花时间阅读本文,希望本文能为你带来帮助。如果你觉得本文对你有帮助,别忘了点赞和分享,让更多的人受益。让我们一起在技术的道路上不断前行,共同成长!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MAUI APP开发蓝牙协议的经验分享:与跳绳设备对接

在开发MAUI应用程序时&#xff0c;蓝牙协议的应用是一个重要的环节&#xff0c;尤其是在需要与外部设备如智能跳绳进行数据交换的场景中。以下是我在开发过程中的一些经验和心得&#xff0c;希望能为你的项目提供帮助。 1. 蓝牙协议基础 蓝牙协议是无线通信的一种标准&#x…

快速构建NLP理论知识体系

NLP理论知识体系 一句话解释NLPNLP模型及原理简述1、Rag 一句话解释NLP 如果我们要实现机器翻译、情感分析、问答系统、文本摘要、聊天机器人、构造智能化的辅助文件填写模板&#xff0c;NLP可以通过现成的模型对输入的语音、文字、图片进行处理&#xff08;分词、标词性、去停…

试题转excel;pdf转excel;试卷转Excel,word试题转excel

一、问题描述 一名教师朋友&#xff0c;偶尔会需要整理一些高质量的题目到excel中 以往都是手动复制搬运&#xff0c;几百道题几乎需要一个下午的时间 关键这些事&#xff0c;枯燥无聊费眼睛&#xff0c;实在是看起来就很蠢的工作 就想着做一个工具&#xff0c;可以自动处理…

Android Gradle 相关

JDK环境配置&#xff1a; 1、Gradle运行时的JDK&#xff0c;即Gradle需要用到的JDK&#xff0c;配置如下&#xff1a; 如需修改现有项目的 Gradle JDK 配置&#xff0c;请依次点击 File&#xff08;或者 macOS 上的 Android Studio&#xff09;> Settings > Build, Exe…

LeetCode - #151 颠倒字符串中的单词

文章目录 前言1. 描述2. 示例3. 答案关于我们 前言 我们社区陆续会将顾毅&#xff08;Netflix 增长黑客&#xff0c;《iOS 面试之道》作者&#xff0c;ACE 职业健身教练。&#xff09;的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新…

图数据库 | 11、图数据库架构设计——高性能图存储架构(下)

在上篇内容中&#xff0c;老夫着重讲了高性能图存储系统的特点&#xff0c;咱们继续往下讲重点——高性能存储架构的设计思路&#xff01;&#xff01; 2.高性能存储架构设计思路 首先呢&#xff0c;存储架构以及核心数据结构的设计思路通常围绕如下4个维度来进行&#xff1a…

如何配置Github并在本地提交代码

前提: 可以流畅访问github, 需要一些上网技巧, 这就自行处理了 申请一个github账号 Github官网地址 首先就是邮箱注册啦, github没有对邮箱的限制, 只要是能收邮件的就ok, qq邮箱, 163等都可以使用. 然后和普通注册账号一样, 一路填写需要的信息, 验证邮箱即可. 如何新增代…

小型支付商城系统-MVC工程架构开发

第1-1节 DDD 架构概念 1.DDD 是什么 那 DDD 是什么呢&#xff1f;来自于维基百科的一段定义&#xff1a;"Domain-driven design (DDD) is a major software design approach. "&#xff0c;DDD 是一种软件设计方法。也就是说 DDD 是指导我们做软件工程设计的一种手…

【计算机网络】实验11:边界网关协议BGP

实验11 边界网关协议BGP 一、实验目的 本次实验旨在验证边界网关协议&#xff08;BGP&#xff09;的实际作用&#xff0c;并深入学习在路由器上配置和使用BGP协议的方法。通过实验&#xff0c;我将探索BGP在不同自治系统之间的路由选择和信息交换的功能&#xff0c;理解其在互…

ai即可一键生成ppt解决烦恼

在快节奏的职场环境中&#xff0c;制作PPT已经成为许多人日常工作的一部分。尽管PPT看似简单&#xff0c;却常常让人耗费大量时间。好在技术的进步为我们带来了全新的解决方案&#xff0c;比如智能生成PPT&#xff0c;让那些深夜加班的人看到了曙光。 从“手动排版”到“一键生…

利用docker-compose来搭建flink集群

1.前期准备 &#xff08;1&#xff09;把docker&#xff0c;docker-compose&#xff0c;kafka集群安装配置好 参考文章&#xff1a; 利用docker搭建kafka集群并且进行相应的实践-CSDN博客 这篇文章里面有另外两篇文章的链接&#xff0c;点进去就能够看到 &#xff08;2&…

网络命令配置

随笔记录 目录 1. 背景介绍 2. 配置网络命令空间 3 验证 3.1 未网络命令空间外网卡配置IP 3.2 验证配置 3.2.1 在网络命令空间外接口启动iperf3 3.2.2 网络命令空间内启动iperf3 client 1. 背景介绍 2. 配置网络命令空间 1. 配置前[rootlocalhost SDK-V1.10.1.7]# ip…

沃丰科技智能客服在电商独立站中有哪些核心功能?

在数字化飞速发展的今天&#xff0c;电商独立站作为企业与消费者沟通的重要桥梁&#xff0c;其客户服务的质量和效率直接关系到企业的竞争力和市场地位。沃丰科技智能客服以其全面的功能&#xff0c;成为了电商独立站接入的首选&#xff0c;为电商企业提供了全新的解决方案。 …

【深度学习】四大图像分类网络之VGGNet

2014年&#xff0c;牛津大学计算机视觉组&#xff08;Visual Geometry Group&#xff09;和Google DeepMind公司一起研发了新的卷积神经网络&#xff0c;并命名为VGGNet。VGGNet是比AlexNet更深的深度卷积神经网络&#xff0c;该模型获得了2014年ILSVRC竞赛的第二名&#xff0c…

C/C++当中的内存对齐

一&#xff1a;为什么要存在内存对齐 对与计算机而言&#xff0c;一次性可以取出处理的单元大小为字&#xff0c;在32位系统下&#xff0c;一次性可以取出4个字节&#xff0c;而在64位系统下&#xff0c;一次性可以取出8个字节&#xff0c;而一个地址对应一个内存单元&#xff…

vue聊天对话语音消息播放动态特效

vue2写法&#xff0c;vue3也能用&#xff0c;粘之即走&#xff1a; 示例&#xff1a; <template><div class"voice-hidden"><divclass"voice-play-chat":class"[className, { animate-stop: !isPlaying }]"><div class&q…

最新AI问答创作运营系统(SparkAi系统),GPT-4.0/GPT-4o多模态模型+联网搜索提问+问答分析+AI绘画+管理后台系统

目录 一、人工智能 系统介绍文档 二、功能模块介绍 系统快速体验 三、系统功能模块 3.1 AI全模型支持/插件系统 AI大模型 多模态模型文档分析 多模态识图理解能力 联网搜索回复总结 3.2 AI智能体应用 3.2.1 AI智能体/GPTs商店 3.2.2 AI智能体/GPTs工作台 3.2.3 自…

流媒体之linux下离线部署FFmpeg 和 SRS

前言 用户对网络做了限制&#xff0c;只能访问指定的网址&#xff0c;和没网没啥区别&#xff0c;导致无法连接外网&#xff0c;无法获取安装包&#xff0c;还有一些编译需要的开源工具 用户需要用平台查看库房的海康摄像头实时监控&#xff0c;只能在库房里一台纯净的ubantu…

8. 一分钟读懂“代理模式”

8.1 模式介绍 代理模式是一种结构型设计模式&#xff0c;它通过提供一个代理对象来替代对另一个对象&#xff08;真实对象&#xff09;的访问。代理对象与真实对象实现相同的接口&#xff0c;并通过代理类对真实对象的访问进行控制&#xff0c;可以在调用前后执行附加操作&…

插值方法在MATLAB中的应用和比较

插值方法在MATLAB中的应用和比较 在数据处理和科学计算中&#xff0c;插值是一种常见的技术&#xff0c;用于估计在已知数据点之间未知位置的数值。插值在图像处理、信号处理、数值分析等领域发挥着重要作用。通过插值&#xff0c;我们可以填补数据之间的空隙&#xff0c;平滑数…