一、问题:
使用的grails开发项目当配置多个数据源时,非默认数据源的事务会失效
二、探索:
网上找到spring同样存在这样的问题,必须使用atomikos
三、atomikos插件
grails官网上有atomikos插件,但是好多年不用了,并且这个插件是在grails1.3.5基础上开发的,并且依赖的jar也下载不下来了,更不要谈安装插件了
最后尝试将插件代码下载下来,重新修改,修改需要注意几个问题
1、grails版本要改为你项目用的版本
2、BuildConfig文件中dependencies引用到的jar包都下载不下来,需要自己手动下载相应的jar包,注意版本问题,并且注释掉dependencies里面的所有compile
3、修改文件AtomikosGrailsPlugin.groovy中
System.setProperty 'com.grails.atomikos.icatch.service',UserTransactionServiceFactory.name
的“grails”去掉
上面的三个问题修改后,就可以打自己的atomikos的插件了,见附件
四、grails+atomikos
在项目中安装自己打好的插件,开始配置了
1、BuildConfig.groovy
plugins { ... compile ':atomikos:1.0' }
2、Config.groovy
grails.plugin.atomikos.uts = [ 'com.atomikos.icatch.console_file_name' : 'tm.out', 'com.atomikos.icatch.log_base_name' : 'tmlog', 'com.atomikos.icatch.tm_unique_name' : 'tsTransactionManager', 'com.atomikos.icatch.console_log_level' : 'ERROR', 'com.atomikos.icatch.log_base_dir' : 'target/atomikos', 'com.atomikos.icatch.output_dir' : 'target/atomikos', 'com.atomikos.icatch.force_shutdown_on_vm_exit': 'true']
3、数据源配置DataSource.groovy
development { //默认数据源 dataSource { pooled = true url = 'jdbc:mysql://localhost:3309/main driverClassName = 'com.mysql.jdbc.Driver' properties { username = "root" password = "root" maxIdle = "30" maxWait = "10000" maxActive = -1 } xaConfig = [ driverClassName: 'com.mysql.jdbc.jdbc2.optional.MysqlXADataSource', driverProperties: [ URL: 'jdbc:mysql://localhost:3309/main', user: 'root', password: 'root', pinGlobalTxToPhysicalConnection: "true", autoReconnect: true, autoReconnectForConnectionPools: true, autoReconnectForPools: true], minPoolSize: 1, maxPoolSize: 50 ] } //非默认数据源 dataSource_ts { pooled = true url = 'jdbc:mysql://localhost:3309/ts?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull' driverClassName = 'com.mysql.jdbc.Driver' properties { username = "root" password = "root" maxIdle = "30" maxWait = "10000" maxActive = -1 } xaConfig = [ driverClassName: 'com.mysql.jdbc.jdbc2.optional.MysqlXADataSource', driverProperties: [ URL: 'jdbc:mysql://localhost:3309/ts?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull', user: 'root', password: 'root', pinGlobalTxToPhysicalConnection: "true", autoReconnect: true, autoReconnectForConnectionPools: true, autoReconnectForPools: true], minPoolSize: 1, maxPoolSize: 50 ] } }
pinGlobalTxToPhysicalConnection: "true"其中这个一定要配置,否则会有问题,请参见http://www.atomikos.com/Documentation/KnownProblems#MySQL_XA_bug
4、测试代码
1)分别创建两个类MainTask使用默认数据源,Task使用ts
2)Service代码
class TaskService { //默认为true,当改为false抛任何异常,数据都会保存 static transactional = true; def saveTask() { // Task t = Task.get(92l);//更新 Task t = new Task(); t.taskName = t.taskName + "testdhw_noclick" t.save(); saveOpenTask() } Object saveOpenTask() { OpenTask ot = new OpenTask(); ot.taskName = ot.taskName + "open_task_test" ot.save(); throw new RuntimeException("save task fail!"); } }
验证事务已经起作用了,当 transactional =false,即使最后抛出RunTimeException异常,数据同样会保存
五、另外一个问题
多数据源事务失效问题引起的另外一个“分页查询”问题也同时得到了解决
grails分页的确很方便,但是当你所查询的类不是默认数据源时,悲剧了,你必须将得transactional =false才能正常查询,(ps:曾经啊,,,曾经就让这个问题悄悄溜过去了)
控制类代码如下
class TaskController { TaskService taskService; def list = { def resultMap = [:]; try { PagedResultList pageList = taskService.queryTaskByCondition(params); //Task为非默认数据源,在不使用插件的情况下,在事务开启状态时,控制类里获取总数方法会报connection is close!!! if (pageList.getTotalCount() == 0) { resultMap << ['total': 0]; resultMap << ['rows': []]; } else { resultMap << ['total': pageList.getTotalCount()]; resultMap << ['rows': pageList.list]; } } catch (Exception e) { log.error("查询任务列表出错:" + e.getMessage(), e); resultMap << ['total': 0]; resultMap << ['rows': []]; } render(resultMap as JSON); } }
service代码如下
class TaskService { static transactional = true; PagedResultList queryTaskByCondition(GrailsParameterMap params) { def currPage = params.page ? Integer.valueOf(params.page) : 1; def pageSize = params.rows ? Integer.valueOf(params.rows) : 10; def offset = (currPage - 1) * pageSize; params.max = pageSize; params.offset = offset; def searchParam = { order('updateTime', "desc"); order('id', "desc"); } def criteria = Task.createCriteria(); PagedResultList pageResult = criteria.list(params, searchParam); return pageResult; } }
六、相关查阅资料
1、spring存在同样的问题解决方案
http://loftor.com/archives/spring-mybatis-tomcat-jta.html
2、插件依赖的jar下载,注意版本注意版本注意版本(重要的事说三遍)
http://mvnrepository.com/artifact/com.atomikos
3、官方插件文档
http://grails-plugins.github.io/grails-atomikos/docs/manual/guide/2%20Getting%20Started.html
4、github插件源码
http://grails-plugins.github.io/grails-atomikos/
5、jtapropertie介绍
http://www.atomikos.com/Documentation/JtaProperties
相关推荐
基于springboot的招聘求职系统源码数据库文档.zip
基于springboot的校园自助洗衣服务管理系统源码数据库文档.zip
基于java的家乡特产网上商城的开题报告.docx
基于java的校园跑腿管理系统的开题报告
毕业设计&课设_ 健身房管理系统 Java 后端,含多种功能模块,代码完整开源.zip
基于springboot的小学家校互联平台源码数据库文档.zip
基于java的线上选课系统的开题
基于springboot+vue的桂林旅游网站系统源码数据库文档.zip
基于springboot协同过滤算法的个性化音乐推荐系统源码数据库文档.zip
基于SpringBoot的中药材管理系统源码数据库文档.zip
基于springboot的电缆行业生产管理系统源码数据库文档.zip
最新HTML一键打包EXE工具2.0.0, 采用了新的内核, 相比1.x版本, 支持更多最新浏览器特性. HTML一键打包EXE工具能把任意HTML项目(址)一键打包为单个exe文件,在脱离浏览器及服务器的情况下直接运行,支持课件,游戏,址等各类项目.
基于SpringBoot的社区居民诊疗健康管理系统源码数据库文档.zip
上传【mysql数据库项目】资源
压缩文件(3).zip
安装office2010时经常会提示MSXML未安装等问题,导致无法继续安装,使用此一键修复工具可以完美解决
基于springboot的网上商城源码数据库文档.zip
详情介绍 html实现的破碎拼接文字动画特效代码是一段会自动产生文字依次破碎再拼接的效果,非常的炫。欢迎对此段代码感兴趣的朋友前来下载使用。
基于springboot高考志愿智能推荐系统源码数据库文档.zip
Oracle数据库是一种功能强大的关系型数据库管理系统,在企业中被广泛使用。为了方便用户进行数据库管理和操作,Oracle提供了丰富的命令集。 《Oracle常用命令速查手册》将介绍一些常用的Oracle命令和其用法,比如数据导入导出命令、存储过程和触发器的管理以及性能监控等方面的常用命令,通过简单明了的示例,展示了每个命令的用法和效果,以帮助读者更好地理解和使用Oracle数据库