Spring中进行事务管理的两种方式

2023-11-12

1、Spring中事务管理的API

事务是指逻辑上要么全部成功、要么全部失败的一组操作。例如用户A给用户B转账,则用户A账户余额减少、用户B账户增加这两个操作就是一组事务,必须全部成功或失败撤回操作,不能出现A账户余额减少,B增加失败的情况。事务具有如下几个特性:

  • 原子性:事务的操作不可分割
  • 一致性:账户A的减少和B的增加一起发生
  • 隔离性:在多个事务操作时,彼此之间互不干扰
  • 持久性:事务提交到数据库之后永久的改变

spring提供了三个接口用于实现事务的管理,在进行事务管理时,spring首先会读取TransactionDefinition中隔离、传播、超时等事务定义信息,然后PlatformTransactionManager会根据这些信息进行事务管理,然后将产生的事务状态保存在TransactionStatus中

TransactionDefinition

事务定义信息接口中ISOLATION开头的常量用于定义事务的隔离级别、PROPAGATION开头定义事务传播行为、TIMEOUT_DEFAULT定义超时时间。

隔离级别用于解决多个事务提交时可能出现的脏读、不可重复读、

  • 脏读:A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。
  • 不可重复读:一个事务读取了另一个事务更新(update)前、后的数据,导致前后两次读取数据不一致
  • 幻读:一个事务读取时,另一个事务进行插入(insert),导致读取到了之前没有的记录

事务的隔离级别有如下四种类型,如果为DEFAULT则使用后端数据库默认的隔离级别,例如MySQL使用的是repeatable_read,Oracle数据库使用的是read_committed级别

READ_UNCOMMITED 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITTED 允许在并发事努已经提交后读取。可防止脏读,但幻读和不可重复读仍可发生
REPEATABLE_READ 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE 完全服从ACID的隔离级别,通过完全锁定事务中涉及的数据表来确保不发生脏、幻、不可重复读,但执行效率最低

事务的传播行为用于解决业务层方法互相调用时如何传递事务的问题。例如方法a和b中都用到了事务T,那么a在调用b时是新建一个事务T还是使用b中的事务T呢?有如下七种传播方式

PROPAGATION_REQUIRED 支持当前事务,如果不存在就新建一个
PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事劳,创建一个新的事务
PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
PROPAGATION_NESTED 如果当前事务存在,则嵌套执行事务

PlatformTransactionManager

spring为不同的持久层框架提供了相应的PlatformTransactionManager接口实现,spring JDBC和MyBatis对应DataSourceTransactionManager、Hibernate对应HibernateTransactionManager,还有JPA、Jdo、JTA等,不同的持久层使用不同的实现类

org.springframework.jdbc.datasource.DataSourceTransaction.Manager
Spring JDBC或iBatis逬行持久化数据时使用
org.springframework.orm.hibernate3.HibernateTransactionManager
Hibernate3.0版本进行持久化数据时使用
org.springframework.orm.jpa.JpaTransactionManager
JPA进行持久化时使用
org.springframework.jdo.JdoTransaction Manager
当持久化机制是Jdo时使用
org.springframework.transactionjta.JtaTransactionManager
JTA管理事务,在一个事务跨越多 个资源时必须使用

TransactionStatus

用于记录事务是否完成、是否产生保存点、是否可回滚等状态。

2、编程式事务管理

在Spring中使用事务有两种方式,第一种是通过手动编写来实现一个事务。

如下左图所示为一个用户账户的数据表,通过事务管理实现根据id对账户的money进行转账,以实现一个账户money减少的同时另一个增加。

   

1、引入jar包。上面右图所示为项目的目录结构,lib文件夹中包含了项目依赖的jar包,包括Spring基础包commons-logging、spring-core、spring-beans、spring-context、spring-expression、spring-test,以及连接数据库的spring-jdbc、mysql-connector,事务管理spring-tx,此外要用到c3p0对数据库连接池进行管理,除了引入c3p0包之外还需要引入mchange-commons包才可以使用。

2、配置数据源连接,在jdbc.properties文件中完成数据库连接的配置

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=1234

接着在配置文件spring-transaction.xml中引入properties并将属性注入c3p0的配置中,完成dataSource的配置

    <!-- 引入属性文件jdbc.properties -->
    <context:property-placeholder location="jdbc.properties"/>

    <!-- 配置c3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

3、实现数据对象的DAO类,在AccountDao类中通过继承spring的JdbcDaoSupport类,可以使用JdbcTemplate中的update()方法完成对数据库的更新操作。由于JdbcDaoSupport需要DataSource获取数据库的连接,因此在AccountDao的Bean配置中通过属性注入c3p0数据源dataSource

package com.transaction;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class AccountDao extends JdbcDaoSupport {
    public void transferIn(int id,double money){
        String sql="UPDATE customers SET money = money + ? WHERE id =?";
        this.getJdbcTemplate().update(sql,money,id);        //使用JdbDaoSupport类的方法操作数据库
    }
    public void transferOut(int id,double money){
        String sql="UPDATE customers SET money = money - ? WHERE id =?";
        this.getJdbcTemplate().update(sql,money,id);
    }
}
    <!-- DAO类 -->
    <bean class="com.transaction.AccountDao" id="accountDao">
        <!-- SpringJdbc需要注入连接池DataSource作为参数来初始化 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

4、实现事务操作Service类。在AccountService类中完成事务操作,spring编程式的事务管理通过Spring的TransactionTemplate类来实现,将一个事务操作放在其execute()方法内完成,execute()需要传入一个TransactionCallback类作为参数,这里采用匿名内部类的方式实现。在内部类中doIntransaction()方法中执行事务操作,通过调用DAO层的方法完成具体数据库操作

package com.transaction;

import org.springframework.transaction.support.TransactionTemplate;

public class AccountService {
    private AccountDao accountDao;
    private TransactionTemplate transactionTemplate;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    public void transfer(int inAccount, int outAccount, double money) {
        //使用spring的TransactionTemplate进行事务操作
        transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                accountDao.transferIn(inAccount, money);
                int i = 1/0;            //除数为0会抛出异常
                accountDao.transferOut(outAccount, money);
                return null;
            }
        });
    }
}

AccountService类中用到了accountDao和transactionTemplate两个属性,因此在配置Bean时需要注入两个bean对象。accountDao类是之前创建的,那么transactionTemplate类哪里来的呢?transactionTemplateDataSourceTransactionManager创建的,之前提到它是PlatformTransactionManager接口用于spring jdbc的一个实现类。所以需要先创建一个transactionManager的bean,而要创建它还需要注入DataSource作为属性。

     <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 事务管理模板 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"/>
    </bean>

    <!-- 业务层类 -->
    <bean id="accountService" class="com.transaction.AccountService">
        <property name="accountDao" ref="accountDao"/>
        <property name="transactionTemplate" ref="transactionTemplate"/>
    </bean>

项目的数据流动如下:

最后测试AccountService类,调用accountService对象的transfer()方法从id为2的向1转账50。由于在事务中进行了除以0的操作,事务执行失败并且回滚,数据库操作不生效

class AccountServiceTest {
    @org.junit.jupiter.api.Test
    void transfer() {
        ApplicationContext appCtx=new ClassPathXmlApplicationContext("spring-transaction.xml");
        AccountService accountService= appCtx.getBean("accountService",AccountService.class);
        accountService.transfer(2,1,50);
    }
}

3、声明式事务管理

Spring基于声明式的事务管理是利用AOP的思想,因此需要额外引入spring-aop和aopalliance两个jar包。由于SpringAOP的使用有三种方式,所以声明式事务管理也有三种:通过spring的TransactionProxy、使用<aop>标签、使用注解的方式

基于TransactionProxy的方式

在accountService类的基础上通过TransactionProxyBeanFactory产生代理类serviceProxy来对事务进行管理,由于是通过AOP引入的方式,所以原来的accountService类不需要增加transactionTemplate

public class AccountService {
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void transfer(int inAccount, int outAccount, double money) {
        accountDao.transferIn(inAccount, money);
                int i = 1/0;            //除数为0会抛出异常
        accountDao.transferOut(outAccount, money);
    }
}

xml文件中也不需要对TransactionTemplate进行配置,只需要保留TransactionManager,但是需要新配置代理类serviceProxy,代理配置时需要注入属性--代理目标对象、事务管理器和事务属性。在transactionAttributes中通过<prop>键值对标签配置具体transfer()方法的事务属性,其中PROPAGATION_开头的是传播行为,ISOLATION_开头的是隔离级别,+开头的定义发生哪些异常后事务不回滚,-开头定义发生哪些异常回滚。

    <!-- 业务层代理 -->
    <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <!-- 代理目标 -->
        <property name="target" ref="accountService"/>
        <!-- 注入事务管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
        <!-- 配置事务属性 -->
        <property name="transactionAttributes">
            <props>
                <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ,+ArithmeticException</prop>
            </props>
        </property>
    </bean>

在使用时通过serviceProxy获取代理Bean,通过增强后的代理调用transfer()

    @Test
    void transfer() {
        ApplicationContext appCtx=new ClassPathXmlApplicationContext("spring-transaction.xml");
        AccountService accountService= appCtx.getBean("serviceProxy",AccountService.class);
        accountService.transfer(1,2,50);
    }

基于AspectJ的<aop>标签

由于上面的方法需要为每一个事务对象单独配置一个代理类,较为繁琐,所以实际中不常用。使用AspectJ不产生代理类,而是直接织入到accountService中。由于需要使用aspectJ进行织入,所以需要引入aspectjweaver.jar包。此外在xml配置文件中使用到了<tx>和<aop>标签,需要在<beans>声明。然后通过<tx>标签定义事务通知,其中的<tx:method>中可以对具体事务方法进行配置,包括隔离级别isolation、传播属性propagation、不回滚的异常。在<aop:config>标签值对切面进行配置,包括切入点和通知。

<?xml version="1.0" encoding="UTF-8"?>
<!-- 声明tx、aop等标签 -->
<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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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 http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    ......

    <!-- 配置事务AOP的通知-->
    <tx:advice id="serviceAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置切面 -->
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut id="transferPointcut" expression="execution(* com.transaction.AccountService.*(..))"/>
        <!-- 配置通知 -->
        <aop:advisor advice-ref="serviceAdvice" pointcut-ref="transferPointcut"/>
    </aop:config>

</beans>

由于不产生代理类,可以直接使用accountService对象

    @Test
    void transfer() {
        ApplicationContext appCtx=new ClassPathXmlApplicationContext("spring-transaction.xml");
        AccountService accountService= appCtx.getBean("accountService",AccountService.class);
        accountService.transfer(1,2,50);
    }

基于注解的方式

通过注解来使用spring事务管理代码更为简洁,只需要在xml配置文件中配置事务管理器并开启事务注解即可

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>   
    <!-- 开启基于注解的事务管理 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

接着在具体要使用到事务的类上添加@Transactional注解即可。在注解中可以指定隔离级别、传播属性、回滚/不回滚异常等属性

package com.transaction;

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,
        rollbackFor = java.lang.ArithmeticException.class)
public class AccountService {
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void transfer(int inAccount, int outAccount, double money) {
        accountDao.transferIn(inAccount, money);
        int i = 1/0;            //除数为0会抛出异常
        accountDao.transferOut(outAccount, money);
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring中进行事务管理的两种方式 的相关文章

  • 枚举的子类化

    有没有一种简单的方法来子类化Javaenum 我问这个问题是因为我有大约 10 个实现相同接口的对象 但它们对某些方法也有相同的实现 因此我想通过将所有相同的实现放置在扩展的中间对象中来重用代码Enum它也是我需要的所有其他类的超类 或许事
  • Java将字符串解析为double

    如何解析字符串中的这个 Double 00034800 变成 Double 值 最后两位数字实际上是小数点 所以我正在寻找的结果是348 00 是否有这样的格式可以与十进制格式一起使用 Well String s 00034800 doub
  • Android:如何暂停和恢复可运行线程?

    我正在使用 postDelayed 可运行线程 当我按下按钮时 我需要暂停并恢复该线程 请任何人帮助我 这是我的主题 protected void animation music6 music4 postDelayed new Runnab
  • “源兼容性”和“目标兼容性”有什么区别?

    之间有什么关系 区别sourceCompatibility and targetCompatibility 当它们设置为不同的值时会发生什么 根据工具链和兼容性 https docs gradle org current userguide
  • 连接外部 Accumulo 实例和 java

    我正在尝试使用 Accumulo 连接到虚拟机 问题是 我无法将其连接到 Java 中 我可以看到 Apache 抛出的网页 但我无法让它与代码一起工作 我认为这是缺乏知识的问题而不是真正的问题 但我找不到这方面的文档 所有示例都使用 lo
  • java程序有多少种结束方式?

    我知道使用 System exit 0 可以结束一个java程序 例如 如果我有一个JFrame窗口 它会关闭并结束程序 但我想知道还有多少其他方法 可以关闭它并结束程序 包括发生错误时 程序会被关闭 JFrame也会被关闭吗 添加到其他答
  • 使用 proguard 混淆文件名

    我正在使用 proguard 和 Android Studio 混淆我的 apk 当我反编译我的apk时 我可以看到很多文件 例如aaa java aab java ETC 但我项目中的所有文件都有原始名称 有没有办法混淆我的项目的文件名
  • 使用 Exec Maven 插件分叉 Java,而不使用“exec”目标

    来自文档 https www mojohaus org exec maven plugin exec exec在单独的进程中执行程序和Java程序 exec java在同一虚拟机中执行 Java 程序 我想 fork 一个 java 程序
  • 我们可以有条件地声明 spring bean 吗?

    有没有一种方法可以有条件地声明 Spring bean 例如
  • 为什么 jar 执行的通配符在 docker CMD 中不起作用?

    我有一个Dockerfile与以下CMD启动我的 Spring Boot 应用程序 FROM java 8 jre CMD java jar app file jar 当我尝试从创建的图像启动容器时 我得到 Error Unable to
  • 在 Spring 中为 @Pathvariable 添加类级别验证

    在发布这个问题之前 我已经做了很多研究并尝试了很多可用的解决方案 这是我陷入的棘手情况 我有一个 Spring 控制器 它有多个请求映射 它们都有 PathVariables 控制器如下所示 Controller EnableWebMvc
  • 为什么在将 String 与 null 进行比较时会出现 NullPointerException?

    我的代码在以下行中出现空指针异常 if stringVariable equals null 在此语句之前 我声明了 stringVariable 并将其设置为数据库字段 在这个声明中 我试图检测该字段是否有null值 但不幸的是它坏了 有
  • 2^31 次方的 Java 指数错误 [重复]

    这个问题在这里已经有答案了 我正在编写一个java程序来输出2的指数幂 顺便说一句 我不能使用Math pow 但是在 2 31 和 2 32 处我得到了其他东西 另外 我不打算接受负整数 My code class PrintPowers
  • 从三点求圆心的算法是什么?

    我在圆的圆周上有三个点 pt A A x A y pt B B x B y pt C C x C y 如何计算圆心 在Processing Java 中实现它 我找到了答案并实施了一个可行的解决方案 pt circleCenter pt A
  • 按降序排序映射java8 [重复]

    这个问题在这里已经有答案了 private static
  • Tomcat 6 未从 WEB-INF/lib 加载 jar

    我正在尝试找出我的 tomcat 环境中的配置问题 我们的生产服务器正在运行 tomcat 安装并从共享 NFS 挂载读取战争 然而 当我尝试使用独立的盒子 及其配置 进行同样的战争时 我收到下面发布的错误 有趣的是 如果我将 WEB IN
  • Azure Java SDK:ServiceException:ForbiddenError:

    尝试了基本位置检索器代码 如下所示 String uri https management core windows net String subscriptionId XXXXXXXX 5fad XXXXXX 9dfa XXXXXX St
  • java实现excel价格、收益率函数[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 即使禁用安全性,OAuth 令牌 API 也无法在 Elastic Search 中工作

    我是 Elastic search 新手 使用 Elastic search 版本 7 7 1 我想通过以下方式生成 OAuth 令牌弹性搜索文档 https www elastic co guide en elasticsearch re
  • 如何让 Firebase 与 Java 后端配合使用

    首先 如果这个问题过于抽象或不适合本网站 我想表示歉意 我真的不知道还能去哪里问 目前我已经在 iOS 和 Android 上开发了应用程序 他们将所有状态保存在 Firebase 中 因此所有内容都会立即保存到 Firebase 实时数据

随机推荐

  • python中import与from方法总结

    这篇文章主要介绍了python中import与from方法总结 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 需要的朋友们下面随着小编来一起学习学习吧 一 模块 包简介 模块 所谓模块就是一个 py文件 用来存
  • ufo帧率测试网站_移动全平台性能测试分析工具:PerfDog性能狗

    点击关注 我们共同每天进步一点点 PerfDog是腾讯出品的移动端性能测试工具 致力于提升移动应用和游戏的性能和品质 主打游戏APP 当然应用APP也能用 介绍 移动全平台iOS Android性能测试 分析工具平台 快速定位分析性能问题
  • Linux下安装单节点kafka

    Linux下单节点kafka的安装 官网下载地址 http kafka apache org downloads 1 查看Linux防火墙 firewall cmd state 2 解压kafka到想要安装的Linux目录下 tar zxv
  • Gogs push 报 HTTP 401 错误解决方法

    Gogs push 报 HTTP 401 错误解决方法 error RPC failed HTTP 401 curl 22 The requested URL returned error 401 错误原因 用户名和密码错误 导致验证不通过
  • 笔记 学习51单片机串口中断

    单片机的串口通信功能是比较常用的功能 80C51的串行口 我在学习的过程中 觉得SBUF的使用方法是最难的 于是对着这个图和资料一步步理解 才搞明白一点 A SBUF 和 SBUF A 的意思 51单片机通过特殊功能寄存器SBUF对串行接收
  • 【前端】Vue项目:旅游App-(8)city:标签页Tabs动态数据:网络请求axios与request、数据管理store与pinia、各种封装

    文章目录 目标 过程与代码 安装相关库 封装网络请求相关代码 网络请求数据 网络请求数据操作封装 pinia管理数据并封装 tab栏改为动态数据 效果 本篇总结 总代码 修改或新建的文件 service index modules的city
  • pytorch:计算网络模型在gpu上的推理时间

    计算网络模型的推理时间 网络模型的推理过程是在gpu上进行的 方法一 import torch import time net net to cuda 网络模型 input input to cuda 输入 time start time
  • 最详细小白入门Python7-bug和调试

    bug调试工具的使用 打断点 在行号后边点击出现小红点 右键debug进入调试模式 代码执行暂停到断点位置代码执行之前 debugger 查看参数及变量在执行过程中的变化情况 console 查看控制台输出内容 step over 单步执行
  • pytorch图像检索评价指标MAP

    map是图像检索模型的一个评价指标 以图片中第一个计算AP值为例 P的分别是 1 2 3 3 6 4 9 5 10 R值分别是 1 5 2 5 3 5 4 5 1 AP计算结果 1 2 3 3 6 4 9 5 10 5 https blog
  • c语言蝴蝶图案代码,通达信指标公式,临界点蝴蝶图案出现,暴涨趋势出现(附源码)...

    暴涨临界点指标 如上图所示 保障临界点指标专门用于监控起爆买点 当临界点出现后期一定会有上升 一战成名主图 指标源码 DRAWGBK 1 RGB 36 38 40 RGB 24 16 51 0 1 0 VAR1B 100 EMA EMA C
  • UE4中英文语言切换的三种方式(当然也可以多种语言)

    一 用ue4的Localization Dashboard 1 2 3 4 5 最后 必须独立运行游戏才能看到效果 二 使用WidgetSwitcher 1 2 3 4 用一个按钮点击进行Index的修改 就可以完成中英文切换 三 用两个T
  • 2-软件生命周期模型

    软件生命周期模型 软件工程过程 工程项目的PDCA循环 戴明环 美国质量管理专家戴明博士针对工程项目的质量目标 将全面质量管理思想引入工程项目过程 提出了PDCA循环 也称为戴明环 即Plan 规划 Do 执行 Check 检查 Actio
  • PTA9文件操作(python3)

    python程序设计09 文件操作 9 1 从文件中查找最长的单词 20分 请勿修改 20 分 9 2 求文件行数 20 分 9 3 analyze the character distribution of a document 20 分
  • 最大报文段长度——MSS

    1 概念 MSS Maximum Segment Size 最大报文长度 是TCP协议定义的一个选项 MSS选项用于在TCP连接建立时 收发双方协商通信时每一个报文段所能承载的最大数据长度 在以太网环境下 MSS MTU 20字节TCP报头
  • unity按钮点击无响应的处理方法

    在程序中给Button控件添加了点击事件后无反应 可能由于下列原因导致 按钮的interactable false或者enable false 父节点如果有CanvasGroup组件 还必须把CanvasGroup组件上的interacta
  • 【CentOS 7.9】基于VMware虚拟机的详细安装教程

    一 下载CentOS 7 9 镜像文件 Linux版本大家自己选择 目前市面还是7 X版本用的多 这里我就以7 9版本为例进行演示 镜像下载地址 https mirrors tuna tsinghua edu cn centos 7 9 2
  • Ubuntu16.04LTS64位安装64JDK9.0.1

    第一步 去Oracle下载JDK 根据自己的需要选择不同的版本 这里选择的JDK9 0 1 下载地址 http www oracle com technetwork java javase downloads jdk9 downloads
  • yolov8保存结果

    找到predictor py文件加上如下代码 for result in self results path result path split images 1 split 0 boxes result boxes box boxes c
  • oracle 数据库truncate,Oracle中的truncate用法

    语法 TRUNCATE TABLE table 在使用truncate语句 DDL语言 可以删除表中的所有记录 使用truncate语句删除数据时 通常要比使用delete语句快得多 这是因为使用truncate语句删除数据时 不会产生任何
  • Spring中进行事务管理的两种方式

    1 Spring中事务管理的API 事务是指逻辑上要么全部成功 要么全部失败的一组操作 例如用户A给用户B转账 则用户A账户余额减少 用户B账户增加这两个操作就是一组事务 必须全部成功或失败撤回操作 不能出现A账户余额减少 B增加失败的情况