Spring事务(2)——@Transaction详解

news2025/4/15 9:58:43

目录

一、rollbackFor

结论:

二、事务隔离级别

1、MySQL 事务隔离级别(回顾)

2、Spring 事务隔离级别

三、Spring 事务传播机制

1、什么是事务传播机制?

2、事务的传播机制有哪些?

3、Spring 事务传播机制使用 和 各种场景演示

(1)REQUIRED(加入事务)

(2)REQUIRES_NEW(新建事务)

(3)NEVER(不支持当前事务,抛异常)

(4)NESTED(嵌套事务)

 当全部都成功时

当部分失败

(5)NESTED和REQUIRED有什么区别


思维导图:

        gitee:https://gitee.com/cool_tao6/studying-java-ee-advanced/tree/master/spring-trans

        代码准备和上篇博客一样,地址:Spring事务(1)-CSDN博客

        通过上篇博客的学习,我们学习了 @Transactional 的基本使用。接下来我们学习 @Transactional 注解的使用细节。

        我们主要学习 @Transactional 注解当中的三个常见属性:

1、rollbackFor异常回滚属性。指定能够触发事务回滚的异常类型。可以指定多个异常类型

2、IsoIation事务的隔离级别。默认值为 IsoIation.DEFAULT

3、propagation事务的传播机制。默认值为:Propagation.REQUIRED


一、rollbackFor

        @Transactional 默认只在 遇到运行时异常Error 时才会回滚,非运行时异常不回滚(即Exception的子类中,除了 RuntimeException 及其子类,都不回滚)。继承关系图如下:

        之前为了演示事务回滚,手动设置了程序异常:

int a = 10 / 0;

        接下来我们把异常改为如下代码:

@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionalController {
    @Transactional
    @RequestMapping("/r2")
    public String r2(String name, String password) throws IOException {
        //用户注册
        Integer ret = userService.registry(name, password);
        log.info("用户数据插入成功");
        if(true) {
            throw new IOException();
        }
        if(ret > 0) return  "注册成功";
        return "注册失败";
    }
}

        把之前数据都删了,重新建表,现在表的元素如图:

        运行程序:127.0.0.1:8080/trans/r2?name="zhangsan"&&password="123",发现事务没有回滚,事务提交了。

        程序虽然发生异常了,但事务仍旧提交了

        如果我们需要所有异常都回滚,需要来配置 @Transactional 注解当中的 rollbackFor属性,通过 rollbackFor 这个属性指定出现何种异常类型时事务进行回滚。

@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionalController {
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/r2")
    public String r2(String name, String password) throws IOException {
        //用户注册
        Integer ret = userService.registry(name, password);
        log.info("用户数据插入成功");
        if(true) {
            throw new IOException();
        }
        if(ret > 0) return  "注册成功";
        return "注册失败";
    }
}

        上面设置 rollbackFor = Exception.class,表示异常是Exception及其子类,都会进行事务回滚

        运行程序:运行程序:127.0.0.1:8080/trans/r2?name="zhangsan"&&password="123",发现事务回滚了。

结论:

1、在 Spring 的事务管理中,默认只在遇到运行时异常 RuntimeException 和 Error 时才会回滚

2、如果需要回滚指定类型的异常,可以通过 rollbackFor 属性来指定


二、事务隔离级别

1、MySQL 事务隔离级别(回顾)

        SQL 标准定义了四种隔离级别,MySQL全都支持。这四种隔离级别分别是:

1、读未提交(READ UNCOMMITTED)读未提交,也叫未提交读。该隔离级别的事务可以看到其他事务中未提交的数据

        因为其他事务未提交的数据可能会发生回滚,但是该隔离级别却可以读到,我们把该级别读到的数据称之为脏数据,这个问题称之为 脏读

2、读已提交(READ COMMITTED)读已提交,也叫提交读。该隔离级别的事务能读取到已经提交事务的数据

        该隔离级别不会有脏读的问题。但由于在事务的执行中可以读到其他事务提交的结果,所以在不同时间的相同 SQL 查询可能会得到不同的结果,这种现象叫作 不可重复读

3、可重复读(REPEATABLE READ)事务不会读到其他事务对已有数据的修改,即使其他事务已提交。也就可以确保同一事务多次查询的结果一致,但是其他事务新插入的数据,是可以感知到的。这也就引发了幻读问题。可重复读,是MySQL的默认事务隔离级别

        比如次级别的事务正在执行时,另一个事务成功的插入了某条数据,但因为它每次查询的结果都是一样的,所以会导致查询不到这条数据,自己重复插入时又失败(因为唯一约束的原因)。明明在事务中查询不到这条信息,但自己就是插入不进去,这个现象叫作 幻读。

4、串行化(SERIALIZABLE)序列化,事务最高隔离级别。它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读、幻读的问题,但因为执行效率低,所以真正使用的场景并不多

        在数据库中通过以下 SQL 查询全局事务隔离级别和当前连接的事务隔离级别:

select @@global.tx_isolation,@@tx_isolation;

        以上的SQL的执行结果如下:

2、Spring 事务隔离级别

        Spring 中事务隔离级别有 5 种

1、Isolation.DEFAULT以连接数据库的事务隔离级别为主

2、Isolation.READ_UNCOMMITTED读未提交,对应 SQL标准中 READ UNCOMMITTED

3、Isolation.READ_COMMITTED读已提交,对应 SQL标准中 READ COMMITTED

4、Isolation.REPEATABLE_READ可重复读,对应 SQL标准中 REPEATABLE READ

5、Isolation.SERIALIZABLE串行化,对应 SQL标准中 SERIALIZABLE

        源码如下:

public enum Isolation {
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);

    private final int value;

    private Isolation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}

        Spring 中事务隔离级别可以通过 @Transactional 中的 isolation 属性进行设置

@Transactional(isolation = Isolation.READ_COMMITTED)
@RequestMapping("/r3")
public String r3(String name,String password) throws IOException {
    //... 代码省略
    return "r3";
}

三、Spring 事务传播机制

1、什么是事务传播机制?

        事务传播机制就是:多个事务方法存在调用关系,事务是如何在这些方法间传播的

        比如有两个方法:A方法、B方法,它们都被 @Transaction 修饰,A方法 调用 B方法。A方法 运行时,会开启一个事务。当 A方法 调用 B方法 时,B方法本身就有事务了,此时 B方法 运行,它是加入 A方法 的事务?还是使用自己的事务?或者是自己新建一个事务呢?

        上述问题就涉及到了事务的传播机制了。

比如公司流程管理:

        执行任务之前,需要先写执行文档,任务执行结束,再写总结汇报,如图:

        此时 A部门 有一项工作,需要 B部门 的支援,此时 B部门 是直接使用 A部门的文档,还是新建一个文档呢?

        事务隔离级别 解决的是多个事务同时调用一个数据库的问题。如图:

        而 事务的传播机制 解决的是一个事务在多个节点(方法)中传递的问题。如图:

2、事务的传播机制有哪些?

        @Transaction 注解支持事务传播机制的设置,通过 propagation 属性来指定传播行为。

        Spring 事务传播机制有以下7种:(方法A 调用 方法B,A -> B,类似 controller -> service

        1、Propagation.REQUIRED默认的传播机制。如果当前存在事务,则加入该事务;如果当前没有事务,则新建一个事务

如果 A 有事务,则用 A 的事务;如果 A 没有,则 B 新建一个事务

        4、Propagation.REQUIRES_NEW创建一个新的事务。如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法都会新开启自己的事务,且开启的事务相互独立

如果 A 有事务,则把 A 的事务挂起,B 新建一个事务

        7、Propagation.NESTED如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行,如果当前没有事务,则该取值等价于 Propagation_REQUIRED

当存在事务,这里的事务当做车、房,嵌套事务就是把车、房抵押给银行,银行给我贷款,我用贷款的钱启动事业;如果生意失败,车、房也没了)。

        2、Propagation.SUPPORTS如果当前存在事务,则加入该事务。如果当前没有事务,则以非事务的方式继续运行

如果 A 有事务,B 就有 A 的事务;如果 A 没有事务,B 就以非事务的方式运行

        5、Propagation.NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则把当前事务挂起(不用)

不管 A 有没有事务,B 都不用,以非事务方式运行

        3、Propagation.MANDATORY强制性。如果当前存在事务,则加入该事物。如果当前没有事务,则抛出异常

如果 A 有事务,B 就加入该事务;如果 A 没有事务,就抛出异常

        6、Propagation.NEVER以非事务方式运行,如果当前存在事务,则抛出异常

A 不能有事务,否则抛出异常

        源码如下:

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);

    private final int value;

    private Propagation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}

3、Spring 事务传播机制使用 和 各种场景演示

        对于以上事务传播机制,我们重点关注一下两个:

1、REQUIRED(默认值)

2、REQUIRES_NEW

(1)REQUIRED(加入事务)

        看下面代码实现:

①用户注册,插入一条数据

②记录操作日志,插入一条数据(出现异常)

        观察 propagation = Propagation.REQUIRED 的执行结果

@RestController
@RequestMapping("/u2")
public class UserController2 {
    @Autowired
    private UserService userService;
    @Autowired
    private LogService logService;

    @Transactional
    @RequestMapping("/register")
    public Boolean register(String userName, String password) {
        /**
         * 用户的插入和日志表的插入,应该在Service完成
         * 为了方便学习,放在Controller里完成
         */
        Integer result = userService.registry(userName, password);
        System.out.println("插入用户表,result" + result);
        //插入日志表
        Integer logResult = logService.insertLog(userName, "用户注册");
        System.out.println("插入用户表,logResult" + logResult);
        return true;
    }
}

@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer registry(String name, String password) {
        return userInfoMapper.insert(name, password);
    }
}

@Service
public class LogService {
    @Autowired
    private LogInfoMapper logInfoMapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public Integer insertLog(String name, String op) {
        //记录用户操作
        return logInfoMapper.insertLog(name, op);
    }
}

        现在的Controller、userService、logService各自都有事务,Controller使用的是默认的传播机制,也就是Propagation.REQUIRED,而userService和logService使用的也是Propagation.REQUIRED,所以它们三个共用同一个事务,也就是共存亡。

当程序没有错误时,启动程序

        URL:127.0.0.1:8080/u2/register?userName=lisi&password=123456

        都插入成功了。

现在修改LogService成错误的,代码如下:

@Service
public class LogService {
    @Autowired
    private LogInfoMapper logInfoMapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public Integer insertLog(String name, String op) {
        //记录用户操作
        Integer result = logInfoMapper.insertLog(name, op);
        int a = 10 / 0;
        return result;
    }
}

        因为出错了,所以LogService肯定会回滚,因为Controller、userService、logService共用一个事务,所以其他俩个也肯定会回滚。

当有错误时,重新启动程序

         URL:127.0.0.1:8080/u2/register?userName=lisi&password=123456

        数据库也就不会新增数据了,如图:

        日志里也没有显示提交committing的字样。

        关系图如下:

(2)REQUIRES_NEW(新建事务)

        代码如下:

@RestController
@RequestMapping("/u2")
public class UserController2 {
    @Autowired
    private UserService userService;
    @Autowired
    private LogService logService;

    @Transactional
    @RequestMapping("/register")
    public Boolean register(String userName, String password) {
        /**
         * 用户的插入和日志表的插入,应该在Service完成
         * 为了方便学习,放在Controller里完成
         */
        Integer result = userService.registry(userName, password);
        System.out.println("插入用户表,result" + result);
        //插入日志表
        Integer logResult = logService.insertLog(userName, "用户注册");
        System.out.println("插入用户表,logResult" + logResult);
        return true;
    }
}

@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Integer registry(String name, String password) {
        return userInfoMapper.insert(name, password);
    }
}

@Service
public class LogService {
    @Autowired
    private LogInfoMapper logInfoMapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Integer insertLog(String name, String op) {
        //记录用户操作
        Integer result = logInfoMapper.insertLog(name, op);
        int a = 10 / 0;
        return result;
    }
}

        REQUIRES_NEW是不管当前有没有事务,都会新建一个事务,而且新建的事务都是相互独立的。

现在运行程序,logService中是有错误的。

        URL:127.0.0.1:8080/u2/register?userName=wangwu&password=1234

        看看数据库里的内容

        可以看到logService发生错误后回滚了,但userService没有。

        关系图如下:

(3)NEVER(不支持当前事务,抛异常)

        代码如下:

@RestController
@RequestMapping("/u2")
public class UserController2 {
    @Autowired
    private UserService userService;
    @Autowired
    private LogService logService;

    @Transactional
    @RequestMapping("/register")
    public Boolean register(String userName, String password) {
        /**
         * 用户的插入和日志表的插入,应该在Service完成
         * 为了方便学习,放在Controller里完成
         */
        Integer result = userService.registry(userName, password);
        System.out.println("插入用户表,result" + result);
        return true;
    }
}

@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Transactional(propagation = Propagation.NEVER)
    public Integer registry(String name, String password) {
        return userInfoMapper.insert(name, password);
    }
}

        Controller有事务了,因为Propagation.NEVER是不支持有事务的,会抛出异常,运行程序

        URL:http://127.0.0.1:8080/u2/register?userName=zhaoliu&password=1234

        数据并没有添加成功

        关系图如下:

(4)NESTED(嵌套事务)

        代码如下:

@RestController
@RequestMapping("/u2")
public class UserController2 {
    @Autowired
    private UserService userService;
    @Autowired
    private LogService logService;

    @Transactional
    @RequestMapping("/register")
    public Boolean register(String userName, String password) {
        /**
         * 用户的插入和日志表的插入,应该在Service完成
         * 为了方便学习,放在Controller里完成
         */
        Integer result = userService.registry(userName, password);
        System.out.println("插入用户表,result" + result);
        //插入日志表
        Integer logResult = logService.insertLog(userName, "用户注册");
        System.out.println("插入用户表,logResult" + logResult);
        return true;
    }
}

@Service
public class LogService {
    @Autowired
    private LogInfoMapper logInfoMapper;

    @Transactional(propagation = Propagation.NESTED)
    public Integer insertLog(String name, String op) {
        //记录用户操作
        Integer result = logInfoMapper.insertLog(name, op);
        //int a = 10 / 0;
        return result;
    }
}

@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Transactional(propagation = Propagation.NESTED)
    public Integer registry(String name, String password) {
        return userInfoMapper.insert(name, password);
    }
}

        这里只演示存在事务时,创建一个事务作为当前事务的嵌套事务来运行,如果不存在事务,就会创建一个,和REQUIRED是一样的。

        三个事务全部正常的情况下,运行程序,

URL:http://127.0.0.1:8080/u2/register?userName=zhaoliu&password=1234

 当全部都成功时

        是和REQUIRED是一样的,日志内容如下:

        数据库:

当部分失败

        其他不变,logService的代码如下:

@Service
public class LogService {
    @Autowired
    private LogInfoMapper logInfoMapper;

    @Transactional(propagation = Propagation.NESTED)
    public Integer insertLog(String name, String op) {
        //记录用户操作
        Integer result = logInfoMapper.insertLog(name, op);
        int a = 10 / 0;
        return result;
    }
}

        运行程序,URL:http://127.0.0.1:8080/u2/register?userName=zhouba&password=1234

        日志信息:

        数据库:

        都没有新增数据。

        说明两次插入的操作都进行回滚了。

        这里也能看出,如果部分失败,还是和REQUIRED一样的。

关系图如下:

(5)NESTED和REQUIRED有什么区别

        而和REQUIRED相比,NESTED可以部分回滚。

        其他部分和之前的一样,LogService代码如下:

@Service
public class LogService {
    @Autowired
    private LogInfoMapper logInfoMapper;

    @Transactional(propagation = Propagation.NESTED)
    public Integer insertLog(String name, String op) {
        //记录用户操作
        Integer result = logInfoMapper.insertLog(name, op);
        try{
            int a = 10 / 0;
        }catch (Exception e) {
            //回滚当前事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }
}

        运行程序,URL:127.0.0.1:8080/u2/register?userName=zhouba&password=1234

        数据库:

        可以看到只有logService回滚了,userService数据插入成功了,并没有回滚,实现了部分回滚的功能。

        如果是REQUIRED有部分回滚的话,那其余全部事务也会回滚。

        嵌套事务之所以能够实现部分事务的回滚,是因为事务中有一个保存点(savepoint)的概念,嵌套事务进入之后相当于新建了一个保存点,而回滚时只回滚到当前保存点。

        资料参考:MySQL :: MySQL 5.7 Reference Manual :: 13.3.4 SAVEPOINT, ROLLBACK TO SAVEPOINT, and RELEASE SAVEPOINT Statements

        REQUIRED是加入到当前事务中,并没有创建事务的保存点,因此出现了回滚就是整个事务回滚,这就是嵌套事务和REUQIRED(加入事务的区别。)


四、总结

1、Spring中使用事务,有两种方式:编程式事务(手动操作)和声明式事务。其中声明式事务使用较多,在方法添加@Transactional 就可以实现了。

2、通过@Transactional(isolation = Isolation.SERIALIZABLE)设置事务的隔离级别。Spring中的事务给级别有5种。

3、通过@TransactionAl(propagation = Propagation.REQUIRED) 设置事务的传播机制,Spring中的事务传播机制有7种,重点关注REQUIRED(默认值)和REQUIRES_NEW。

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

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

相关文章

基于SpringBoot技术的家具网站设计与实现

你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。 开发语言:Java 数据库:MySQL 技术:SpringBoot框架 工具:Eclipse、Navicat 系统展示 首页 家具详情界面 购物车界面 订单…

Python 数据分析— Pandas 基本操作(上)

文章目录 学习内容:一、Series 创建及操作二、DataFram 的创建与操作三、Pandas 的读写操作四、选择指定行列数据 学习内容: 一、Series 创建及操作 ** Series : Pandas 的一种数据结构形式,可理解为含有索引的一维数组。** **(…

Python | Leetcode Python题解之第390题消除游戏

题目&#xff1a; 题解&#xff1a; class Solution:def lastRemaining(self, n: int) -> int:a1 1k, cnt, step 0, n, 1while cnt > 1:if k % 2 0: # 正向a1 stepelse: # 反向if cnt % 2:a1 stepk 1cnt >> 1step << 1return a1

【IPV6从入门到起飞】2-1 获取你的IPV6(手机、CPE等)

【IPV6从入门到起飞】2-1 获取你的IPV6&#xff08;手机、CPE等&#xff09; 1 IPV6就在身边2 手机IPV62.1 查看IPV62.2 IPV6 ping包测试2.3 IPV6入站测试 3 电脑通过CPE获取IPV63.1 拉不起宽带的打工人3.2 开始部署IPV6环境3.2.1 刷系统3.2.2 激活IPV63.2.3 设置防火墙入站&am…

Opencv实现提取卡号(数字识别)

直接开始 实行方法 解析命令行参数&#xff1a;使用argparse库来解析命令行输入&#xff0c;确保用户提供了输入图像和模板图像的路径。 读取模板图像&#xff1a;使用cv2.imread()函数读取模板图像的路径&#xff0c;并显示原始图像。 图像预处理&#xff1a; 将图像转换为…

ARM——结构体系(处理器工作模式,CPSR,立即数,汇编语言函数调用)

1、处理器工作模式 ARM有7个基本工作模式: User:非特权模式&#xff0c;大部分任务执行在这种模式FIQ:当一个高优先级(fast)中断产生时将会进入这种模式 IRQ:当一个低优先级(normal)中断产生时将会进入这种模式 Supervisor:当复位或软中断指令执行时将会进入这种模式 Abort:当存…

CAN总线数据帧的帧结构

CAN总线中的信息是以固定格式的“帧”发送的&#xff0c;当总线为空闲时&#xff0c;任何已连接的节点都可以开始发送一个新的“帧”。 在一个CAN系统中&#xff0c;数据在节点之间的发送和接收主要通过四种不同类型的“帧”来执行和控制。这四种类型分别是数据帧、远程帧、错…

探索ArrayList的线程不安全性

文章目录 概要示例代码原因解决用 synchronized 保证安全添加元素其他方法 总结 概要 要测试ArrayList的线程不安全性&#xff0c;可以创建多个线程同时对 ArrayList 进行修改操作&#xff08;如添加、删除元素&#xff09;&#xff0c;并观察是否会引发异常或数据不一致的问题…

Typescript实现react-redux的useSelector和useDispatch的状态定义

背景&#xff1a;react中使用typescript,在引入redux之后很多状态定义有问题&#xff0c;记录下来&#xff08;文章记录学习react-redux过程中的踩坑&#xff09;。 1.useSelector时&#xff0c;state语法报错&#xff0c;类型为unknown,如下图 我的store状态设置的很简单&am…

Luminar Neo for Mac智能图像处理软件【操作简单,轻松上手】

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…

【机器学习】LSTM(长短期记忆网络)详解

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 LSTM(长短期记忆网络)详解LSTM的基本思想LSTM的前向传播过程LSTM在实际任务中的…

mysql高级知识之集群

一、安装 源码编译MySQL,若需要MySQLtar包可私信我 #创建数据目录 mkdir /data/mysql -p#安装相关依赖 yum install libtirpc-devel-0.2.4-0.16.el7.x86_64.rpm yum install cmake gcc-c++ openssl-devel ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen…

C++入门day3-面向对象编程(中)

前言&#xff1a;C入门day2-面向对象编程&#xff08;上&#xff09;-CSDN博客 运算符重载 我们接触过函数重载&#xff0c;就是同名的函数有不同的功能。那么运算符重载&#xff0c;顾名思义也是赋予运算符其他的功能。在这里&#xff0c;我个人以为&#xff0c;运算符就是特…

C/C++语言基础--函数基础(函数定义、调用、生命周期、递归)

本专栏目的 更新C/C的基础语法&#xff0c;包括C的一些新特性 前言 函数是语言的基本组成部分&#xff0c;也是面向对象编程的基石&#xff0c;他体现了封装的思想&#xff0c;代码的复用的功能。欢迎点赞 收藏 关注&#xff0c;本人将会持续更新 文章目录 函数什么是函数&am…

彩漩科技亮相第一届人工智能教育应用论坛,荣获AI教育科技产品TOP30奖项

近日&#xff0c;由中国教育发展战略学会人工智能与机器人教育专业委员会指导&#xff0c;北京教育信息化产业联盟主办的第一届人工智能教育应用论坛暨 AI 教育科技成果展在北京隆重举办。本次活动以“ AI 强校大时代 —— 用新质生产力打造金钥匙强校”为主题&#xff0c;汇聚…

vector 常见函数

目录 一.vector 构造函数 二 . Iterators 迭代器&#xff08;random access iterator&#xff09; 三.Capacity: 空间 3.1 resize 3.2 reserve 四.Element access: 元素访问 方式 4.1 operator[] 类似于数组的 [] 4.2 front 和back 五.Modifiers: 六.vector 的 二…

数据结构(单向链表)

单向链表代码 #ifndef _LINK_H_#define _LINK_H_typedef int DataType;typedef struct node {DataType data;struct node *pnext; }Link_Node_t;typedef struct link {Link_Node_t *phead;int clen; }Link_t;extern Link_t *link_creat(); extern int push_link_head(Link_t *…

智慧公厕技术应用、系统架构、应用功能有哪些?@卓振思众

智慧公厕的标准涵盖了多个方面&#xff0c;包括技术应用、系统架构、应用功能以及环保节能等。以下是【卓振思众】整理的一些标准要点&#xff1a; 技术应用‌物联网技术‌&#xff1a;通过无线传感器、监控设备等实时采集公厕内部环境数据。‌大数据与云计算‌&#xff1a;对数…

2157. 优秀的拆分(power)

代码 #include<bits/stdc.h> using namespace std; int a[10001]; int main() {int n,t1,k0;bool flagfalse;cin>>n;if(n%21) {cout<<-1;return 0;}while(n>0){if(n%21){k;a[k]t; }nn/2;tt*2;}if(k>1) {flagtrue;for(int ik;i>1;i--)cout<&l…

lit-llama代码解析

https://github.com/Lightning-AI/lit-llama/blob/main/README.md 下载的时候会报错误&#xff0c;因为网不行&#xff0c;一种方法就是多次尝试&#xff0c;另一种方法是终端连上代理下载 pycharm连接hugging face等网站_hugging face怎么连接-CSDN博客 根据指引下载权重 下…