在MVC请求完成之前,Hibernate事务不会启动
我正在使用spring MVC 3和Hibernate 3.6,使用Spring tx来管理hibernate事务,
现在我正在向控制器发出一个ajax请求,当控制器返回一个值时,我导航到另一个页面,我继续检查控制器,直到返回值。
这个控制器方法调用也有一些数据库事务要做,而我想要做的是在每个事情完成并且数据库tx完成并且一切都很好时导航,但是会发生什么是hibernate的persist()或save( )方法退出但事务未启动。
我调试了代码并发现spring对事务执行了某种队列,直到对控制器的请求完成为止,这意味着它不会执行事务,而是表示方法已完成,并对事务进行排队然后执行此操作后来。
编辑
这是我的相关代码
$("#kse_search").click(function (e){ $.get('updateProgress',function(data){ if(data == 'NaN' || data < 0){ $(".modal-backdrop").removeClass("hidden"); $("#bar_carrier").removeClass("hidden"); $.get('kse.htm'); interval = setInterval("ajaxP()",1000); }else{ alert("There is an ongoing query for the same session, please wait until its finished"); } }); }) // updata progress function ajaxP(){ $.get('updateProgress',function(data){ datain = data; if(data != 404){ var bar = " "; if($("#bar").length == 0){ $("#bar_carrier").html(bar); } if(data < 100){ $("#bar").css("width",data+"%"); $("#please_wait").html("" +Math.round(data)+"% complete"); } else if(data >= 100 && (data == 203 || data == 204)){ var please_wait = "Finalizing and saving to database please wait<i class='icon-spinner icon-spin'"; if($("#please-wait-font").length == 0) { $("#bar").css("width",data+"%"); } else{ $("#please_wait").html(please_wait); $("#bar").css("width",data+"%"); } clearInterval(interval); setTimeout('ajaxProgress()',2*60*1000); } } else{ clearInterval(interval); $("#bar_carrier").html("market is still open please try again later
") } }) }
这是我的控制器有关更新进度和初始请求
@RequestMapping("/kse.htm") public @ResponseBody String kseData(Model model){ parser.setExchange("kse"); boolean choice = parser.start(); return String.valueOf(choice); } @RequestMapping("/updateProgress") public @ResponseBody String progress(Model model){ float progress = parser.getProgress(); if(progress != 404 && progress != 204 && progress != 203){ return String.valueOf((progress/parser.getTotalProgress())*100); } else{ return String.valueOf(progress); } }
这是我的dao函数中的保存函数
public boolean add(T entity) { getSession().save(entity); return true; }
这是我的getSession()工厂自动assembly
public Session getSession(){ return (this.factory.getCurrentSession()==null)? this.factory.openSession(): this.factory.getCurrentSession(); }
这就是我的事务通过xml配置管理的方式
控制器调用解析器的方法(一个会话范围的bean)来执行开始执行,解析器的函数是一个Async,它依次调用dao的另一个方法来执行保存,每个东西都工作正常, dao的方法退出然后发送到更新进度的所有请求完成后,事务开始了,他们是否懒得完成? 我想要做的就是在我到达save方法或任何方法时进行转换。
编辑2
好的,这是我更新进度或重要部分的方法
if(found != null){ this.tempData = found; notFound = dataChecker.checkData(found); if(notFound.size() == 0){ saveAllData(addDuplicates(dataChecker.getModifiedHolders())); this.progress = 204; return true; } else { this.progress = 203; return false; } } return false;
现在我注意到了一些更糟糕的行为,dataChecker负责填充未发现的List,并且在这样做时它将很多数据保存到数据库,现在不应该返回进度,直到所有这些完成,
但是会发生的是,进度返回为204,就好像datachecker已经完成并且数据为空。
然后事务开始发生,像datachecker只将它们添加到队列中。
但是在我使用空的notFound导航到另一个页面之后会发生这种情况,并且在事务完成后刷新页面并且每件事都完成后,页面现在都有数据。
请注意,默认的Spring事务管理是特定于线程的 。 每个事务状态(及其数据库连接)都存储在ThreadLocal变量( TransactionSynchronizationManager
)中。
这意味着,如果您在一个请求中启动事务(假设线程为http-0
)然后您尝试通过从不同线程(假设为http-1
)进行的数据库查询来检查进度,那么您将无法成功。 第二个线程将拥有自己的事务,并且在第一个线程提交更改之前,它不会看到绑定到第一个线程的事务中的数据。
您实际需要的是在某个变量中定期存储和更新第一个线程( http-0
)的进度,然后可以由其他线程读取。
更新1:更具体一点 – 您的parser.getProgress()
不得调用数据库以获取正确的进度信息。
更新2:刚刚注意到你的getSession()
方法。 自己打开新会话是一个严重的错误 。 这应该由Spring的事务管理器完成。 如果sessionFactory.currentSession()
返回null
则应抛出exception。
- 支持实体 – 属性 – 值模型的Java框架
- JPA / Hibernate选择查询返回重复记录
- Hibernate:映射未找到exception
- 我的自定义存储库实现中的CrudRepository
- 检查hibernate映射类中的不变量
- Spring Boot 1.2.5 Hibernate JPA嵌套了很多对很多关系
- sessionfactory.openSession()和sessionfactory.openStatelessSession()之间的区别?
- 从另一个DAO调用一个DAO?
- 无法创建sessionFactory object.org.hibernate.InvalidMappingException:无法解析资源Employee.hbm.xml中的映射文档