声明式事务

文章目录

    • 1.事务分类
        • 1.传统方式解决事务
        • 2.声明式事务
    • 2.声明式事务案例
        • 1.需求分析
        • 2.解决方案分析
        • 3.数据表创建
        • 4.编写GoodsDao.java
          • 1.编写配置文件JdbcTemplate_ioc.xml
          • 2.单元测试
        • 5.编写GoodsService.java
        • 6.配置事务管理器JdbcTemplate_ioc.xml
        • 7.进行测试
    • 3.debug事务管理器DataSourceTransactionManager
        • 1.基本步骤解释
          • 1.配置文件
          • 2.注解
          • 3.具体AOP示意图
        • 2.debug出现异常情况
          • 1.下断点
          • 2.执行
          • 3.下一个断点
          • 4.再打一个断点,跳过去
          • 5.下一个断点
          • 6.在con.rollback();打一个断点,跳过去然后下一步
    • 4.声明式事务传播机制
        • 1.基本介绍
        • 2.事务传播机制种类
        • 3.图解
          • 1.默认事务传播机制(REQUIRED)
          • 2.REQUIRES_NEW事务传播机制
          • 3.两种事务传播机制的区别
        • 4.声明式事务传播机制的设置方法
        • 5.应用实例
          • 1.文件目录
          • 2.GoodsDao.java
          • 3.GoodsService.java
          • 4.MultiplyService.java
          • 5.默认传播机制测试
            • 1.故意修改GoodsDao.java第一套的updateBalance方法
            • 2.初始数据表
            • 3.测试代码
            • 4.结果展示
          • 6.REQUIRES_NEW传播机制演示
            • 1.故意修改GoodsDao.java第二套的updateBalance方法(第一套的改回来)
            • 2.修改GoodsService.java的两个事务传播机制
            • 3.修改MultiplyService.java的一个事务传播机制
            • 4.初始数据表
            • 5.测试代码
            • 6.结果展示
            • 7.注意事项
    • 5.事务隔离级别
        • 1.基本介绍
        • 2.应用实例
          • 1.简要介绍
          • 2.结果展示
            • 1.原goods表
            • 2.启动测试程序
            • 3.修改id为1的价格
            • 4.打开断点,查看第二次结果
        • 3.修改事务隔离级别
    • 6.事务超时回滚
        • 1.基本介绍
        • 2.代码实例
          • 1.GoodsService.java的buyGoodsByTxSOLATION方法
          • 2.测试程序
          • 3.原账户表
          • 4.执行测试程序
    • 7.课后练习
        • 1.要求
        • 2.数据表设计
        • 3.代码实现
          • 1.文件目录
          • 2.jdbc.properties
          • 3.txhomework.xml
          • 4.HomeWorkDao.java
          • 5.HomeWorkService.java
          • 6.测试类
          • 7.原数据表
          • 8.执行测试类
            • 1.执行失败
            • 2.执行成功

1.事务分类

1.传统方式解决事务

image-20240223103145604

2.声明式事务

2.声明式事务案例

1.需求分析

image-20240223103404559

2.解决方案分析

image-20240223103746418

image-20240223103759610

3.数据表创建
-- 声明式事务要创建的表-- 账户表
CREATE TABLE `user_account`(
user_id INT UNSIGNED PRIMARY KEY auto_increment,
user_name VARCHAR(32) NOT NULL DEFAULT'',
money DOUBLE NOT NULL DEFAULT 0.0
);
INSERT INTO `user_account` VALUES(NULL, '张三', 1000);
INSERT INTO `user_account` VALUES(NULL, '李四', 2000);SELECT * FROM user_account;-- 商品表
CREATE TABLE `goods`(
goods_id INT UNSIGNED PRIMARY KEY auto_increment,
goods_name VARCHAR(32) NOT NULL DEFAULT'',
price DOUBLE NOT NULL DEFAULT 0.0
);
INSERT INTO goods VALUES(NULL, '小风扇',10.00);
INSERT INTO goods VALUES(NULL, '小台灯',12.00);
INSERT INTO goods VALUES(NULL, '可口可乐',1.00);SELECT * FROM goods;-- 商品库存表
CREATE TABLE `goods_amount`(
goods_id INT UNSIGNED PRIMARY KEY auto_increment,
goods_num INT UNSIGNED DEFAULT 0
);
INSERT INTO goods_amount VALUES(NULL, 200);
INSERT INTO goods_amount VALUES(NULL, 20);
INSERT INTO goods_amount VALUES(NULL, 23);SELECT * FROM goods_amount;
4.编写GoodsDao.java
package com.sxs.spring.tx;import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/
//反射创建bean对象
@Repository
public class GoodsDao {//依赖注入@Resourceprivate JdbcTemplate jdbcTemplate;/*** 根据商品id返回价格** @param id* @return*/public Double queryPriceById(Integer id) {String sql = "select price from goods where goods_id = ?";Double price = jdbcTemplate.queryForObject(sql, Double.class, id);System.out.println(id + "号商品价格为" + price);return price;}/*** 根据用户名id减少用户余额** @param user_id* @param money*/public void updateBalance(Integer user_id, Double money) {String sql = "update user_account set money = money - ? where user_id = ?";int update = jdbcTemplate.update(sql, money, user_id);if (update == 1) {System.out.println("用户余额减少成功");}}/*** 修改商品库存** @param goods_id* @param amount*/public void updateAmount(Integer goods_id, Integer amount) {String sql = "update goods_amount set goods_num = goods_num - ? where goods_id = ?";int update = jdbcTemplate.update(sql, amount, goods_id);if (update == 1) {System.out.println("商品库存减少成功!");}}}
1.编写配置文件JdbcTemplate_ioc.xml

image-20240223113504708

2.单元测试
package com.sxs.spring.tx;import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/
//反射创建bean对象
@Repository
public class GoodsDao {//依赖注入@Resourceprivate JdbcTemplate jdbcTemplate;/*** 根据商品id返回价格** @param id* @return*/public Double queryPriceById(Integer id) {String sql = "select price from goods where goods_id = ?";Double price = jdbcTemplate.queryForObject(sql, Double.class, id);System.out.println(id + "号商品价格为" + price);return price;}/*** 根据用户名id减少用户余额** @param user_id* @param money*/public void updateBalance(Integer user_id, Double money) {String sql = "update user_account set money = money - ? where user_id = ?";int update = jdbcTemplate.update(sql, money, user_id);if (update == 1) {System.out.println("用户余额减少成功");}}/*** 修改商品库存** @param goods_id* @param amount*/public void updateAmount(Integer goods_id, Integer amount) {String sql = "update goods_amount set goods_num = goods_num - ? where goods_id = ?";int update = jdbcTemplate.update(sql, amount, goods_id);if (update == 1) {System.out.println("商品库存减少成功!");}}}
5.编写GoodsService.java
package com.sxs.spring.tx.service;import com.sxs.spring.tx.GoodsDao;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/@Service
public class GoodsService {@Resourceprivate GoodsDao goodsDao;@Transactional //会将方法中对数据库的操作作为一个事务管理public void buyGoodsByTx(Integer userId, Integer goodsId, Integer amount) {//得到商品的价格Double price = goodsDao.queryPriceById(goodsId);//减少用户的余额goodsDao.updateBalance(userId, amount * price);//减少库存goodsDao.updateAmount(goodsId, amount);}
}
6.配置事务管理器JdbcTemplate_ioc.xml
    <!--配置事务管理器对象--><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><!--需要与数据源关联,因为操作数据库的jdbcTemplate要与dataSource关联,他们要一致--><property name="dataSource" ref="dataSource"/></bean><!--配置启动注解的声明式事务管理功能--><tx:annotation-driven transaction-manager="transactionManager"/>

image-20240223124447662

7.进行测试
    //通过声明式事务管理测试@org.junit.jupiter.api.Testpublic void byGoodsByTx() {GoodsService bean1 = ioc.getBean(GoodsService.class);bean1.buyGoodsByTx(1, 1, 3);}

执行前后并没有出现数据不一致

image-20240223124633636

3.debug事务管理器DataSourceTransactionManager

1.基本步骤解释
1.配置文件
  • 首先配置了一个事务管理器对象,绑定与jdbcTemplate一致的数据源

  • 然后启动tx注解,绑定这个事务管理器对象

image-20240223130513649

2.注解
  • 当使用这个注解时,表名这个方法就会被AOP作为一个事务管理

image-20240223130805179

3.具体AOP示意图

image-20240223131706489

2.debug出现异常情况
1.下断点

image-20240223134007045

image-20240223134020750

2.执行

image-20240223134201189

3.下一个断点

image-20240223134248093

4.再打一个断点,跳过去

image-20240223134419259

5.下一个断点

image-20240223134520652

6.在con.rollback();打一个断点,跳过去然后下一步

image-20240223134647924

4.声明式事务传播机制

1.基本介绍

image-20240223134933511

image-20240223134943012

2.事务传播机制种类

image-20240223135400830

3.图解
1.默认事务传播机制(REQUIRED)
  • 可以理解为将方法1和方法2的事务功能去掉了,将方法1和方法2的代码合并交给Tx事务管理
  • 具体例子
    • 方法1出错:方法1和方法2和Tx事务全部回滚
    • 方法2出错:方法1和方法2和Tx事务全部回滚
    • Tx事务出错(除了方法1和方法2的部分):方法1和方法2和Tx事务全部回滚

image-20240223140441185

2.REQUIRES_NEW事务传播机制
  • 可以理解为Tx事务、方法1事务、方法2事务都是各自独立
  • 具体例子
    • 方法1出错:方法1事务回滚
    • 方法2出错:方法2事务回滚
    • Tx事务出错(除了方法1和方法2的部分):Tx事务(除了方法1和方法2的部分)回滚

image-20240223140854861

3.两种事务传播机制的区别

image-20240223141541267

4.声明式事务传播机制的设置方法

image-20240223141421702

5.应用实例
1.文件目录

image-20240223144431435

2.GoodsDao.java
package com.sxs.spring.tx;import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/
//反射创建bean对象
@Repository
public class GoodsDao {//依赖注入@Resourceprivate JdbcTemplate jdbcTemplate;//第一套方法/*** 根据商品id返回价格** @param id* @return*/public Double queryPriceById(Integer id) {String sql = "select price from goods where goods_id = ?";Double price = jdbcTemplate.queryForObject(sql, Double.class, id);System.out.println(id + "号商品价格为" + price);return price;}/*** 根据用户名id减少用户余额** @param user_id* @param money*/public void updateBalance(Integer user_id, Double money) {String sql = "update user_account set money = money - ? where user_id = ?";int update = jdbcTemplate.update(sql, money, user_id);if (update == 1) {System.out.println("用户余额减少成功");}}/*** 修改商品库存** @param goods_id* @param amount*/public void updateAmount(Integer goods_id, Integer amount) {String sql = "update goods_amount set goods_num = goods_num - ? where goods_id = ?";int update = jdbcTemplate.update(sql, amount, goods_id);if (update == 1) {System.out.println("商品库存减少成功!");}}//第二套方法/*** 根据商品id返回价格** @param id* @return*/public Double queryPriceById2(Integer id) {String sql = "select price from goods where goods_id = ?";Double price = jdbcTemplate.queryForObject(sql, Double.class, id);System.out.println(id + "号商品价格为" + price);return price;}/*** 根据用户名id减少用户余额** @param user_id* @param money*/public void updateBalance2(Integer user_id, Double money) {String sql = "update user_account set money = money - ? where user_id = ?";int update = jdbcTemplate.update(sql, money, user_id);if (update == 1) {System.out.println("用户余额减少成功");}}/*** 修改商品库存** @param goods_id* @param amount*/public void updateAmount2(Integer goods_id, Integer amount) {String sql = "update goods_amount set goods_num = goods_num - ? where goods_id = ?";int update = jdbcTemplate.update(sql, amount, goods_id);if (update == 1) {System.out.println("商品库存减少成功!");}}}
3.GoodsService.java
package com.sxs.spring.tx.service;import com.sxs.spring.tx.GoodsDao;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/@Service
public class GoodsService {@Resourceprivate GoodsDao goodsDao;//调用第一套方法@Transactional //会将方法中对数据库的操作作为一个事务管理public void buyGoodsByTx(Integer userId, Integer goodsId, Integer amount) {//得到商品的价格Double price = goodsDao.queryPriceById(goodsId);//减少用户的余额goodsDao.updateBalance(userId, amount * price);//减少库存goodsDao.updateAmount(goodsId, amount);}//调用第二套方法@Transactional //会将方法中对数据库的操作作为一个事务管理public void buyGoodsByTx2(Integer userId, Integer goodsId, Integer amount) {//得到商品的价格Double price = goodsDao.queryPriceById2(goodsId);//减少用户的余额goodsDao.updateBalance2(userId, amount * price);//减少库存goodsDao.updateAmount2(goodsId, amount);}
}
4.MultiplyService.java
package com.sxs.spring.tx.service;import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/
@Service
public class MultiplyService {@Resourceprivate GoodsService goodsService;@Transactional //默认事务传播机制public void multiBuyGoodsByTx() {//默认事务传播机制goodsService.buyGoodsByTx(1,1,1);goodsService.buyGoodsByTx2(1,1,1);}
}
5.默认传播机制测试
1.故意修改GoodsDao.java第一套的updateBalance方法

image-20240223144741663

2.初始数据表
  • 账户表

image-20240223144946645

  • 库存表

image-20240223144913270

3.测试代码
  • 此时是默认传播机制,所以如果第一套方法出现异常,则第二套方法也会回滚
  • 所以结果应该是数据表没有变化
    //事务传播机制测试@org.junit.jupiter.api.Testpublic void multiBuyGoodsByTx() {MultiplyService bean1 = ioc.getBean(MultiplyService.class);bean1.multiBuyGoodsByTx();}
4.结果展示

image-20240223145236270

image-20240223145243679

6.REQUIRES_NEW传播机制演示
1.故意修改GoodsDao.java第二套的updateBalance方法(第一套的改回来)

image-20240223151004668

2.修改GoodsService.java的两个事务传播机制

image-20240223145623684

3.修改MultiplyService.java的一个事务传播机制

image-20240223145648252

4.初始数据表
  • 账户表

image-20240223144946645

  • 库存表

image-20240223144913270

5.测试代码
  • 此时是REQUIRES_NEW传播机制,所以如果第二套方法出现异常,第一套方法不会回滚
  • 所以结果应该是第一套方法执行成功,张三购买一件商品1成功
    //事务传播机制测试@org.junit.jupiter.api.Testpublic void multiBuyGoodsByTx() {MultiplyService bean1 = ioc.getBean(MultiplyService.class);bean1.multiBuyGoodsByTx();}
6.结果展示

image-20240223150835997

image-20240223150825770

7.注意事项
  • 第一次我将第一套方法改错了,本来以为第二套方法会正常执行
  • 但是虽然事务是独立的,但是第一套方法报错了后面的就不继续执行了
  • 最外面的事务设置成默认的还是REQUIRES_NEW类型都不会影响里面的两个事务的独立性

5.事务隔离级别

1.基本介绍

image-20240223152325593

2.应用实例
1.简要介绍

image-20240223153156103

2.结果展示
1.原goods表

image-20240223153845855

2.启动测试程序

image-20240223153939973

3.修改id为1的价格

image-20240223154858766

4.打开断点,查看第二次结果

image-20240223154937502

3.修改事务隔离级别

image-20240223155307494

6.事务超时回滚

1.基本介绍

image-20240223155506448

image-20240223155716193

2.代码实例
1.GoodsService.java的buyGoodsByTxSOLATION方法
    @Transactional(timeout = 2) //设置超时回滚时间为2秒public void buyGoodsByTxSOLATION(){//查询两次商品的价格Double aDouble = goodsDao.queryPriceById(1);//减少用户的余额goodsDao.updateBalance2(1, 1000.0);try {//设置4秒休眠时间Thread.sleep(4000);} catch (InterruptedException e) {throw new RuntimeException(e);}Double aDouble1 = goodsDao.queryPriceById(1);System.out.println(aDouble1);}
2.测试程序
    @org.junit.jupiter.api.Testpublic void buyGoodsByTxSOLATION() {GoodsService bean1 = ioc.getBean(GoodsService.class);bean1.buyGoodsByTxSOLATION();}
3.原账户表
  • 如果没有回滚则money应该减少1000

image-20240223160316654

4.执行测试程序

image-20240223160528891

image-20240223160545038

7.课后练习

1.要求

image-20240223160756954

2.数据表设计
-- seller
CREATE TABLE seller (
seller_id INT UNSIGNED PRIMARY KEY auto_increment,
seller_name VARCHAR(32) NOT NULL DEFAULT'',
money DOUBLE NOT NULL DEFAULT 0.0
);INSERT INTO seller VALUES(NULL, '李白', 100.0)
SELECT * FROM seller-- buyer
CREATE TABLE buyer (
buyer_id INT UNSIGNED PRIMARY KEY auto_increment,
buyer_name VARCHAR(32) NOT NULL DEFAULT'',
money DOUBLE NOT NULL DEFAULT 0.0
);INSERT INTO buyer VALUES(NULL, '杜甫', 100.0)
SELECT * FROM buyer-- goods
CREATE TABLE goods (
goods_id INT UNSIGNED PRIMARY KEY auto_increment,
goods_name VARCHAR(32) NOT NULL DEFAULT'',
price DOUBLE NOT NULL DEFAULT 0.0,
goods_num INT UNSIGNED DEFAULT 0
);INSERT INTO goods VALUES(NULL, 100.0, 10, '酒')
SELECT * FROM goods-- taoBao
CREATE TABLE taoBao (
taoBao_id INT UNSIGNED PRIMARY KEY auto_increment,
goods_name VARCHAR(32) NOT NULL DEFAULT'',
money DOUBLE NOT NULL DEFAULT 0.0
)SELECT * FROM taoBao
3.代码实现
1.文件目录

image-20240223185143537

2.jdbc.properties
jdbc.user=root
jdbc.pwd=root
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
3.txhomework.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><!--容器扫描--><context:component-scan base-package="com.sxs.spring.tx"/><!--数据库配置--><!--引入外部配置文件,读取数据源信息--><context:property-placeholder location="classpath:jdbc.properties"/><!--配置数据源--><bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource"><property name="user" value="${jdbc.user}"/><property name="password" value="${jdbc.pwd}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="driverClass" value="${jdbc.driver}"/></bean><!--配置JdbcTemplate对象--><bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"><!--配置数据源属性--><property name="dataSource" ref="dataSource"/></bean><!--配置事务管理器对象--><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><property name="dataSource" ref="dataSource"/></bean><!--启动事务管理器注解--><tx:annotation-driven transaction-manager="transactionManager"/></beans>
4.HomeWorkDao.java
package com.sxs.spring.tx.homework.dao;import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/
@Repository
public class HomeWorkDao {@Resourceprivate JdbcTemplate jdbcTemplate;//根据卖家id增加moneypublic int addMoneyBySellerId(Integer seller_id, Double money) {String sql = "update seller set money = money + ? where seller_id = ?";return jdbcTemplate.update(sql, money, seller_id);}//根据买家id减少moneypublic int subMoneyByBuyerId(Integer buyer_id, Double money) {String sql = "update buyer set money = money - ? where buyer_id = ?";return jdbcTemplate.update(sql, money, buyer_id);}//根据id减少商品库存量public int subGoodsNumByGoodsId(Integer goods_id, Integer goods_num) {String sql = "update goods se goods_num = goods_num - ? where goods_id = ?";return jdbcTemplate.update(sql, goods_num, goods_id);}//根据id查找商品价格public Double findPriceById(Integer goods_id) {String sql = "select price from goods where goods_id = ?";//public <T> T queryForObject(String sql, @Nullable Object[] args, Class<T> requiredType)//传入sql, Object[]填充sql的值,Class<T> requiredType传入要返回的类型Double aDouble = jdbcTemplate.queryForObject(sql, new Object[]{goods_id}, Double.class);return aDouble;}//给taoBao添加一条记录public int addtoTaoBao(Double money) {String sql = "insert into taoBao values(?, ?, ?)";return jdbcTemplate.update(sql, null, "name", money);}
}
5.HomeWorkService.java
package com.sxs.spring.tx.homework.service;import com.sxs.spring.tx.homework.dao.HomeWorkDao;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** @author 孙显圣* @version 1.0*/
@Service
public class HomeWorkService {@Resourceprivate HomeWorkDao homeWorkDao;//买家买卖家的商品@Transactional //启动事务管理器public boolean getGoods(Integer seller_id, Integer buyer_id, Integer goods_id) {try {//1.根据id查找商品价格Double priceById = homeWorkDao.findPriceById(goods_id);//2.计算给淘宝的money和卖家得到的moneyDouble taobao_money = priceById * 0.1;Double seller_money = priceById * 0.9;//3.根据id修改卖家的moneyhomeWorkDao.addMoneyBySellerId(seller_id, seller_money);//4.根据id修改买家的moneyhomeWorkDao.subMoneyByBuyerId(buyer_id, priceById);//5.增加taobao表的记录homeWorkDao.addtoTaoBao(taobao_money);//6.减少库存homeWorkDao.subGoodsNumByGoodsId(goods_id, 1);} catch (Exception e) {System.out.println("购买商品逻辑出现问题!");throw new RuntimeException(e);}return true;}
}
6.测试类
package com.sxs.spring.tx.homework;import com.sxs.spring.tx.homework.service.HomeWorkService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author 孙显圣* @version 1.0*/
public class Test {public static void main(String[] args) {ApplicationContext ioc = new ClassPathXmlApplicationContext("txhomework.xml");HomeWorkService bean = ioc.getBean(HomeWorkService.class);bean.getGoods(1, 1, 1);}
}
7.原数据表
  • seller

image-20240223185442943

  • buyer

image-20240223185448553

  • goods

image-20240223185454120

  • taoBao

image-20240223185500052

8.执行测试类
  • 如果执行成功
    • 李白money = 190
    • 杜甫money = 0
    • goods表goods_num = 7
    • taoBao表有一条新记录
  • 如果执行失败
    • 事务回滚
1.执行失败

image-20240223185843899

2.执行成功

image-20240223190012328

image-20240223190029665

image-20240223190035549

image-20240223190041325

image-20240223190047393

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

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

相关文章

2. 链表

链表的概念及结构 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。 链表的结构跟⽕⻋⻋厢相似&#xff0c;淡季时⻋次的⻋厢会相应减少&#xff0c;旺季时⻋次的⻋厢会额外增加⼏节。…

@NameBinding注解名称绑定过滤器/拦截器

NameBinding注解名称绑定过滤器/拦截器&#xff0c;只针对某一些资源方法执行处理逻辑 一、为什么要用名称绑定 一般情况下&#xff0c;借助Spring的过滤器或者拦截器等对Http请求或响应进行处理就能满足需求。但是在有些场景下若只需对特定的xxxResource做拦截处理&#xff0…

【ARM Trace32(劳特巴赫) 使用介绍 12.1 -- Trace32 读写 64位地址】

请阅读【Trace32 ARM 专栏导读】 文章目录 Trace32 读写 64位地址读 64 位地址写64位地址Trace32 读写 64位地址 在使用TRACE32进行调试时,有时需要读取或操作64位的地址,特别是在处理64位的处理器或操作系统时。以下是如何在TRACE32中读取64位地址的一般方法。 读 64 位地…

vue-element-admin vue设置动态路由 刷新页面后出现跳转404页面Bug 解决方法

做项目时遇到的这个bug&#xff0c;因为除了跳404之外也没太大影响&#xff0c;之前就一直放着没管&#xff0c;现在项目基本功能实现了&#xff0c;转头处理了一下&#xff0c;现在在这里记录一下解决方法 这个bug的具体情况是&#xff1a;设置了动态路由之后&#xff0c;不同…

FPGA - ZYNQ 基于Axi_Lite的PS和PL交互

前言 在FPGA - ZYNQ 基于EMIO的PS和PL交互中介绍了ZYNQ 中PS端和PL端交互的开发流程&#xff0c;接下来构建基于基于Axi_Lite的PS和PL交互。 开发流程 Axi_Lite从机 在FPGA - AXI4_Lite&#xff08;实现用户端与axi4_lite之间的交互逻辑&#xff09;中&#xff0c;详解介绍…

微信小程序:基于MySQL+Nodejs的汽车品牌管理系统

各位好&#xff0c;接上期&#xff0c;今天分享一个通过本地MySQLNodejs服务器实现CRUD功能的微信小程序&#xff0c;一起来看看吧~ 干货&#xff01;微信小程序通过NodeJs连接MySQL数据库https://jslhyh32.blog.csdn.net/article/details/137890154?spm1001.2014.3001.5502 …

针对窗口数量多导致窗口大小显示受限制的问题,使用滚动条控制窗口

建议&#xff1a;首先观察结果展示&#xff0c;判断是否可以满足你的需求。 目录 1. 问题分析 2. 解决方案 2.1 界面设计 2.2 生成代码 2.3 源码实现 3. 结果展示 1. 问题分析 项目需要显示的窗口数量颇多&#xff0c;主界面中&#xff0c;如果一次性显示全部窗口&#x…

飞书小技巧:markdown导出

文章目录 下载Feishu2Md飞书应用配置配置feishu2md工具绑定应用导出markdown 下载Feishu2Md Feishu2Md 飞书应用配置 进入飞书开发者后台 https://open.feishu.cn/app。 点击“创建企业自建应用”&#xff0c;并填写应用名称等信息。而后点击创建。 PS: 此处作者创建应用名…

面向对象设计与分析40讲(25)中介模式、代理模式、门面模式、桥接模式、适配器模式

文章目录 门面模式代理模式中介模式 之所以把这几个模式放到一起写&#xff0c;是因为它们的界限比较模糊&#xff0c;结构上没有明显的差别&#xff0c;差别只是语义上。 这几种模式在结构上都类似&#xff1a; 代理将原本A–>C的直接调用变成&#xff1a; A–>B–>…

网渲应用领域有哪些?渲染100邀请码1a12

网渲是一种利用云计算技术把本地渲染上传到云端进行的过程&#xff0c;它极大提高了渲染效率&#xff0c;摆脱了本地限制&#xff0c;使用网渲的领域有很多&#xff0c;这里我们列举下。 1、影视制作 在影视制作当中&#xff0c;对于需要大量特效和动画效果的电影来说&#x…

【STM32】嵌入式实验二 GPIO 实验:数码管

实验内容&#xff1a; 编写程序&#xff0c;在数码管上显示自己的学号。 数码管相关电路&#xff1a; PA7对应的应该是段码&#xff0c;上面的图写错了。 注意&#xff1a;选中数码管是低电平选中&#xff1b;并且用74HC595模块驱动输出的段码&#xff0c; 这个模块的学习可以…

太奇怪了!99%的人没见过的Oracle故障:网络恢复后,集群的监听和vip无法启动

故障描述 15:46操作系统日志出现net4、net5网卡down&#xff0c;15:53分钟的网络恢复。网络中断是由于db汇聚交换机出现了问题。 网络恢复后&#xff0c;节点1的监听和vip无法启动。 故障分析 查看grid alert日志可以看到监听资源确实没有正常启动。 由于监听资源是crs的Ora…