用spring的时候,什么时候需要手动控制事务?在方法前加@Transaction不行么?

有这么一种场景,用户在web页面点击一个按钮,后台需要几分钟或几小时的长时间执行一段程序。这时如果页面不响应,用户感觉就一直卡在这里了。一种方法是起一个线程来跑这个程序,让请求立即返回。但这与我们平时的代码不太一样。平时的代码如果有事务直接放在Service的方法上就行了,再这个真正的执行是在一个线程里。而这里得不到外面的开的事务。所以就在执行方法里手动打开与关闭事务。

关于长时任务,在这篇文章中有介绍 《Java耗时任务怎么不重复执行》。这里就不多说了,看以下代码,根据经验1000行以下就直接执行,以上就开起一个线程跑数据:

@Transactional

public String processDatas(ImportVo importVo,List> data) {

String rstInfo=null;

WorkState startState=new WorkState(WorkState.STATE.DOING.getCode(),new Date(),null);

setWorkSate(importVo.getServiceId(),importVo.getGradeId(),JSONObject.toJSONString(startState));

if(data.size()<1000) {

try {

int sucNum=importAnswers(importVo);

rstInfo="成功导入"+sucNum+"份数据";

}catch(Exception e) {

log.error(e.getMessage(),e);

rstInfo=e.getMessage();

setWorkSate(importVo.getServiceId(),importVo.getGradeId(),JSONObject.toJSONString(new WorkState(WorkState.STATE.FAIL.getCode(),new Date(),e.getMessage())));

}

}else {

String key="TaskKey";

LongTimeWorkThread ltw=new LongTimeWorkThread() {

@Override

public void doWork() {

try {

int sucNum=importAnswers(importVo);

}catch(Exception e) {

log.error(e.getMessage(),e);

setWorkSate(importVo.getServiceId(),importVo.getGradeId(),JSONObject.toJSONString(new WorkState(WorkState.STATE.FAIL.getCode(),new Date(),e.getMessage())));

}

}

@Override

public Object finish() {

distributeWorkService.clearKey(key);

return null;

}

};

StartInfo startInfo=distributeWorkService.checkStart(key, ltw);

if(startInfo.isThisStartFlag()) {

rstInfo="启动成功,预计需要:"+data.size()/10+"秒";

}else {

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

rstInfo="启动失败,现在执行的是"+sdf.format(startInfo.getStartTime())+"开始的任务";

}

}

return rstInfo;

}

setWorkSate方法是设置这个任务的状态,方便用户了解任务的执行情况,前面两个是业务键,作为任务的主键。表结构如下:

CREATE TABLE `import_work` (

`id` bigint(20) NOT NULL,

`activity_id` bigint(20) DEFAULT NULL,

`grade_id` int(11) DEFAULT NULL,

`msg` varchar(512) DEFAULT NULL COMMENT '成功,失败信息',

`create_time` datetime DEFAULT NULL,

`update_time` datetime DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

这个processDatas也是有事务的。但在线程中的importAnswers方法就没有事务了。可以这样手动控制事务:

1.注入

@Autowired

private DataSourceTransactionManager dstManager

2.开启事务

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。

TransactionStatus transaction= dstManager.getTransaction(def); // 获得事务状态

3.提交事务

dstManager.commit(transaction);

4.回滚事务

dstManager.rollback(transaction);

我的项目中对数据源重新配置过了,配置方法见http://www.highersoft.net/html/notice/notice_447.html,所以第1步注入有问题。所以我的注入方法是这样的:

//DynamicDataSourceConfiguration是数据源配置类 @Configuration

@Autowired

private DynamicDataSourceConfiguration dynamicDataSourceConfiguration;

开启事务时,这样取事务管理对象:

PlatformTransactionManager dataSourceTransactionManager=dynamicDataSourceConfiguration.platformTransactionManager();

其它的一样。

如果在这个手工事务里想做个数据库操作让用户立刻可以看见,但又不想影响之前开的事务(之前开的事务未提交,不能让用户看见)。可以在方法中间再加一个方法,再开一个手工事务,代码同上,就可以了。

上面记录得有点乱,最近又遇到这个问题。对于大文件的导入还是用手工事务的方式,不过这次用简化的方法。直接取spring管理的org.springframework.jdbc.datasource.DataSourceTransactionManager,代码模板是这样。

@Autowired

private DataSourceTransactionManager transactionManager;

public String importFile(String fileName,Integer rewriteType) {

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。

TransactionStatus transaction = transactionManager.getTransaction(def); // 获得事务状态

try{

//业务处理

transactionManager.commit(transaction);

}catch(Exception e) {

transactionManager.rollback(transaction);

log.error(e.getMessage(),e);

}

return "成功导入";

}当然,业务处理这块可能比较麻烦,Exception处理也有些技巧。文件导入批量更新可参考《批量插入,用mybatis还是jdbc》

spring手动控制事务开启_手动控制spring事务相关推荐

  1. spring手动控制事务开启_“上帝视角”图解Spring事务的传播机制原理

    转载:https://mp.weixin.qq.com/s/odP1DKgRtXsCcAKxwGahug 数据库事务的"抓手" 数据库的事务功能已经由数据库自身实现,它留给用户的就 ...

  2. java spring 事务传播_实战Spring事务传播性与隔离性

    一.事务传播性 1.1 什么是事务的传播性 事务的传播性一般在事务嵌套时候使用,比如在事务A里面调用了另外一个使用事务的方法,那么这俩个事务是各自作为独立的事务执行提交,还是内层的事务合并到外层的事务 ...

  3. spring 事务 会话_测试Spring的“会话”范围

    spring 事务 会话 在基于Spring的Web应用程序中,bean的作用域可以是用户"会话". 从本质上讲,这意味着对会话范围Bean的状态更改仅在用户会话范围内可见. 本条 ...

  4. java 事务嵌套_解惑 spring 嵌套事务

    解惑spring嵌套事务 在所有使用spring的应用中,声明式事务管理可能是使用率最高的功能了,但是,从我观察到的情况看,绝大多数人并不能深刻理解事务声明中不同事务传播属性配置的的含义,让我们来看一 ...

  5. boot spring 接口接收数据_在 Spring Boot 中使用 Dataway 配置数据查询接口

    Dataway介绍 Dataway 是基于 DataQL 服务聚合能力,为应用提供的一个接口配置工具.使得使用者无需开发任何代码就配置一个满足需求的接口. 整个接口配置.测试.冒烟.发布.一站式都通过 ...

  6. java 数据库 事务 只读_不使用事务和使用只读事务的区别

    转转转,,还需要具体验证( 决定把readonly类型的事务完全去掉,以提高性能,这里有讨论:http://stackoverflow.com/questions/2562865/spring-tra ...

  7. java观察者模式在spring中的应用_利用spring自己实现观察者模式

    利用spring,自己实现的一个观察者模式,写着玩玩,目的是为了加深理解,下次用Spring自带的玩一玩. 首先我们定义一个侦听类接口 package com.hyenas.common.listen ...

  8. spring boot jar包_「Spring Boot 新特性」 jar 大小自动瘦身

    自动分析瘦身 Spring Boot 项目最终构建处理 JAR 包大小一直是个诟病,需要把所有依赖包内置最终输出可运行的 jar.当然可以使用其他的插件扩展 实现依赖 JAR 和 可运行 jar 分离 ...

  9. spring 多个数据库_在Spring使用多个数据库

    spring 多个数据库 在开发企业应用程序时,我们经常面临访问多个数据库的挑战. 也许我们的应用程序必须将数据归档到某个数据仓库中,或者也许它必须将数据传播到某个第三方数据库. 使用Spring可以 ...

  10. springboot默认开启事务吗_香~Spring Boot 应用也可以有配置中心。

    点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 8:55 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | J ...

最新文章

  1. Prim算法生成迷宫
  2. 第一次来写博客,这里可以记录很多故事。
  3. golang中的time详情
  4. 完全图解RNN、RNN变体、Seq2Seq、Attention机制
  5. 【哲学】自由意志是什么?(主观能动性)
  6. mysql xtrabackup-v2_pxc wsrep_sst_method均配置为xtrabackup-v2报错
  7. Framework 1.0/1.1中NotifyIcon的不足
  8. 查询链接服务器信息,如何通过 SQL Server 链接服务器和分布式查询使用 Excel
  9. python桌面应用html_是否将Python后端与HTML / CSS / JS用户界面集成到桌面应用程序? - javascript...
  10. 二叉树的前序、中序、后序遍历及互相求法
  11. C程序设计语言现代方法14:预处理器
  12. JDBC05 ResultSet结果集
  13. 捕获iOS模拟器视频以进行App预览
  14. 写在《Python高手修炼之道》发行之前:选择一本好书,即是少走弯路
  15. 计算机三维设计ppt,1 三维建模技术发展史.ppt
  16. Scenario 3 – HP C7000 Virtual Connect FlexFabric SUS with Active/Active
  17. 内存溢出(Memory Overflow)和内存泄露(Memory Leak)的区别
  18. 嗨!亲爱的朋友们,欢迎您光临我的BLOG
  19. HTTP中的301、302、303、307、308
  20. PPT批量替换字体、行间距操作

热门文章

  1. 多道程序 cpu利用率
  2. codeforces 题解
  3. keil5安装教程及下载
  4. linux按行将两个txt合并成一个文件
  5. 高性能可扩展mysql(电商数据库设计构思)
  6. html利用浏览器打印jquery.jqprint-0.3.js,制作票据通用模板js
  7. ubuntu下adb的使用以及开启黑域
  8. JavaScript的封装方法
  9. 分布式集群中网络分区问题
  10. amap不同样式marker点_amap不同样式marker点_CAD制图软件中如何设置CAD打印样式表(CTB)?...