[SSM]MyBatisPlus拓展

news2024/11/24 3:13:39

五、拓展篇

5.1逻辑删除

在电商网站中,我们会上架很多商品,这些商品下架以后,我们如果将这些商品从数据库中删除,那么在年底统计商品的时候,这个商品要统计的,所以这个商品信息我们是不能删除的。

如果商城的商品下架了,这时候我们将商品从数据库删掉,那么到年终总结的时候,我们要总结这一年的销售额,发现少了20000,这肯定是不合理的。所以我们是不能将数据真实删除的。

  • 这里我们就采取逻辑删除的方案,逻辑删除的操作就是增加一个字段表示这个数据的状态,如果一条数据需要删除,我们通过改变这条数据的状态来实现,这样既可以表示这条数据是删除的状态,又保留了数据以便以后统计。

1.修改字段

  • 在表中增加一列字段status,表示是否删除的状态,这里我们使用的字段类型为int类型,通过1表示该条数据可用,0表示该条数据不可用。

2.修改实体类

  • 实体类添加一个字段为Integer,用于对应表中的字段
public class User extends Model<User> {
    private Long id;
    @TableField("username")
    private String name;
    private Integer age;
    private String email;
    @TableField("`desc`")
    private String desc;
    //逻辑删除字段
    @TableLogic(value = "1",delval = "0")
    private Integer status;
}

3.测试逻辑删除效果

@Test
void LogicDelete() {
    userMapper.deleteById(7L);
}

在这里插入图片描述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.查询t_user表

@Test
void logicSelect() {
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    List<User> users = userMapper.selectList(lambdaQueryWrapper);
    System.out.println(users);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 我们还可以通过全局配置来实现逻辑删除的效果
#配置逻辑删除字段
mybatis-plus.global-config.db-config.logic-delete-field=status
#未删除为1
mybatis-plus.global-config.db-config.logic-not-delete-value=1
#删除为0
mybatis-plus.global-config.db-config.logic-delete-value=0

5.2通用枚举

  • 当我们想要表示一组信息,这组信息只能从一些固定的值中进行选择,不能随意写,在这种场景下,枚举就非常的合适。
  • 假如我们想要表示性别,性别只有两个值,要么是男性,要么是女性,那我们就可以使用枚举来描述性别。

1.添加字段

  • 我们先在表中添加一个字段gender,表示性别,这里一般使用int来描述,因为int类型可以通过0和1这两个值来表示两个不同的性别

2.编写枚举类

public enum GenderEnum {
    MAN(0,"男"),WOMEN(1,"女");

    @EnumValue
    private Integer gender;
    private String genderName;

    GenderEnum(Integer gender, String genderName) {
        this.gender = gender;
        this.genderName = genderName;
    }
}

3.实体类添加相关字段

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User extends Model<User> {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private GenderEnum gender;
    private Integer status;
}

4.添加数据

@Test
void enumTest() {
    User user = new User();
    user.setName("王五");
    user.setAge(28);
    user.setEmail("wangwu@qq.com");
    user.setStatus(1);
    user.setGender(GenderEnum.WOMEN);

    userMapper.insert(user);
}

5.3字段类型处理器

  • 在某些场景下,我们在实体类中是使用Map集合作为属性接收前端传递过来的数据的,但是这些数据存储在数据库时,我们使用的是json格式的数据进行存储,json本质是一个字符串,就是varchar类型。那怎么做到实体类的Map类型和数据库的varchar类型的互相转换,这里就需要使用字段类型处理器来完成。

1.在实体类中添加一个字段,Map类型

@Data
@NoArgsConstructor
@AllArgsConstructor
//查询时将json字符串封装为Map集合
@TableName(autoResultMap = true)
public class User extends Model<User> {
    private Long id;
    @TableField("username")
    private String name;
    private Integer age;
    private String email;
    @TableField("`desc`")
    private String desc;
    @TableField(exist = false)
    private Integer online;
    private Integer status;
    private GenderEnum gender;
    //指定字段类型处理器
    @TableField(typeHandler = FastjsonTypeHandler.class)
    private Map<String,String> contact;//联系方式
}

2.在数据库中添加一个字段contact,为varchar类型

3.添加依赖

  • 字段类型处理器依赖Fastjson这个Json处理器,所以我们需要引入对应的依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.7</version>
</dependency>

4.测试添加操作

@Test
void typeHandler() {
    User user = new User();
    user.setName("Li");
    user.setAge(28);
    user.setEmail("li@qq.com");
    user.setGender(GenderEnum.MAN);
    user.setStatus(1);

    HashMap<String, String> map = new HashMap<>();
    map.put("tel", "15896637666");
    map.put("phone", "0371-60283366");

    user.setContact(map);

    userMapper.insert(user);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.测试查询操作

@Test
void typeHandlerSelect() {
    List<User> users = userMapper.selectList(null);
    System.out.println(users);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.4自动填充功能

  • 在项目中有一些属性,如果我们不希望每次都填充的话,我们可以设置为自动填充,比如常见的时间。

1.在数据库的表中添加两个字段
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 注意设置驼峰命名

2.添加字段

  • 在实体类中,添加对应字段,并为需要自动填充的属性指定填充时机
//插入时自动填充createTime字段
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//插入或更新时自动填充updateTime字段
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

3.编写自动填充处理器,指定填充策略

@Component
public class MyMetaHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        setFieldValByName("createTime",new Date(),metaObject);
        setFieldValByName("updateTime",new Date(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        setFieldValByName("updateTime",new Date(),metaObject);
    }
}

4.测试插入操作

@Test
void testFillInsert(){
    User user = new User();
    user.setName("wang");
    user.setAge(35);
    user.setEmail("wang@powernode.com");
    user.setGender(GenderEnum.MAN);
    user.setStatus(1);
    HashMap<String, String> contact = new HashMap<>();
    contact.put("phone","010-1234567");
    contact.put("tel","13388889999");
    user.setContact(contact);
    userMapper.insert(user);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.测试更新操作

@Test
void testFillUpdate(){
    User user = new User();
    user.setId(18L);
    user.setName("wangwu");
    user.setAge(39);
    user.setEmail("wang@powernode.com");
    user.setGender(GenderEnum.MAN);
    user.setStatus(1);
    HashMap<String, String> contact = new HashMap<>();
    contact.put("phone","010-1234567");
    contact.put("tel","13388889999");
    userMapper.updateById(user);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.5防全表更新与删除插件

  • 在实际开发中,全表更新和删除是非常危险的操作,在MybatisPlus中,提供了插件和防止这种危险操作的发生。

1.注入MybatisPlusInterceptor类,并配置BlockAttackInnerInterceptor拦截器

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //防止全表更新
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        return interceptor;
    }
}

2.测试全表更新

@Test
public void updateAll(){
    User user = new User();
    user.setGender(GenderEnum.MAN);

    userService.saveOrUpdate(user,null);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.6MybatisX快速开发插件

  • MybatisX是一款IDEA提供的插件,目的是为了我们简化Mybatis以及MybatisPlus框架而生。

5.6.1安装

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.6.2功能

1.点击小鸟,Mapper接口和映射文件可以互相跳转

2.逆向工程

  • 逆向工程就是通过数据库表结构,逆向产生Java工程的结构
  • 包括以下几点:
    • 实体类
    • Mapper接口
    • Mapper映射文件
    • Service接口
    • Service实现类

1.引入依赖,编写对应的配置文件信息

<dependencies>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.31</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
#配置数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=030522

2.使用IDEA连接mysql

3.使用逆向工程
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.编写逆向工程配置信息和生成信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.在Mapper接口上添加@Mapper注解

@Mapper
public interface UserMapper extends BaseMapper<User> {

}

6.测试

@SpringBootTest
class Mp03ApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Resource
    private UserService userService;

    @Test
    void testUserMapper() {
        List<User> users = userMapper.selectList(null);
        users.forEach(user -> System.out.println(user));
    }

    @Test
    void testUserService() {
        User byId = userService.getById(10L);
        System.out.println(byId);
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.常见需求代码生成

  • 虽然Mapper接口中提供了一些常见方法,我们可以直接使用这些方法来完成sql操作,但是对于实际场景中各种复杂的操作需求来说,依然是不够用的,所以MybatisX提供了更多的方法,以及可以根据这些方法直接生成对应的sql语句,这样使得开发变得更加简单。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.7乐观锁

  • 首先我们先要了解开发中的一个常见场景,叫做并发请求。并发请求就是在同一时刻有多个请求同时请求服务器资源,如果是获取信息,没什么问题,但是如果是对于信息做修改操作就会出现问题。

比如目前商品的库存只剩余1件了,这个时候有多个用户都想要购买这件商品,都发起了购买商品的请求,不能让多个用户都购买到,因为多个用户都买到了这件商品,那么就会出现超卖问题,库存不够是没法发货的。所以在开发中就要解决这种超卖的问题。

  • 这类场景的核心问题就是,一个请求在执行的过程中,其他请求不能改变数据,如果是一次完整的请求,在该请求的过程中其他请求没有对于这个数据产生修改操作,那么这个请求是能够正常修改数据的。如果该请求在改变数据的过程中,已经有其他请求改变了数据,那该请求就不能改变这条数据了。
  • 想要解决这类问题,最常见的就是加锁的思想,锁可以用验证在请求的执行过程中,是否有数据发生改变。
  • 常见的数据库锁类型有两种:悲观锁、乐观锁。
  • 一次完成的修改操作是:先查询数据,然后修改数据。
  • 悲观锁:悲观锁是在查询的时候就锁定数据,在这次请求未完成之前,不会释放锁,等到这次请求完毕之后再释放锁,释放了锁之后,其他请求才可以对于这条数据完成读写。例子:华为商店抢手机,排队中…
  • 这样做的操作能够保证读取到的信息就是当前的信息,保证了信息的正确性,但是并发效率很低,在实际开发中使用悲观锁的场景很少,因为在并发时我们是要保证效率的。
  • 乐观锁:乐观锁是通过表字段完成设计的,他的核心思想是,在读取的时候不加锁,其他请求依然可以读取到这个数据,在修改的时候判断一个数据是否有被修改过,如果有被修改过那么本次请求的修改操作失效。例子:大麦抢票

具体的SQL语句

Update 表 set 字段 = 新值,version = version + 1 where version = 1

  • 这样做的操作是不会对于数据读取产生影响的,并发效率高,但是可能眼前看到的数据并不是真实信息数据,是被修改之前的,在很多场景下是可以容忍的,并不是产生很大影响,例如很多时候我们看到的是有库存或者都加入到购物车了,但是点进去以后库存没有了。

乐观锁的使用

1.在数据库表中添加一个字段version,表示版本,默认值是1

2.找到实体类,添加对应的属性,并使用@Version标注为这是一个乐观锁字段信息

@Version
private Integer version;

3.配置拦截器

  • 因为要对每条修改语句完成语句的增强,这里我们通过拦截器的配置,让每条修改的sql语句在执行的时候,都加上版本控制的功能。
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //实现乐观锁的控制
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

4.测试效果

  • 先模拟查询,再修改
@Test
void updateTest() {
    User user = userMapper.selectById(18L);
    System.out.println(user);
    user.setName("赵六");
    userMapper.updateById(user);
}
  • 当我们完成修改时,会自动将版本号+1

5.模拟多个修改请求

  • 乐观锁的效果是,一个请求在修改的过程中,是允许另一个请求查询的,但是修改时会通过版本号是否改变来决定是否修改,如果版本号变了,证明已经有请求修改过数据了,那这次修改不生效,如果版本号没有发生变化,那就完成修改。
@Test
void updateTest2() {
    //模拟操作1的查询操作
    User user1 = userMapper.selectById(18L);
    System.out.println(user1);

    //模拟操作2的查询操作
    User user2 = userMapper.selectById(18L);
    System.out.println(user2);

    user2.setName("zhao");
    userMapper.updateById(user2);

    user1.setName("liu");
    userMapper.updateById(user1);
}
  • 这段代码其实是两次操作,只不过操作1在执行的过程中,有操作2完成了对于数据的修改,这时操作1就无法再次进行修改了。

5.8代码生成器

  • 代码生成器和逆向工程的区别在于,代码生成器可以生成更多的结构,更多的内容,允许我们能够配置生成的选项更多。

1.引入依赖

<!--代码生成器依赖-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.3</version>
</dependency>

<!--freemarker模板依赖-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

2.编写代码生成器代码

@SpringBootTest
public class GeneratorApplicationTests {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false", "root", "030522")
                .globalConfig(builder -> {
                    builder.author("hhb") // 设置作者
                            //.enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir("D://"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.hhb.mp02") // 设置父包名
                            .moduleName("mybatisplus") // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("t_user") // 设置需要生成的表名
                            .addTablePrefix("t"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}

3.执行,查看生成效果

5.9执行SQL分析打印

  • 在我们日常开发工作中,避免不了查看当前程序所执行的SQL语句,以及了解它的执行时间,方便分析是否出现了慢SQL问题。我们可以使用MybatisPlus提供的SQL分析打印的功能,来获取SQL语句执行的时间。

1.引入依赖

<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>

2.修改application.properties配置文件

#配置数据源
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/mybatisplus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=030522

3.在resources下,创建spy.properties配置文件

#3.2.1以上使用modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory

# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger

#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger

# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger

# 设置 p6spy driver 代理
deregisterdrivers=true

# 取消JDBC URL前缀
useprefix=true

# 配置记录 Log 例外,可去掉的结果集error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset

# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss

# 实际驱动可多个
#driverlist=org.h2.Driver

# 是否开启慢SQL记录
outagedetection=true

# 慢SQL记录标准 2 秒
outagedetectioninterval=2

4.测试

  • 执行查询所有的操作,可以看到sql语句的执行时间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.10多数据源

  • 当一个项目的数据库的数据十分庞大时,在完成SQL操作的时候,需要检索的数据就会更多,我们会遇到性能问题,会出现SQL执行效率低的问题。
  • 针对这个问题,我们的解决方案是,将一个数据库中的数据拆分到多个数据库中,从而减少单个数据库的数据量,从分摊访问请求的压力和减少单个数据库数据量这两个方面,都提升了效率。

数据源切换

1.引入依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.1.0</version>
</dependency>

2.创建新的数据库,提供多数据源环境

3.编写配置文件,指定多数据源信息

spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          username: root
          password: root
          url: jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_1:
          username: root
          password: root
          url: jdbc:mysql://localhost:3306/mybatisplus2?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver

4.创建多个Service,分别使用@Ds注解描述不同的数据源信息

@Service
@DS("master")
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
}
@Service
@DS("slave_1")
public class UserServiceImpl2 extends ServiceImpl<UserMapper, User> implements UserService{
}

5.测试service多数据源环境执行结果

@SpringBootTest
class Mp03ApplicationTests {

    @Autowired
    private UserServiceImpl userServiceImpl;

    @Autowired
    private UserServiceImpl2 userServiceImpl2;

    @Test
    public void select(){
        User user = userServiceImpl.getById(1L);
        System.out.println(user);
    }

    @Test
    public void select2(){
        User user = userServiceImpl2.getById(1L);
        System.out.println(user);
    }
}
  • 测试发现,结果可以从两个数据源中获取。

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

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

相关文章

球谐函数实现环境光照漫反射实践

该文章以及代码主要来自 图形学论文解析与复现&#xff1a;【论文复现】An Efficient Representation for Irradiance Environment Maps 作者&#xff1a;Monica的小甜甜 与原文的不同&#xff1a; 对一些有问题的地方进行了修改添加了注释对有疑问的地方添加了疑问点引入了其…

【笔试强训选择题】Day37.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01; 文章目录 前言一、Day…

camx camera initial

qnx 平台中的camera hal 接口 HAL3Module&#xff1a;chi_hal_override_entry 在android 的中使用Camx 打开com.qti.chi.override.so进行注册hal ops 操作接口 camhal3module.cpp 中的构造函数HAL3Module中 CHIHALOverrideEntry funcCHIHALOverrideEntry reinterpret_cast…

即拼七人拼团系统开发模式的奖励机制都有哪些?

即拼七人拼团是市场上非常火爆的商业模式之一&#xff0c;它通过团购机制、互动社交和抽奖等方式&#xff0c;有效解决了电商平台的复购难题。不仅可以降低商品价格&#xff0c;还能够增加用户的参与感和购物乐趣&#xff0c;提升平台的用户粘性和产品销量。下面就来具体说一下…

驱动轴相机参数设置Web前端界面开发

一、基于Django的Web应用界面的开发&#xff1a; 在Realtimeresults.html上添加一个按钮组件&#xff0c;获取检测到的轴型和车轮信息&#xff0c;点击后可以获取package.json里存放的json数据&#xff0c;效果如下&#xff1a; 实现逻辑&#xff1a;需要从URL设置、视图函数、…

YOLOV8从零搭建一套目标检测系统(修改model结构必看)附一份工业缺陷检测数据集

目录 1.YOLOV8介绍 2.YOLOV8安装 2.1环境配置 3.数据集准备 1.YOLOV8介绍 Yolov8结构图&#xff1a; YoloV8相对于YoloV5的改进点&#xff1a; Replace the C3 module with the C2f module. Replace the first 6x6 Conv with 3x3 Conv in the Backbone. Delete two Convs …

Mysql--事务

事务 开始之前&#xff0c;让我们先想一个场景&#xff0c;有的时候&#xff0c;为了完成某个工作&#xff0c;需要完成多种sql操作 比如转账 再比如下单 第一步 我的账户余额减少 第二步 商品的库存要减少 第三步 订单表中要新增一项 事务的本质&#xff0c;就是为了把多个操…

Excel数学、工程和科学计算插件:FORMULADESK Studio

如果 Excel 是您的武器 - 让我们磨砺您的剑&#xff01;为整天使用 Excel 的人们提供创新的 Excel 加载项&#xff0c;你需要这个 FORMULADESK Studio。。。 Excel 插件为任何使用 Excel 执行数学、工程和科学计算的人提供了必备工具。 * 将公式视为真正的数学方程 * 为您的公…

vue3中如何实现通过点击不同的按钮切换不同的页面

完成以上需求&#xff0c;我们可以使用vue中的component标签来实现。 component是Vue.js中一个特殊的标签&#xff0c;用于动态地绑定其它组件。它可以与v-bind:is指令一起使用&#xff0c;来决定要渲染哪个组件。下面是示例代码 <template><div class"app-conte…

OpenCV 07(图像滤波器)

一、卷积 什么是图片卷积? 图像卷积就是卷积核在图像上按行滑动遍历像素时不断的相乘求和的过程 步长 步长就是卷积核在图像上移动的步幅. 上面例子中卷积核每次移动一个像素步长的结果, 如果将这个步长修改为2, 结果会如何? 为了充分扫描图片, 步长一般设为1. padding …

【操作系统】电脑上没有IIS怎么办

文章目录 前言一、查看二、解决 前言 有的新机刚开始在计算机-管理-服务下没有IIS网络服务怎么办。 一、查看 桌面计算机/此电脑 鼠标右键&#xff1a;管理 服务和应用 发现没有IIS 二、解决 控制面板 程序和功能 启动或关闭Windows功能 IIS相关的所有功能选中&#xff…

【JavaScript】JS语法入门到实战

文章目录 一、初识JavaScript1. 什么是JavaScript&#xff1f;2. JavaScript 和 HTML 和 CSS 之间的关系3. JavaScript的运行过程4. JavaScript的组成 二、JavaScript的书写形式三、变量1. 输入输出2. 变量的使用3. 数据类型 四、运算符五、分支和循环语句1. 分支语句2. 循环语…

将PyCharm中的终端运行前面的PS修改成当前环境

最近使用Pycharm中的Terminal来pip安装一些pakage&#xff0c;发现Terminal运行前面的显示的是PS&#xff0c;然后输入安装指令报错。“python无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。” 解决方法&#xff1a; 只需要在pycharm的设置中修改一些termi…

Java缓存理解

CPU占用&#xff1a;如果你有某些应用需要消耗大量的cpu去计算&#xff0c;比如正则表达式&#xff0c;如果你使用正则表达式比较频繁&#xff0c;而其又占用了很多CPU的话&#xff0c;那你就应该使用缓存将正则表达式的结果给缓存下来。 数据库IO性能&#xff1a;如果发现有大…

基于YOLOv8和WiderFace数据集的人脸目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8和WiderFace数据集的人脸目标检测系统可用于日常生活中检测与定位人脸目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算…

数据结构(C语言版)概念、数据类型、线性表

数据结构&#xff08;C语言&#xff09;基本概念 数据的基本单位 数据的基本单位是位&#xff08;bit&#xff09;和字节&#xff08;byte&#xff09;。位是最小的存储单位&#xff0c;它可以表示一个二进制的0或1。字节由8个位组成&#xff0c;用于表示一个字符或数字。在计…

STM32 Nucleo-144开发板开箱bring-up

文章目录 1. 开篇2. 开发环境搭建2.1 下载官方例程2.2 ST-Link安装 3. STM32F446ZE demo工程3.1 STM32F446ZE简介3.2 跑个demo试一试 1. 开篇 最近做项目&#xff0c;用到STM32F446ZET6这款MCU&#xff0c;为了赶进度&#xff0c;前期软件需要提前开发&#xff0c;于是在某宝买…

基于FPGA的RGB图像转Ycbcr实现,包括tb测试文件以及MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 将FPGA的数据导入到matlab进行显示 2.算法运行软件版本 Vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // E…

企业微信后台管理-关联小程序、H5/web

企业微信后台管理-小程序、web 应用-关联小程序应用-绑定h5(web页面的app)企业微信-工作台 应用-关联小程序 企业微信后台管理地址&#xff0c;管理员扫码登录后台管理&#xff0c;找到应用管理-自建-创建应用/小程序。 填写项目相关信息之后&#xff0c;如下图。 点击关联小…

Cpp/Qtday030908cpp基础

目录 目录 自行封装一个栈的类&#xff0c;包含私有成员属性&#xff1a;栈的数组、记录栈顶的变量 成员函数完成&#xff1a;构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求栈的大小 头文件&#xff1a;stack.h 源文件: stack.cp…