【Spring 事务和事务传播机制】

目录

1 事务概述

1.1 为什么需要事务

1.2 事务的特性

1.3 Spring 中事务的实现

2 Spring 声明式事务

2.1 @Transactional

2.2 @Transactional 的作用范围

2.3 @Transactional 的各种参数

2.3.1 ioslation 

2.4 事务发生了异常,也不回滚的情况

异常被捕获时

3 事务的传播机制 

3.1 定义

3.2 为什么需要事务传播机制

3.3 事务传播机制种类

Propagation.REQUIRED 

 Propagation.SUPPORTS 

 Propagation.MANDATORY

Propagation.REQUIRES_NEW

Propagation.NOT_SUPPORTED

Propagation.NEVER

Propagation.NESTED


1 事务概述

1.1 为什么需要事务

事务定义

将⼀组操作封装成⼀个执⾏单元(封装到⼀起),要么全部成功,要么全部失败。

对于转账来说:

第一步操作:A 账户 -1000 元

第二步操作:B 账户 +1000 元

使用了事务之后,这一组操作要么一起执行成功,要么一起失败。如果没有事务的情况下,有可能第一步成功了,第二步失败了,那么对于 A 来说,它的账户的 1000 块钱就人间蒸发了。

1.2 事务的特性

事务有4 ⼤特性(ACID),原⼦性、持久性、⼀致性和隔离性,具体概念如下:

原⼦性(Atomicity):⼀个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中 间某个环节。事务在执⾏过程中发⽣错误,会被回滚(Rollback)到事务开始前的状态,就像这个 事务从来没有执⾏过⼀样。

⼀致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写⼊的资料必须完 全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以⾃发性地完成预定的⼯ 作。

隔离性(Isolation):数据库允许多个并发事务同时对其数据进⾏读写和修改的能⼒,隔离性可以防⽌多个事务 并发执⾏时由于交叉执⾏⽽导致数据的不⼀致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串⾏化 (Serializable)。

持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

1.3 Spring 中事务的实现

Spring 中事务操作分为两类:

1. 编程式事务(手动写代码操作事务)

2. 声明式事务(利用注解自动开启和提交事务)

2 Spring 声明式事务

MySQL 中,事务有三个重要的操作:开启事务、提交事务、回滚事务,对应的操作命令如下:

-- 开启事务

start transaction;

 

-- 业务执行

  

-- 提交事务

commit;

  

-- 回滚事务

rollback;

而 Spring 声明式事务的实现与 MySQL 事务的实现基本一致,只是前者自动的,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务。

2.1 @Transactional

package com.example.demo.model;import lombok.Data;import java.time.LocalDateTime;@Data
public class UserInfo {private int id;private String username;private String password;private String photo;private LocalDateTime createtime;private LocalDateTime updatetime;private int state;
}
package com.example.demo.mapper;import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper {@Insert("insert into userinfo(username,password) values(#{username},#{password})")int add(UserInfo userInfo);
}
package com.example.demo.service;import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public int add(UserInfo userInfo){return userMapper.add(userInfo);}
}
package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactionalpublic  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("莉丝");userInfo.setPassword("6363");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);int num = 10/0;// 3. 将结果给前端return 0;}
}

启动项目发现,使用了 @Transactional 注解的确回滚了事务:

 可以看到,信息并没有添加到数据库的 userinfo 这表里。

2.2 @Transactional 的作用范围

@Transactional 可以用来修饰方法或类,修饰方法时,只能应用到 public 方法上,其他访问权限均不生效;修饰类时,该注解对该类中所有的 public 方法都生效。

2.3 @Transactional 的各种参数

参数作用
value配置多个事务管理器时,使用该属性指定一个事务管理器
transactionManager
propagation事务的传播行为,默认值为 Propagation.REQUIRED
isolation事务的隔离级别,默认值为 Isolation.DEFAULT
timeout事务的超出时间,默认值为 -1。如果超出该时间限制但事务还没有完成,则自动回滚事务
readOnly是否为只读事务,默认值为 false;
rollbackFor指定触发事务回滚的异常类型,可以多个
rollbackForClassName指定触发事务回滚的异常类名称,可以多个
noRollbackFor指定不回滚事务的异常类型,可以多个
noRollbackForClassName指定不回滚事务的异常类名称,可以多个

2.3.1 ioslation 

根据文章开头的介绍,我们知道事务有四大特性,分别是原子性、一致性、隔离性以及持久性。而这四大特性中,只有隔离性,也就是隔离级别是可以设置的。

事务的隔离级别是用来保障多个并发事务执行更加可控,更符合程序员的预期。

在 Spring 中,可以通过 @Transactional 中的 isolation 属性进行设置。

MySQL 事务隔离级别:

1. READ UNCOMMITTED:读未提交,该隔离级别的事务可以看到其他事务中未提交的数据,⽽未提交的数据可能会发⽣回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读。

2. READ COMMITTED:读已提交,该隔离级别的事务能读取到已经提交事务的数据, 因此它不会有脏读问题。但由于在事务的执⾏中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读。

3. REPEATABLE READ:可重复读,是 MySQL 的默认事务隔离级别,它能确保同⼀事务多次查询的结果⼀致,这就意味着,该级别的事务 A 正在执行,而另一个事务 B 成功插入了一条数据,但由于可重复读要保证每次查询的结果一致,所以 A 就会查询不到这条数据,但是 A 也想插入这条数据,却发现插入不了,这就是幻读。

4. SERIALIZABLE:序列化,事务最⾼隔离级别,它会强制事务排序,使之不会发⽣冲突,从⽽解决了脏读、不可重复读和幻读问题,但因为执⾏效率低,所以真正使⽤的场景并不多。

 

事务隔离级别脏读不可重复读幻读
读未提交
读已提交×
可重复读××
串行化×××

 

● 脏读:⼀个事务读取到了另⼀个事务修改的数据之后,后⼀个事务⼜进⾏了回滚操作,从⽽导致第⼀个事务读取的数据是错误的。

● 不可重复读:⼀个事务两次查询得到的结果不同,因为在两次查询中间,有另⼀个事务把数据修改了。

● 幻读:⼀个事务两次查询中得到的结果集不同,因为在两次查询中另⼀个事务有新增了⼀部分数据。

不同的数据库的隔离级别是不一样的,MySQL 有四种,Oracle 有三种。Spring 的隔离级别为五种,是为了兼容不同的数据库。

Spring 中事务隔离级别包含以下 5 种:

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

2. Isolation.READ_UNCOMMITTED:读未提交,可以读取到未提交的事务,存在脏读。

3. Isolation.READ_COMMITTED:读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重复读。

4. Isolation.REPEATABLE_READ:可重复读,解决了不可重复读,但存在幻读(MySQL默认级别)。

​​​​​​​

5. Isolation.SERIALIZABLE:串⾏化,可以解决所有并发问题,但性能太低。

如果 Spring 的隔离级别与 MySQL 设置的隔离级别不同的时候,以 Spring 设置的隔离级别为主。

Spring 相当于一个客户端,设置了,以 Spring 设置的为主,没有设置时,跟连接的数据库的隔离级别一样,也就是 DEFAULT。

隔离级别枚举的值以 2 的次方,性能更高。

2.4 事务发生了异常,也不回滚的情况

异常被捕获时

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactionalpublic  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("莉丝");userInfo.setPassword("6363");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);try{int num = 10/0;}catch (Exception e){}// 3. 将结果给前端return 0;}
}

 

@Transactional 是AOP,出现异常的时候,代理对象可以感知到异常,并进行事务的回滚。但如果异常被捕获了,外部的代理对象就感知不到了,就不会进行事务的回滚了。

对此有两种解决方案。

1. 将异常继续抛出去,让代理对象感知到异常,也就能自动的回滚事务了。

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactionalpublic  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("埃罗尔");userInfo.setPassword("9146");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);try{int num = 10/0;}catch (Exception e){throw e;}// 3. 将结果给前端return 0;}
}

2.  使用代码,手动回滚事务

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactionalpublic  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("埃罗尔");userInfo.setPassword("9146");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);try{int num = 10/0;}catch (Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}// 3. 将结果给前端return 0;}
}

 在网页没有报错的情况下,进行了事务的回滚。

3 事务的传播机制 

3.1 定义

Spring 事务传播机制定义了多个包含了事务的⽅法,相互调⽤时,事务是如何在这些⽅法间进⾏传递的。

3.2 为什么需要事务传播机制

事务隔离级别是保证多个并发事务执⾏的可控性的(稳定性的),⽽事务传播机制是保证⼀个事务在多个调⽤⽅法间的可控性的(稳定性的)。

8

 

3.3 事务传播机制种类

Propagation.REQUIRED 

默认的事务传播级别,如果当前存在事务,就加入这个事务(加入意味着成为这个外部事务的一部分),如果不存在事务,则会自己创建一个新的事务。与其他被调用的事务,要么一起提交事务,要么一起回滚事务。

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactionalpublic  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("埃罗尔");userInfo.setPassword("9146");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);try{int num = 10/0;}catch (Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}// 3. 将结果给前端return 0;}
}
package com.example.demo.service;import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Transactionalpublic int add(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("add result -> " + result);insert(userInfo);return result;}@Transactionalpublic int insert(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("insert result -> " + result);int num = 10 / 0;return result;}
}

add 调用两个加了@Transactional 的 service 的方法。

 Propagation.SUPPORTS 

如果当前存在事务(存在于别的方法开启的事务中,而不是自己启动事务),则加入该事务;如果没有,则以非事务的方式继续运行。

修改 insert 方法如下,添加 propagation 参数:

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactional(propagation = Propagation.SUPPORTS)public  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("埃罗尔");userInfo.setPassword("9146");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);try{int num = 10/0;}catch (Exception e){
//            throw e;TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}// 3. 将结果给前端return 0;}
}

 对于上述 add 来说,它并没有存在于任何一个事务当中,所以它按照非事务的方式运行。

package com.example.demo.service;import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Transactional(propagation = Propagation.SUPPORTS)public int add(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("add result -> " + result);insert(userInfo);return result;}@Transactional(propagation = Propagation.SUPPORTS)public int insert(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("insert result -> " + result);int num = 10 / 0;return result;}}

service 中, add 被 controller 调用,由于 controller 不存在事务,因此 add 也不存在于任何事务中,所以 add 按照非事务的方式运行,同样对于 insert 来说也是如此,按照非事务的方式运行。

运行结果是:添加了两条信息:

 

如果 controller 的 add 的事务传播机制改成 Propagation.REQUIRED ,其他两个方法不变,结果会怎么样呢?

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactional(propagation = Propagation.REQUIRED)public  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("埃罗尔");userInfo.setPassword("9146");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);try{int num = 10/0;}catch (Exception e){
//            throw e;TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}// 3. 将结果给前端return 0;}
}

 Propagation.MANDATORY

mandatory 强制性的意思。如果当前存在事务,则加入该事务;如果没有事务,则抛出异常。

Propagation.REQUIRES_NEW

表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂 起。也就是说不管外部⽅法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部⽅法会新开 启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰。

Propagation.NOT_SUPPORTED

以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。

Propagation.NEVER

以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactional(propagation = Propagation.REQUIRED)public  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("埃罗尔");userInfo.setPassword("9146");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);try{int num = 10/0;}catch (Exception e){
//            throw e;TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}// 3. 将结果给前端return 0;}
}
package com.example.demo.service;import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Transactional(propagation = Propagation.NEVER)public int add(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("add result -> " + result);insert(userInfo);return result;}@Transactional(propagation = Propagation.NEVER)public int insert(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("insert result -> " + result);int num = 10 / 0;return result;}}

 

运行结果: 

 不添加任何一条信息。

Propagation.NESTED

如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。

嵌套的事务不影响外部的事务。NESTED 嵌套 NESTED ,一个完蛋,所有的 NESTED 都完蛋。

package com.example.demo.controller;import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactional(propagation = Propagation.REQUIRED)public  int add(){// 1. 非空判断UserInfo userInfo = new UserInfo();userInfo.setUsername("玛丽莲·梦露");userInfo.setPassword("18");// 2. 调用 service 执行添加int result = userService.add(userInfo);System.out.println("result:"+result);userService.insert(userInfo);// 3. 将结果给前端return 0;}
}
package com.example.demo.service;import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Transactional(propagation = Propagation.NESTED)public int add(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("add result -> " + result);return result;}@Transactional(propagation = Propagation.NESTED)public int insert(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("insert result -> " + result);try {int num = 10 / 0;}catch (Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
}

如果 insert 方法写成以下这种形式,不但 insert 感知到了异常,调用方感知到了异常,就会造成总体回滚,这就意味着数据无法添加。

    @Transactional(propagation = Propagation.NESTED)public int insert(UserInfo userInfo){int result = userMapper.add(userInfo);System.out.println("insert result -> " + result);int num = 10 / 0;return result;}

而如果对 insert 进行手动回滚操作,这样只有 insert 感知到了异常,但是调用方并没有感知。

为什么把 insert 放在 add 里,也会回滚。


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

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

相关文章

通过 Blob 对二进制流文件下载实现文件保存下载

原理&#xff1a;前端将二进制文件做转换实现下载: 请求后端接口->接收后端返回的二进制流(通过二进制流&#xff08;Blob&#xff09;下载,把后端返回的二进制文件放在 Blob 里面)->再通过file-saver插件保存 页面上使用&#xff1a; <span click"downloadFil…

作为产品经理,有必要考PMP或者NPDP么?

产品经理的核心竞争力是什么? 三点&#xff1a;知识、能力和决策 懂得越多&#xff0c;能力越强&#xff0c;决策越正确&#xff0c;核心竞争力越强。一般来说&#xff0c;看的越多&#xff0c;做的越多&#xff0c;实践出经验才是王道&#xff0c;但是&#xff0c;总有看不…

智慧物流发展的重要推动力量:北斗卫星导航系统

随着经济的快速发展和电商的普及&#xff0c;物流行业的规模不断扩大&#xff0c;对物流运输的效率和安全性也提出了更高的要求。传统的物流运输方式存在着效率低下、信息不对称、安全隐患等问题&#xff0c;因此发展智慧物流已经成为物流行业的必然趋势。智慧物流可以通过先进…

立晶半导体Cubic Lattice Inc 专攻音频ADC,音频DAC,音频CODEC,音频CLASS D等CL7016

概述&#xff1a; CL7016是一款高保真USB Type-C兼容音频编解码芯片。可以录制和回放有24比特音乐和声音。内置回放通路信号动态压缩&#xff0c; 最大42db录音通路增益&#xff0c;PDM数字麦克风&#xff0c;和立体声无需电容耳机驱动放大器。 5V单电源供电。兼容USB 2.0全速工…

深度学习面试八股文(2023.9.06持续更新)

一、优化器 1、SGD是什么&#xff1f; 批梯度下降&#xff08;Batch gradient descent&#xff09;&#xff1a;遍历全部数据集算一次损失函数&#xff0c;计算量开销大&#xff0c;计算速度慢&#xff0c;不支持在线学习。随机梯度下降&#xff08;Stochastic gradient desc…

基于vue-cli创建后台管理系统前端页面——element-ui,axios,跨域配置,布局初步,导航栏

目录 引出安装npm install安装element-ui安装axios 进行配置main.js中引入添加jwt前端跨域配置 进行初始布局HomeView.vueApp.vue 新增页面和引入home页面导航栏总结 引出 1.vue-cli创建前端工程&#xff0c;安装element-ui&#xff0c;axios和配置&#xff1b; 2.前端跨域的配…

记录学习--字节码解析try catch

1.示例代码 Testpublic void someTest() {String s "111";try {s "222";int i 1/0;} catch (Exception e){e.printStackTrace();System.out.println(s);}System.out.println(s);}2.示例代码对应的字节码 0 ldc #2 <111>2 astore_13 ldc #3 <22…

“深入理解SpringMVC的注解驱动开发“

目录 引言1. SpringMVC的常用注解2. SpringMVC的参数传递3. SpringMVC的返回值4. SpringMVC页面跳转总结 引言 在现代的Web开发中&#xff0c;SpringMVC已经成为了一个非常流行和强大的框架。它提供了许多注解来简化开发过程&#xff0c;使得我们能够更加专注于业务逻辑的实现…

【python】TCP socket服务器 Demo

目录 一、单线程服务器 二、多线程服务器 三、多线程服务器&#xff08;发送和接收分离&#xff09; 一、单线程服务器 说明&#xff1a;只能连接一个客户端 import socket,binascii# 创建一个 TCP 套接字 server_socket socket.socket(socket.AF_INET, socket.SOCK_STRE…

nas汇编程序的调试排错方法

nas汇编程序的调试排错方法&#xff1a; 1、查找是哪一步错了 2、查看对应的*.lst文件&#xff0c;本例中是"asmhead.lst" 3、根据*.lst文件的[ERROR #002]提示查看源码&#xff0c;改错。 4、重新运行编译&#xff0c;OK 1、查找是哪一步错了&#xff1a; nask.ex…

基于任务队列的机器学习服务实现

将机器模型部署到生产环境的方法有很多。 常见的方法之一是将其实现为 Web 服务。 最流行的类型是 REST API。 它的作用是全天候&#xff08;24/7&#xff09;部署和运行&#xff0c;等待接收来自客户端的 JSON 请求&#xff0c;提取输入&#xff0c;并将其发送到 ML 模型以预测…

SpringBoot / Vue 对SSE的基本使用(简单上手)

一、SSE是什么&#xff1f; SSE技术是基于单工通信模式&#xff0c;只是单纯的客户端向服务端发送请求&#xff0c;服务端不会主动发送给客户端。服务端采取的策略是抓住这个请求不放&#xff0c;等数据更新的时候才返回给客户端&#xff0c;当客户端接收到消息后&#xff0c;…

http请求头部(header)详解

目录 常见的请求头部字段 GET方法的使用方法&#xff1a; POST方法的使用方法&#xff1a; Accept字段的使用方法 Content-Type字段的使用 总结 在互联网协议中&#xff0c;HTTP请求头部&#xff08;header&#xff09;是一个非常重要的组成部分。它们是客户端和服务器之…

【python自动化】七月PytestAutoApi开源框架学习笔记(一)

前言 本篇内容为学习七月大佬开源框架PytestAutoApi记录的相关知识点&#xff0c;供大家学习探讨 项目地址&#xff1a;https://gitee.com/yu_xiao_qi/pytest-auto-api2 阅读本文前&#xff0c;请先对该框架有一个整体学习&#xff0c;请认真阅读作者的README.md文件。 本文…

【嵌入式软件C编程】主函数free子函数malloc地址的两种方式以及注意事项

本文档主要记录嵌入式C语言在子函数中应用malloc函数的方式&#xff0c;在实际项目中内存管理特别重要 一般在主函数中&#xff08;main&#xff09;使用malloc函数&#xff0c;然后在通过free函数进行释放内存&#xff0c;但有时候如果必须在子函数长调用malloc函数该怎样进行…

基于VueCli创建自定义项目

1.安装脚手架 (已安装) npm i vue/cli -g2.创建项目 vue create hm-exp-mobile选项 Vue CLI v5.0.8 ? Please pick a preset:Default ([Vue 3] babel, eslint)Default ([Vue 2] babel, eslint) > Manually select features 选自定义手动选择功能 选择vue的版本 3.x …

电脑黑屏只有鼠标箭头?4个正确处理方法记得收藏!

“我刚刚在用电脑办公呢&#xff0c;突然之间电脑就黑屏了&#xff0c;只剩下一个鼠标箭头。这是什么原因引起的呢&#xff1f;怎么解决电脑黑屏的问题呀&#xff1f;求解答&#xff01;” 不知道朋友们有没有遇到过在使用电脑时&#xff0c;突然电脑就黑屏了并且只剩下鼠标箭头…

国内免费无限制的chatgpt导航和ai画画

非常实用的AI网址导航&#xff0c;其实际使用体验非常便捷。该导航系统不仅提供了全面的网站分类和搜索功能&#xff0c;还对每个网站进行了精准的评估和排序。推荐高质量的网站资源&#xff0c;并实时检测网站的安全性&#xff0c;保障用户的上网安全。 总的来说&#xff1a…

RHCA之路---EX280(8)

RHCA之路—EX280(8) 1. 题目 On master.lab.example.com using the template file in http://materials.example.com/exam280/gogs as a basis, install an application in the ditto project according to the following requirements: All of the registry entries must poi…

微信小程序源码【195套】【源码导入视频教程+源码导入文档教程+详细图文文档教程】

一、项目说明 盒马鲜生.zip 轻客洗衣.zip 云文档.zip 仿ofo共享单车.zip 仿美团外卖.zip 仿饿了么.zip 灵犀外卖.zip 小契约&#xff08;交友互动小程序&#xff09;.zip 信息科技公司展示小程序.zip 华云智慧园区.zip 房地产公司展示.zip 企业OA系统小程序.zip 优惠券卡卷小程…