【SpringBoot详细教程】-13-SpringBoot整合事务管理 【持续更新】

news2024/11/25 4:51:44

      Hello,大胸弟们,我们又又又见面了,今天攀哥继续为大家分享一下SpringBoot的教程,没点关注的宝宝,点一下关注。 

🌲 事务管理的意义

🌿 身边事务的案例:

  • 桃子向好友攀哥汇款5000元,汇款动作主要有两个

        1) 桃子的银行账户上扣除5000元

        2) 攀哥的银行账户上增加5000元

  • 假设操作1)成功了,而操作2)失败了,桃子平白无故少了5000元,而攀哥的账户上也没有增加5000,桃子亏大发了,攀哥饿死了。。。
  • 银行需要用技术保证操作1)和操作2) 整体的原子性(即1和2同时成功或者同时失败),由此数据库的事务需求就产生了。

🌿 事务的4大特性:

  • 原子性: 一个事务中的所有操作,要么全部提交成功,要么全部失败,不能出现部分成功,部分失败的情况。
  • 一致性:事务的执行不能影响数据库数据的完整性和一致性,数据必须从一个一致性状态到另一个一致性状态。
  • 隔离性:不同事务之间互不干扰,比如并发环境中,一个事务的执行不能被其他事务干扰。桃子向攀哥汇款、景甜也向攀哥汇款,两个事务互不干扰。
  • 持久性: 事务一旦提交,那么对数据库中数据的操作将永远保留,及时停电或者服务器宕机数据也不会丢失。

🌿 实现事务的分类

🍁 编程式事务管理

是指将事务管理代码嵌入到业务方法中去控制事务的提交和回滚,需要在每个业务中包含额外的事务管理代码。

🍁 声明式事务管理

是指将事务管理代码从业务方法中分离出去,以声名的方式实现事务控制,大多数情况下声名式事务比编程式事务管理更好用,主要是通过SpringAop框架去支持声名式事务。

Spring并不直接管理事务,而是通过内置事务管理器实现事务

🌲 Spring声明式事务的注解

Spring事务注解主要有@EnableTransactionManagement 和@Transactional

@EnableTransactionManagement 表示开启事务管理(目前SpringBoot已经支持事务管理,所以无需再到启动类中添加此注解了)

@Transactional 作用在方法上表示该方法会进行事务管理。

  • 数据表如下:
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
  `empno` int NOT NULL AUTO_INCREMENT,
  `ename` varchar(20) DEFAULT NULL,
  `job` varchar(20) DEFAULT NULL,
  `manager` int DEFAULT NULL,
  `hiredate` date DEFAULT NULL,
  `salary` double DEFAULT NULL,
  `comm` double DEFAULT NULL,
  `deptno` int DEFAULT NULL,
  PRIMARY KEY (`empno`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES ('1', '郭靖', 'clerk', '4', '2022-02-03', '7000', '2000', '2');
INSERT INTO `emp` VALUES ('2', '黄蓉', 'saleman', '4', '2023-02-01', '6000', '5000', '3');
INSERT INTO `emp` VALUES ('3', '江湖骗子', 'saleman', '4', '2023-02-18', '7000', '3000', '3');
INSERT INTO `emp` VALUES ('6', '孙尚香', '业务人员', '3', '2023-05-23', '5000', '0', null);
INSERT INTO `emp` VALUES ('7', '赵四', '舞者', '1', '2023-05-30', '5000', '5000', '4');
INSERT INTO `emp` VALUES ('8', '张飞', '开发', '1', '2023-05-30', '8000', '2000', '3');
INSERT INTO `emp` VALUES ('9', '关羽', '运维', '1', '2023-05-30', '6000', '4000', '3');
INSERT INTO `emp` VALUES ('16', '孙尚香', '业务人员', '3', '2023-10-05', '5000', null, null);
INSERT INTO `emp` VALUES ('17', '孙尚香', '业务人员', '3', '2023-10-05', '5000', null, null);


DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `location` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES ('1', '销售部', '上海');
INSERT INTO `dept` VALUES ('2', '技术部', '深圳');
INSERT INTO `dept` VALUES ('3', '运营部', '武汉');

  • 实体类Emp.java:
package com.moxuan.boot_02_mp.entity;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Emp {

    private Long empno;
    private String ename;
    private String job;
    private Long manager;
    private java.sql.Date hiredate;
    private double salary;
    private double comm;
    private Long deptno;

}
  • 实体类:Dept.java
package com.moxuan.boot_02_mp.entity;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {

  private long id;
  private String name;
  private String location;

}
  • DeptMapper 和EmpMapper
package com.moxuan.boot_02_mp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.moxuan.boot_02_mp.entity.Emp;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface EmpMapper extends BaseMapper<Emp> {
}

package com.moxuan.boot_02_mp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.moxuan.boot_02_mp.entity.Dept;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DeptMapper extends BaseMapper<Dept> {
}
  • TransactionService业务层
package com.moxuan.boot_02_mp.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.moxuan.boot_02_mp.entity.Emp;
import com.moxuan.boot_02_mp.mapper.DeptMapper;
import com.moxuan.boot_02_mp.mapper.EmpMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TransactionService {
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private DeptMapper deptMapper;
    
    public void deleteDept(int id){
        deptMapper.deleteById(id);
        System.out.println(5/0);
        deptMapper.selectList(null);
    }
}
  • 控制层代码:
package com.moxuan.boot_02_mp.controller;

import com.moxuan.boot_02_mp.service.TransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TransactionController {
    @Autowired
    private TransactionService service;

    @RequestMapping("/tran1")
    public String transaction(){
        service.deleteDept(2);
        return "";
    }
}

运行之后,会发现,在deleteDept方法中,我们有两个操作数据库的手段,一个时删除数据,一个是查询数据。但是在删除数据之后,我们手动制造了一个异常,发生异常后,后面的查询语句将不会被执行。而异常发生之前的语句会执行,也就是删除操作会正常进行。

我们在业务层的方法上面添加@Transactional注解,代码如下:

@Service
public class TransactionService {
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private DeptMapper deptMapper;

    @Transactional
    public void deleteDept(int id){
        deptMapper.deleteById(id);
        System.out.println(5/0);
        deptMapper.selectList(null);
    }
}

再次运行之后,会发现,当发生异常之后,会发现删除的sql语句虽然执行了,但是数据库中的数据却没有被删除。

这是因为方法添加了@Transactional注解后,该方法将会被纳入事务管理。而事务具有原子性,事务中的语句要么全部成功,要么全部失败。而删除语句在发生异常之前虽然执行成功了,而后面的查询语句,由于前面发生了异常并没有执行到,也就执行失败了,故而前面删除操作会被回滚。

此外@Transactional可以设置read-only属性,表示是否仅为可读。默认为false,比如下面代码:

@Transactional(readOnly = false)
public void deleteEmpByDept(int deptNO){
        QueryWrapper<Emp> qw = new QueryWrapper<>();
        qw.lambda().eq(Emp::getDeptno,deptNO);
        empMapper.delete(qw);
}

我们修改一下控制器代码,调用此方法,代码如下:

@RestController
public class TransactionController {
    @Autowired
    private TransactionService service;

    @RequestMapping("/tran1")
    public String transaction(){
        service.deleteEmpByDept(2);
        return "";
    }
}

运行之后,会发现当read-only为false的时候,可以正常删除。

接下来,我们将read-only修改为true,代码如下:

@Transactional(readOnly = true)
public void deleteEmpByDept(int deptNO){
        QueryWrapper<Emp> qw = new QueryWrapper<>();
        qw.lambda().eq(Emp::getDeptno,deptNO);
        empMapper.delete(qw);

}

控制器代码不变,进行测试,测试之后发现会出如下异常:

表示当前连接仅为可读,不能作为修改。所以总结一下:

  • 增删改操作,需要修改数据库数据的,read-only用false
  • 查询操作,read-only用true

由于Spring事务的回滚会自动回滚发生的runtimeException异常,也就是当发生异常之后事务会自动检测到,比如下面案例中:

@Transactional
public void deleteDeptAndEmp(){
    deleteDept(3);
    System.out.println(5/0);
    deleteEmpByDept(3);
}

我们在方法中想要删除部门号为3的部门以及部门号为3的所有员工,测试代码如下:

package com.moxuan.boot_02_mp.controller;

import com.moxuan.boot_02_mp.service.TransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TransactionController {
    @Autowired
    private TransactionService service;
    
    @RequestMapping("/tran1")
    public String transaction(){
       service.deleteDeptAndEmp();
        return "";
    }
}

当运行项目之后,访问请求,会出现如下结果:

在发生异常之前,删除部门的操作执行了,但是去数据库看,部门号为3的部门依旧存在,说明最终事务回滚了。

那如果,我们将异常手动处理了,会出现什么样的状况???看如下代码,我们在deleteDept中捕获一下异常:

package com.moxuan.boot_02_mp.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.moxuan.boot_02_mp.entity.Emp;
import com.moxuan.boot_02_mp.mapper.DeptMapper;
import com.moxuan.boot_02_mp.mapper.EmpMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TransactionService {
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private DeptMapper deptMapper;

    @Transactional
    public void deleteDept(int id){
        deptMapper.deleteById(id);
        try {
            System.out.println(5 / 0);
        }catch (Exception e){
            e.printStackTrace();
        }
        deptMapper.selectList(null);
    }



    @Transactional(readOnly = true)
    public void deleteEmpByDept(int deptNO){
        QueryWrapper<Emp> qw = new QueryWrapper<>();
        qw.lambda().eq(Emp::getDeptno,deptNO);
        empMapper.delete(qw);

    }


    @Transactional
    public void deleteDeptAndEmp(){
        deleteDept(3);
        deleteEmpByDept(3);
    }
}

然后在控制层调用deleteDeptAndEmp()方法,代码如下:

package com.moxuan.boot_02_mp.controller;

import com.moxuan.boot_02_mp.service.TransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TransactionController {
    @Autowired
    private TransactionService service;

    @RequestMapping("/tran1")
    public String transaction(){
       service.deleteDeptAndEmp();

        return "";
    }
}

运行起来之后,会发现虽然发生了异常,但是部门号为3的部门和部门号为3的员工都会被删除,结果如下:

因此只有当显示触发抛出异常的时候,事务管理才能将其检测到。处理之后的异常将不会触发事务管理。

🍁 rollbackfor和noRollbackfor

运行时异常(RuntimeException):默认都回滚。 int a=1/0

编译时异常(RuntimeException以外的异常):默认不回滚。 throw IOException

在@Transactional注解中如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚

先看看异常分类:

当然,我们也可以指定当发生某个指定异常的时候才发生回滚,也可以指定当发生某个异常的时候不回滚。

  • rollbackFor 当发生哪些指定编译异常时发生回滚
   /**
     * rollbackFor 可以指定哪些编译型异常发生回滚
     * @throws SQLException
     * @throws IOException
     */
    @Transactional(rollbackFor = {IOException.class,SQLException.class})
    public void updateDept1() throws SQLException,IOException {
        Dept dept = new Dept();
        dept.setId(1L);
        dept.setName("打铁部5");
        deptMapper.updateById(dept);
//       throw new IOException("IO异常");
        throw new MyException("自定义异常");// 运行异常,默认都是回滚的

    }

上面代码配置的

rollbackFor = {IOException.class,SQLException.class})

表示当发生IOException和SQLException的时候会回滚。

  • noRollbackFor 当发生哪些指定的运行异常时,不发生回滚
 /**
     * noRollbackFor 可以指定哪些运行时异常不发生回滚
     * @throws SQLException
     * @throws IOException
     */
    @Transactional(noRollbackFor = {MyException.class,ArithmeticException.class})
    public void updateDept2() throws SQLException,IOException {
        Dept dept = new Dept();
        dept.setId(1L);
        dept.setName("打铁部1");
        deptMapper.updateById(dept);
        throw new ArithmeticException("运行时异常");

    }

  • 由于运行时异常默认回滚,编译异常默认不回滚。如果需要同时指定哪些编译异常回滚和哪些运行时异常不会滚,该如何写?
  • rollbackfor 和noRollbackfor可以同时使用
  /**
     * rollbackFor 可以指定哪些编译型异常发生回滚
     * @throws SQLException
     * @throws IOException
     */
    @Transactional(rollbackFor = {IOException.class,SQLException.class} ,noRollbackFor = {MyException.class})
    public void updateDept1() throws SQLException,IOException {
        Dept dept = new Dept();
        dept.setId(1L);
        dept.setName("打铁部5");
        deptMapper.updateById(dept);
//       throw new IOException("IO异常");
        throw new MyException("自定义异常");// 运行异常,默认都是回滚的

    }

🌲SpringBoot 事务隔离级别

定义了一个事务不受其他事务影响的程度。

🌿 数据库事务隔离级别:

  • 读未提交(Read Uncommitted):允许脏读,

在这个隔离级别下,一个事务可以读取另一个未提交的事务的数据。这种隔离级别的优点是并发性最高,但是数据的一致性最差。因为一个事务可能会读取到另一个事务未提交的数据,导致数据不一致。

事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。

分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读

  • 读已提交(Read Committed):

在这个隔离级别下,一个事务只能读取另一个已提交的事务的数据。这种隔离级别的优点是数据的一致性比较好,但是并发性比较差。因为一个事务必须等另一个事务提交之后才能读取它的数据。

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他买单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…

分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。(收费系统的两次读取)

  • 可重复读(Repeatable Read):

在这个隔离级别下,一个事务可以多次读取同一行数据,而且每次读取的结果都是一样的。这种隔离级别的优点是数据的一致性比较好,但是并发性比较差。因为一个事务必须锁定读取的数据,以防止另一个事务修改它。

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。

分析:可重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作

什么时候会出现幻读?

事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。

  • 序列化(Serializable):

在这个隔离级别下,所有的事务都会被串行化执行。这种隔离级别的优点是数据的一致性最好,但是并发性最差。因为所有的事务都必须等待前一个事务执行完毕之后才能执行。

隔离级别越高,数据的一致性和隔离性就越好,但也会带来更多的性能开销和系统负担。在实际应用中,需要根据具体的业务需求和系统性能要求,选择合适的隔离级别。

🌿 四种隔离级别可能导致的问题:

🍁 问题描述

1、Serializable (串行化):最严格的级别,事务串行执行,资源消耗最大;

2、REPEATABLE READ(重复读) :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但不能避免“幻读”,但是带来了更多的性能损失。

3、READ COMMITTED (提交读):大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”,但不能避免“幻读”和“不可重复读取”。该级别适用于大多数系统。

4、Read Uncommitted(未提交读) :事务中的修改,即使没有提交,其他事务也可以看得到,会导致“脏读”、“幻读”和“不可重复读取”。

🍁 什么是脏读?

所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。

也就是说,当前事务读到的数据是别的事务想要修改的但是没有修改成功的数据。

🍁 什么是不可重复读?

事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了

也就是说,当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配,也就照应了不可重复读的语义。

🍁 什么是幻读?

事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。

也就是说,当前事务读第一次取到的数据比后来读取到数据条目不一致。

🌿 SpringBoot中事务的隔离级别设置

  • ISOLATION_DEFAULT : 采用数据库默认的事务隔离级别,与数据库隔离级别保持一致
  • ISOLATION_READ_UNCOMMITTED : 对应数据库的读未提交(Read Uncommitted)
  • ISOLATION_READ_COMMITTED :对应数据库的读已提交(Read Committed)
  • ISOLATION_REPEATABLE_READ:对应数据库的可重复读(Repeatable Read)
  • ISOLATION_SERIALIZABLE:序列化(Serializable)

设置隔离级别:在@Transactional中添加isolation

    /**
     * rollbackFor 可以指定哪些编译型异常发生回滚
     * @throws SQLException
     * @throws IOException
     */
@Transactional(isolation = Isolation.READ_COMMITTED ,rollbackFor = {IOException.class,SQLException.class} ,noRollbackFor = {MyException.class})
public void updateDept1() throws SQLException,IOException {
        Dept dept = new Dept();
        dept.setId(1L);
        dept.setName("打铁部5");
        deptMapper.updateById(dept);
//       throw new IOException("IO异常");
        throw new MyException("自定义异常");// 运行异常,默认都是回滚的

}

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

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

相关文章

STL之set、map的使用

STL之set、map 1. 序列式容器和关联式容器2. set系列的使⽤参考文档链接&#xff1a;2.1 set的介绍&#xff08;2&#xff09;set的增删查2.2 multiset的介绍 3 map3.1 参考文档3.2 map类的介绍3.3 pair类型介绍3.4 map的构造3.6 map的数据修改3.7 multimap和map的差异 1. 序列…

鸿蒙next 电商实战项目 来了

前言&#xff1a; 最新在学习鸿蒙next 开发 就写了一个demo 今天就分享给大家一下 效果图 客户端实现 1 底部导航器实现 import choice from ../view/ChoicePage import HomePage from ../view/HomePage import MyPage from ../view/MyPage import Shoppingcar from ../view…

【Canvas与诗词】要做一棵树,站成永恒

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>要做一棵树站成永恒</title><style type"text/css&quo…

电阻负载柜的工作原理是什么?

电阻负载柜是用于模拟电力系统中各种负载的设备&#xff0c;它可以模拟实际负载的各种特性&#xff0c;如阻性、感性和容性负载。电阻负载柜在电力系统、电气设备测试和维护等领域具有广泛的应用。其工作原理主要包括以下几个方面&#xff1a; 电阻负载柜的核心部分是电阻元件…

根据请求错误的状态码判断代理配置问题

SafeLine&#xff0c;中文名 “雷池”&#xff0c;是一款简单好用, 效果突出的 Web 应用防火墙(WAF)&#xff0c;可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注入、命…

后端——eclipse实现前端后端的交互(1)

1.创建Web Project 首先&#xff0c;为实现前端后端交互&#xff0c;要将HTML文件和Java后端文件放入eclipse。 右键—>New—>Project—>选择“Dynamic Web Project” 创建完成 这里我们会看到报了一个错&#xff1a; Description Resource Path Location Typ…

GC1262E替代APX9262S/茂达芯片在笔记本和显卡风散热风扇中的应用分享

随着移动计算和高性能图形处理技术的不断进步&#xff0c;笔记本电脑和显卡的散热需求日益增加。散热风扇作为关键组件&#xff0c;其控制芯片的选择对系统性能和用户体验有着直接影响。本文将探讨芯麦的GC1262E芯片如何替代APX9262S/茂达芯片&#xff0c;应用于笔记本和显卡的…

持续研发赋能,强达电路具备多项核心技术

深圳市强达电路股份有限公司&#xff08;以下简称&#xff1a;强达电路或公司&#xff09;深耕PCB行业二十年&#xff0c;主营业务为PCB的研发、生产和销售&#xff0c;是一家主要专注于中高端样板和小批量板产品的PCB企业。公司2004年创立于深圳&#xff0c;抓住国内早期缺少中…

面试宝典:揭秘50个大型模型核心问题精选

我精选50个大模型高频面试题&#xff0c;分享给大家 简述GPT和BERT的区别讲一下GPT系列模型是如何演进的&#xff1f;为什么现在的大模型大多是decoder-only的架构&#xff1f;讲一下生成式语言模型的工作机理哪些因素会导致LLM的偏见&#xff1f;LLM中的因果语言建模与掩码语…

【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标?

【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标&#xff1f; 遇到的问题解决方法查看修改效果 遇到的问题 JMeter测试计划中只设置了一个性能监控器jpgc - PerfMon Metrics Collector&#xff1b;在这个监控器中设置几个性能监控指标&#xff0c;比如CPU、Di…

电脑快速切换IP地址命令是什么?详解与实践

有时&#xff0c;出于安全考虑或测试需要&#xff0c;我们可能需要快速切换电脑的IP地址。虽然这一过程在初学者看来可能略显复杂&#xff0c;但通过简单的命令和步骤&#xff0c; 即使是普通用户也能轻松实现。本文将详细介绍在Windows系统中快速切换IP地址的几种方法&#xf…

无人自助超市系统小程序源码开发

随着科技的飞速发展和消费模式的转变&#xff0c;无人自助超市作为一种新兴的商业模式&#xff0c;以其便捷性、高效率以及对“体验式购物”的完美诠释&#xff0c;受到了广泛关注。本文renxb001将深入探讨无人自助超市系统小程序源码开发的核心环节和技术要点。 一、系统需求分…

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第172章 使用C文件编写I2C client代码

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

什么是CSV?超详细+通俗易懂版!!

CSV&#xff0c;全称为Comma-Separated Values&#xff08;逗号分隔值&#xff09;&#xff0c;是一种常用的文本文件格式&#xff0c;用于存储表格数据&#xff0c;如电子表格或数据库。CSV文件由一行或多行文本组成&#xff0c;每行文本包含由逗号分隔的一个或多个字段。这些…

【S2-MLP】核心方法解读

abstract&#xff1a; 近年来&#xff0c;visual Transformer (ViT)及其后续工作抛弃了卷积&#xff0c;利用自关注运算&#xff0c;达到了与CNN相当甚至更高的准确率。最近&#xff0c;MLP-mixer放弃了卷积和自关注操作&#xff0c;提出了一个只包含MLP层的体系结构。为了实现…

漏洞挖掘 | 通过错误日志实现XXE外带

介绍 在最近的一个项目中&#xff0c;我发现了一个与 XML 外部实体&#xff08;XXE&#xff09;攻击相关的重大安全问题。 本文讲述了我在项目中发现并利用 XXE 漏洞的过程&#xff0c;特别是通过一种非传统的方式——利用 Java 异常在日志文件中输出攻击结果。 什么是XXE&a…

基于STM32的太阳跟踪系统设计

引言 本项目设计了一个基于STM32的太阳跟踪系统&#xff0c;通过光敏传感器阵列实时检测太阳位置&#xff0c;并控制电机驱动太阳能板或光伏板跟随太阳移动&#xff0c;从而最大化太阳能的利用效率。该系统使用双轴运动控制&#xff0c;实现水平和垂直方向的精确跟踪&#xff…

【Java】类型转换与类型提升

目录 1.类型转换 1.1自动类型转换&#xff08;隐式&#xff09; 1.2强制类型转化&#xff08;显式&#xff09; 2.类型提升 3.字符串类型 1.类型转换 Java作为一个强类型编程语言,当不同类型之间的变量相互赋值的时候,会有教严格的校验. 在Java中&#xff0c;当参与运算数…

[单master节点k8s部署]36.ingress 配置https(三)

目前我们的tomcat服务在浏览器上通过http来访问。为了提升安全性&#xff0c;我们将配置TLS secret 证书&#xff0c;从而可以进行https访问。 一对TLS密钥包括一个证书&#xff08;trs.crt&#xff09;和一个私钥&#xff0c;证书是公钥证书&#xff0c;用于加密数据并标识服…

气膜滑冰馆的现实意义:冰雪运动的全民普及—轻空间

气膜滑冰馆的出现不仅是城市发展中的一项基础设施建设&#xff0c;更代表着冰雪运动的逐步普及和全民健身理念的深入人心。在过去&#xff0c;许多地方的冰上运动资源相对匮乏&#xff0c;而如今&#xff0c;气膜滑冰馆通过其独特的优势&#xff0c;弥补了这一空白&#xff0c;…