黄石本土做网站的公司,信息流广告怎么投放,视频制作用什么软件,网络游戏美术设计专业1.事务简介 事务#xff08;transaction#xff09;是访问并可能操作各种数据项的一个数据库操作序列#xff0c;这些操作要么全部执行#xff0c;要么全部不执行#xff0c;是一个不可分割的工作单位。 事物的四大特性: 原子性#xff08;Atomicity#xff09;#xf…1.事务简介 事务transaction是访问并可能操作各种数据项的一个数据库操作序列这些操作要么全部执行要么全部不执行是一个不可分割的工作单位。 事物的四大特性: 原子性Atomicity 原子性指事务是一个不可分割的工作单位事务中包括的操作要么全部完成要么全部不完成不可能结束在中间某个环节。事务中的所有操作要么全部提交成功要么在发生错误时全部回滚撤销对数据库的所有更改。这意味着事务内的操作如果失败了那么会回滚到事务开始前的状态就像这些操作从来没有发生过一样。一致性Consistency 一致性确保事务将数据库从一个一致的状态转变为另一个一致的状态。在事务开始之前和事务结束以后数据库的完整性没有被破坏。这表示写入的任何数据都必须满足所有设置的规则包括约束、触发器、级联更新等。例如在转账事务中无论进行多少次转账操作所有用户的总金额应保持不变。隔离性Isolation 多个事务并发执行时一个事务的操作不应影响其他事务。隔离性通过提供“单独”的环境来保证事务不受其他并发事务的影响。这意味着一个事务内部的操作及使用的数据对并发的其他事务是隔离的反之亦然。这有助于防止数据在并发操作中产生不一致的问题。持久性Durability 一旦事务提交则其结果永久保存在数据库中。即使系统崩溃、重启或发生故障数据库还能恢复到事务成功结束时的状态。这意味着一旦事务被提交它对数据库中数据的改变就应该是永久性的。 2.数据库中使用事务
需求账号A向账号B转账账户A更新余额后账户B也同时更新余额
初始数据 操作语句
update account set balance1000 where account_numberA;update account set balance3000 where account_numberB;
操作结果 问题当在执行B失败时数据库数据异常如下 问题A更新数据B数据却未更新。
解决方案事务引入将这两个操作作为一个事务两个事务必须同时成功才能写入数据库。
#开启事物
start transaction ;
update account set balance1000 where account_numberA;update ;#抛出异常update account set balance3000 where account_numberB;
#提交事物,如果执行成功则同时写入数据库
commit ;
#回滚事物,如果执行失败则返回到数据库执行开始状态
ROLLBACK ; 执行结果 3.事物并发问题 在事务处理、数据库操作或任何需要确保数据一致性和完整性的系统中并发问题特别重要。当多个事务或用户同时尝试访问和修改相同的数据时可能会出现以下问题 脏读Dirty Read一个事务读取了另一个尚未提交的事务的数据。如果未提交的事务在之后被回滚那么之前读取的数据将是无效的。不可重复读Non-repeatable Read在同一个事务内由于其他事务的修改导致多次读取同一数据返回的结果有所不同。幻读Phantom Read一个事务在读取某些行的集合时另一个事务插入了新的行导致前一个事务在再次读取相同的范围时看到额外的“幻影”行。丢失更新Lost Update两个事务都读取了同一数据然后都对其进行了修改但第二个事务的修改覆盖了第一个事务的修改导致第一个事务的修改丢失。 为了解决这些问题数据库管理系统DBMS通常提供事务隔离级别来控制并发事务之间的交互。这些隔离级别包括 读未提交Read Uncommitted允许读取尚未提交的事务的数据。这是隔离级别最低的情况可能导致上述所有并发问题。读已提交Read Committed只允许读取已提交的事务的数据。这可以防止脏读但可能仍然会出现不可重复读和幻读。可重复读Repeatable Read确保在同一个事务内多次读取同一数据返回的结果是一致的。这可以防止脏读和不可重复读但可能仍然会出现幻读。串行化Serializable这是最高的隔离级别它强制事务序列化执行从而防止上述所有并发问题。但这也可能导致性能下降因为事务需要等待其他事务完成。 4.springboot项目中使用声明式事务
在Spring框架中声明式事务管理是一种更简洁和声明性的方法来管理事务通常是通过注解来实现的。声明式事务将事务管理的逻辑与业务逻辑分开使开发者无需关心事务的底层细节。在Spring Boot中声明式事务管理主要通过Transactional注解来实现。
下面是如何在Spring Boot中使用声明式事务的步骤
1.启用事务管理
确保在启动类或配置类上添加了EnableTransactionManagement注解以启用Spring的事务管理功能。 import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement; SpringBootApplication
EnableTransactionManagement
public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
2.使用Transactional注解
在需要事务管理的方法或类上使用Transactional注解。这个注解告诉Spring该方法需要在事务的上下文中执行。 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; Service
public class MyService { // ... 依赖注入和数据访问层代码 Transactional public void performTransactionalTask() { // 在这里执行你的业务逻辑 // 如果抛出运行时异常事务会自动回滚 }
}
Transactional注解可以应用于方法或类级别。当应用于类级别时它会影响类中的所有公共方法。
3.配置事务属性
Transactional注解支持多种属性用于定义事务的传播行为、隔离级别、超时和只读属性。 Transactional(propagation Propagation.REQUIRED, isolation Isolation.DEFAULT, timeout 30, readOnly false)
public void performTransactionalTask() { // ...
}
propagation定义事务的传播行为例如Propagation.REQUIRED表示当前方法必须在一个事务中运行如果当前存在事务则加入该事务如果当前没有事务则创建一个新的事务。isolation定义事务的隔离级别如Isolation.DEFAULT使用数据库默认的事务隔离级别。timeout定义事务的超时时间单位是秒。readOnly指定事务是否只读。如果设置为true则事务只读取数据而不修改数据。
4.异常处理
默认情况下如果在事务方法内部抛出了运行时异常RuntimeExceptionSpring会触发事务回滚。对于已检查的异常checked exceptionsSpring不会触发回滚除非明确指定了Transactional注解的rollbackFor属性。
Transactional(rollbackFor Exception.class)
public void performTransactionalTask() throws Exception { // 如果抛出Exception或其子类事务会回滚
}
5.事务的传播行为Propagation Behavior
定义了当事务方法被另一个事务方法调用时应如何使用事务。这主要涉及到如何处理嵌套事务的情况。Spring框架提供了多种传播行为选项这些选项可以通过Transactional注解的propagation属性来设置。以下是Spring框架中定义的事务传播行为
PROPAGATION_REQUIRED如果当前存在事务则加入该事务如果当前没有事务则创建一个新的事务。这是最常见的选择通常作为默认的事务传播行为。 PROPAGATION_SUPPORTS如果当前存在事务则加入该事务如果当前没有事务则以非事务的方式继续运行。这意味着方法可以在事务中运行也可以不在事务中运行取决于调用它的代码是否处于事务中。PROPAGATION_MANDATORY如果当前存在事务则加入该事务如果当前没有事务则抛出异常。这要求调用方法必须在一个事务中运行。PROPAGATION_REQUIRES_NEW总是开启一个新的事务。如果当前存在事务则将其挂起。这意味着无论调用方法是否处于事务中被调用方法都将在一个新的事务中运行。PROPAGATION_NOT_SUPPORTED以非事务方式执行操作如果当前存在事务则将其挂起。这意味着方法将不会在一个事务中运行即使调用它的代码处于事务中。PROPAGATION_NEVER以非事务方式执行如果当前存在事务则抛出异常。这要求调用方法不能在一个事务中运行。PROPAGATION_NESTED如果当前存在事务则嵌套事务作为当前事务的一个子事务运行如果当前没有事务则执行PROPAGATION_REQUIRED行为。这意味着如果在一个事务中调用该方法那么该方法将在嵌套事务中运行嵌套事务可以独立回滚而不影响外部事务。 6.事务的回滚 在Java中使用JDBC或ORM框架如Hibernate、MyBatis等时开发者可以通过调用相应的API来触发事务回滚。例如在使用JDBC时可以通过调用Connection对象的rollback()方法来回滚事务。而在使用Spring框架时可以通过在方法上添加Transactional注解并指定rollbackFor属性来指定需要触发回滚的异常类型。 7.实例
描述: 将用户预约id为1的车位预约信息存入数据库并更新该车位状态在预约信息存入数据库后抛出错误观察事务是否成功。
数据库初始状态 关键代码
/*** 预约处理* param model* param request* return*/PostMapping(/car/orderDetail)Transactional(propagation Propagation.REQUIRED)public String orderDetail(Model model,HttpServletRequest request){String username request.getParameter(username);String tel request.getParameter(tel);String parkId request.getParameter(id);//车位编号String location request.getParameter(location);String date request.getParameter(date);String time request.getParameter(time);String totalprice request.getParameter(totalprice);String type request.getParameter(type);String duration request.getParameter(duration);OrderParking orderParkingnew OrderParking();// 拼接日期和时间字符串String datetime_str date time;// 定义日期时间格式DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm);// 将拼接后的字符串转换为LocalDateTime对象LocalDateTime datetime_obj LocalDateTime.parse(datetime_str, formatter);orderParking.setDate(datetime_obj);orderParking.setLocation(location);orderParking.setTel(tel);orderParking.setParkId(Integer.valueOf(parkId));orderParking.setTotalprice(Double.valueOf(totalprice));orderParking.setType(type);orderParking.setUsername(username);// 计算截止时间LocalDateTime endTime datetime_obj.plusSeconds(Long.parseLong(duration)*3600L);orderParking.setDeadtime(endTime);orderParking.setDuration(Double.valueOf(duration));orderParking.setType(type);//判断是否可以预约int status1 orderService.findStatus(Integer.parseInt(parkId));if(status11){model.addAttribute(msg, 该车位已预约);model.addAttribute(target, http://address:port/order/list);return /operate-result;}//将预约表单存入数据库int i orderService.addOrderParking(orderParking);//这里模拟异常String snull;System.out.println(s.toString());//更新车位表状态int status orderService.updateStatus(Integer.parseInt(parkId));if(status1i1){model.addAttribute(msg, 预约成功);model.addAttribute(target, http://address:port/order/list);return /operate-result;}model.addAttribute(msg, 预约失败);model.addAttribute(target, http://address:port/order/list);return /operate-result;}
执行结果 预约表中记录并为增添且车位状态并未更新(第二列为预约车位编号) 事务执行成功 5.编程式事务 编程式事务管理指的是在代码中显式地管理事务的边界和逻辑而不是依赖于声明式的方式如注解。在编程式事务管理中开发者需要手动开始、提交或回滚事务。Spring框架提供了TransactionTemplate和PlatformTransactionManager等API来支持编程式事务管理。 以下是使用编程式事务管理的基本步骤
1.配置事务管理器
首先你需要在Spring配置中定义一个PlatformTransactionManager的bean。这通常是基于你使用的数据源类型如JDBC、Hibernate、JPA等来决定的。
例如对于JDBC你可以这样配置一个DataSourceTransactionManager
2.使用TransactionTemplate
TransactionTemplate是Spring提供的一个帮助类它简化了编程式事务的使用。你可以创建一个TransactionTemplate的bean并注入你的事务管理器。然后你可以在你的服务代码中使用这个TransactionTemplate来执行需要事务管理的操作。
这里是转账的逻辑
Autowired
OrderMapper orderMapper;
public void update(String A,int aBalance,String B,int bBalance){transactionTemplate.execute(new TransactionCallbackWithoutResult() {Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {try {// 在这里执行你的业务逻辑orderMapper.updateAccount(A,aBalance);String snull;System.out.println(s.toString());orderMapper.updateAccount(B, bBalance);// 如果抛出运行时异常事务会自动回滚} catch (Exception e) {// 可以选择手动回滚status.setRollbackOnly();throw e;}}});}
3.手动管理事务
除了使用TransactionTemplate你还可以直接使用PlatformTransactionManager来手动开始、提交和回滚事务。这通常是通过TransactionStatus对象来完成的。 import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.PlatformTransactionManager; Service
public class MyService { private final PlatformTransactionManager transactionManager; public MyService(PlatformTransactionManager transactionManager) { this.transactionManager transactionManager; } public void performManualTransactionalTask() { TransactionStatus status transactionManager.getTransaction(new DefaultTransactionDefinition()); try { // 在这里执行你的业务逻辑 // 如果抛出运行时异常事务会自动回滚 transactionManager.commit(status); } catch (Exception e) { // 发生异常手动回滚事务 transactionManager.rollback(status); throw e; } }
}