当前位置: 首页 > news >正文

西安做网站 怎样备案学生个人网页制作

西安做网站 怎样备案,学生个人网页制作,怎么做自已的网站,wordpress注册邮件设置密码最近在工作中遇到了两个关于事务操作的问题,顺便就着这两个问题又回顾了一遍Spring的事务相关的操作,想着一次性把这个问题研究明白了,后续使用事务的时候也能踏实点,让事务发挥真实的作用 什么是事务?什么是事务管理…

最近在工作中遇到了两个关于事务操作的问题,顺便就着这两个问题又回顾了一遍Spring的事务相关的操作,想着一次性把这个问题研究明白了,后续使用事务的时候也能踏实点,让事务发挥真实的作用

什么是事务?什么是事务管理?什么是Spring事务

什么是事务?事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用,关乎数据准确性的地方我们一定要用到事务,防止业务逻辑出错。

什么是事务管理,事务管理对于企业应用而言至关重要。它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保证用户和银行的利益都不受损失

关于事务的基本概念和定义可以参照我的另一篇Blog:【Spring学习笔记 九】Spring声明式事务管理实现机制。Sping事务简而言之就是一种JTA事务,这里不再详细展开。

一个用来演示的例子

我们还是沿用:【Spring学习笔记 九】Spring声明式事务管理实现机制这篇文章中的例子,只不过为了更贴近工作实战,这里我重构了一下代码实现。

单元测试入口

package com.example.springboot;import com.example.springboot.model.Person;
import com.example.springboot.service.PersonAggService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;@SpringBootTest
class SpringbootApplicationTests {@Resourceprivate PersonAggService personAggService;@Testpublic void springTransTest() {Person person = new Person();person.setUsername("wcong");person.setAge(30);person.setEmail("111111@qq.com");person.setPassword("111111");person.setPhone(11111111);person.setHobby("跳远");personAggService.addPerson(person, 100086L);}
}

聚合的Service方法

package com.example.springboot.service;import com.example.springboot.model.Person;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author tianmaolin004* @date 2023/8/6*/
@Service
public class PersonAggService {@Resourceprivate PersonService personService;@Resourceprivate PersonMaintainService personMaintainService;public void addPerson(Person person, Long creatorId) {//本地新增人员personService.insert(person);//保存人员创建者personMaintainService.savePersonCreator(creatorId);}
}

数据服务方法

package com.example.springboot.service;import com.example.springboot.dao.PersonDao;
import com.example.springboot.model.Person;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;@Service
public class PersonService {@ResourcePersonDao personDao;public List<Person> getPersonList() {return personDao.getPersonList();}public Person getPersonById(Integer id) {return personDao.getPersonById(id);}public void insert(Person person) {personDao.insert(person);}}

人员维护人添加方法

package com.example.springboot.service;import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;/*** @author tianmaolin004* @date 2023/8/6*/
@Service
public class PersonMaintainService {@Transactional(rollbackFor = Exception.class)public void savePersonCreator(Long userId) {System.out.println("保存人员创建者失败" + userId);throw new RuntimeException();}
}

数据表落库

在这里插入图片描述

不使用事务的情况

不使用事务的情况虽然单元测试报错了
在这里插入图片描述

但是数据库落库还是成功了:
在这里插入图片描述

遇到的两个事务问题

依据以上的基本case示例,模拟我遇到的两个问题和解决方案

Transaction rolled back because it has been marked as rollback-only

为了保证整体数据与预期一致可以回滚,我使用了事务,首先在外层加事务:

   @Transactional(rollbackFor = Exception.class)public void addPerson(Person person, Long creatorId) {//本地新增人员personService.insert(person);try {//发送人员同步到下游系统personMaintainService.savePersonCreator(creatorId);} catch (Exception e) {System.out.println("保存人员维护人异常但是被catch住了");}}

同时呢人员创建人这块我认为这里不需要报错阻塞整体操作,如果这里有问题只要有日志记录就行了,我通过巡检检查关注到即可,所以对这块代码加了try catch,但是呢因为内部代码不知道是谁写的也加了事务,

@Service
public class PersonMaintainService {@Transactional(rollbackFor = Exception.class)public void savePersonCreator(Long userId) {System.out.println("保存人员创建者失败" + userId);throw new RuntimeException();}
}

因为它们用的都是默认的传播机制,所以可以看做一个事务,使用REQUIRED传播模式,addAndSendPerson和savePersonCreator在同一个事务里面,savePersonCreator抛出异常要回滚,addAndSendPerson try Catch了异常正常执行commit,同一个事务一个要回滚,一个要提交,会报read-only异常,结果就是全部回滚,而外层所以这里就会出现rollback-only
在这里插入图片描述
解决方法有两种,一种是

干掉内层事务

内层的savePersonCreator事务干掉,这时数据也能落库成功了,事实上因为JTA的事务是有非常强的业务含义的,所以对于DAO层或简单的数据操作指令,不要加事务,否则对于较长的外部调用链路,会在传播过程中导致意外情况发生
在这里插入图片描述

内层声明为新事务

还有一种解决思路就是内层的事务声明为新事务

package com.example.springboot.service;import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;/*** @author tianmaolin004* @date 2023/8/6*/
@Service
public class PersonMaintainService {@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)public void savePersonCreator(Long userId) {System.out.println("保存人员创建者失败" + userId);throw new RuntimeException();}
}

声明后再跑单测:
在这里插入图片描述
数据也落库成功了,因为是两个独立事务,所以内层事务遇到异常回滚,外层事务捕获到了异常catch住了,没有继续回滚

事务设置为什么不生效?

还有个例子是方法设置了事务但是不生效,我们再调整下以上的代码,模拟一种场景:savePerson要执行很多事项,但是不希望saveDate的执行异常回滚影响整体回滚,所以saveDate中的核心数据操作被try catch,并且声明内部的savePersonCreator方法为新事务,符合上边我们提到的那种场景,这种情况下理论上savePersonCreator抛出异常后会使 personDao.insert(person);回滚,数据不能写入

@SpringBootTest
class SpringbootApplicationTests {@Resourceprivate PersonAggService personAggService;@Testpublic void springTransTest() {Person person = new Person();person.setUsername("wcong");person.setAge(30);person.setEmail("111111@qq.com");person.setPassword("111111");person.setPhone(11111111);person.setHobby("跳远");personAggService.savePerson(person, 100086L);}}@Service
public class PersonAggService {@ResourcePersonDao personDao;@Transactional(rollbackFor = Exception.class)public void savePerson(Person person, Long creatorId) {System.out.println("执行其它事项");saveDate(person, creatorId);}@Transactional(rollbackFor = Exception.class)public void saveDate(Person person, Long creatorId) {//本地新增人员try {savePersonCreator(person, creatorId);} catch (Exception e) {System.out.println("捕获到创建人员异常");}}@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)public void savePersonCreator(Person person, Long userId) {personDao.insert(person);System.out.println("保存人员创建者失败" + userId);throw new RuntimeException();}
}

但事实上,数据库写入数据能成功:
在这里插入图片描述
数据库数据写入成功了
在这里插入图片描述
这是因为:Spring中事务的默认实现使用的是AOP,也就是代理的方式,如果大家在使用代码测试时,同一个Service类中的方法相互调用需要使用注入的对象来调用,不要直接使用this.方法名来调用,this.方法名调用是对象内部方法调用,不会通过Spring代理,也就是事务不会起作用,所以实际上saveDate和savePersonCreator的事务都没有生效

把需要成为事务的方法单独抽出来

上述代码我们把需要有事务机制的savePersonCreator单独抽到一个方法中

@SpringBootTest
class SpringbootApplicationTests {@Resourceprivate PersonAggService personAggService;@Testpublic void springTransTest() {Person person = new Person();person.setUsername("wcong");person.setAge(30);person.setEmail("111111@qq.com");person.setPassword("111111");person.setPhone(11111111);person.setHobby("跳远");personAggService.savePerson(person, 100086L);}}@Service
public class PersonAggService {@ResourcePersonService personService;@Transactional(rollbackFor = Exception.class)public void savePerson(Person person, Long creatorId) {System.out.println("执行其它事项");saveDate(person, creatorId);}@Transactional(rollbackFor = Exception.class)public void saveDate(Person person, Long creatorId) {//本地新增人员try {personService.savePersonCreator(person, creatorId);} catch (Exception e) {System.out.println("捕获到创建人员异常");}}
}@Service
public class PersonService {@ResourcePersonDao personDao;public List<Person> getPersonList() {return personDao.getPersonList();}public Person getPersonById(Integer id) {return personDao.getPersonById(id);}@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)public void savePersonCreator(Person person, Long userId) {personDao.insert(person);System.out.println("保存人员创建者失败" + userId);throw new RuntimeException();}
}

这样savePersonCreator的事务就生效了,数据没有插入成功

Spring事务的更多传播机制

以上两个示例是真实工作中遇到的,基于安全原则模拟了两个类似的case,其实spring还有更多的花式的事务使用机制,可以参照带你读懂Spring 事务——事务的传播机制

总结一下

照例总结一下,在单一的数据操作方法不要加事务,事务应该是一系列操作指令的聚合,添加了细粒度的事务可能会导致上层使用者在方法添加事务时产生了非预期的传播机制。当然如果内外层的方法调用都很复杂,则基于自己的预期进行考虑,如果不希望内层方法影响外层方法,可以使用外层方法异常捕获加内层事务的REQUIRES_NEW传播机制解决。需要注意的是Spring的事务是基于AOP实现的,所以对象内部方法调用,不会通过Spring代理,也就是事务不会起作用,这点非常重要。

http://www.yidumall.com/news/8469.html

相关文章:

  • 电子商务网站开发的内容互联网营销策划案
  • 企业网站建设模板考研培训
  • 心悦免做卡领取网站做关键词推广
  • 张家港seo建站seo外包公司兴田德润
  • 东莞网站系统找哪里百度推广渠道
  • 平凉市政府门户网站软文发稿系统
  • b2b2c网站点击排名软件哪个好
  • 有哪些品牌做打底衫的网站百度搜索下载app
  • 做网站续费网络营销策略有哪几种
  • 贵阳做网站 优帮云seo引擎优化培训
  • 视觉传达设计网站百度快照怎么使用
  • 陕西省建设监理协会官方网站怎么下载有风险的软件
  • win主机伪静态规则 wordpressseo站内优化培训
  • 网站的项目建设周期南阳seo
  • 创新型的合肥网站建设网络营销措施有哪些
  • 做任务提现的网站seo超级外链工具
  • 个人网站制作网站整站优化工具
  • 做亚马逊联盟一定要有网站吗建网站的步骤
  • magento网站建设个人网站的制作
  • 1688批发厂家直销手机百度seo快速排名
  • wordpress采集mp4郑州seo价格
  • 怎么做关于易烊千玺的网站网站推广入口
  • 微信推广工具一键优化免费下载
  • 网站建设方案选公司怎么优化关键词
  • 嘉兴网站建设seo百度搜索历史记录
  • 精品课程网站设计代码石家庄限号
  • 建网站业务如何开展杭州上城区抖音seo有多好
  • 自己如何建立一个网站如何做好网上销售
  • 网站专题设计软件独立站seo怎么做
  • 西安有哪些网站windows优化大师可靠吗