我正在使用 Spring MVC 3 和 Hibernate 3.6,以及 Spring tx 来管理休眠事务,
现在我正在向控制器发出 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 = "<div id='please_wait' class='row-fluid'> </div> <div class='row-fluid'> <div class='span5 progress progress-striped active'> <div id='bar' class='bar'></div> </div> </div>";
if($("#bar").length == 0){
$("#bar_carrier").html(bar);
}
if(data < 100){
$("#bar").css("width",data+"%");
$("#please_wait").html("<font id='please-wait-font'>" +Math.round(data)+"% complete</font>");
}
else if(data >= 100 && (data == 203 || data == 204)){
var please_wait = "<font id='please-wait-font'>Finalizing and saving to database please wait<i class='icon-spinner icon-spin'</font>";
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("<h4 class='label label-success'>market is still open please try again later </h4>")
}
})
}
这是我关于更新进度和初始请求的控制器
@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() 工厂是自动装配的
public Session getSession(){
return (this.factory.getCurrentSession()==null)?
this.factory.openSession(): this.factory.getCurrentSession();
}
这就是通过 xml 配置管理我的事务的方式
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="tx" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="findById*" propagation="REQUIRED" />
<tx:method name="findBetween*" propagation="REQUIRED" />
<tx:method name="findFromTo*" propagation="REQUIRED" />
<tx:method name="updateOwnerId*" propagation="REQUIRED" />
<tx:method name="updateOwnerType*" propagation="REQUIRED" />
<tx:method name="findAllSearch*" propagation="REQUIRED" />
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="tx" pointcut="execution(* *..AbstractDao.*(..))" />
<aop:advisor advice-ref="tx" pointcut="execution(* *..TempDataDao.*(..))" />
<aop:advisor advice-ref="tx" pointcut="execution(* *..OwnershipDao.*(..))" />
<aop:advisor advice-ref="tx" pointcut="execution(* *..OwnersDao.*(..))" />
<aop:advisor advice-ref="tx" pointcut="execution(* *..ChangesDao.*(..))" />
<aop:advisor advice-ref="tx" pointcut="execution(* *..TargetCompaniesDao.*(..))" />
</aop:config>
控制器调用解析器的方法(一个会话范围的bean)来执行开始执行,解析器的功能是一个异步的,它又调用一个dao的另一个方法来保存,一切都很好,并且dao 的方法退出,然后在发送更新进度的所有请求完成后,事务开始,它们是否懒惰地完成了?我要做的就是在我到达保存方法或任何方法时进行转换。
编辑 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 负责填充未找到的列表,并且在这样做的同时将大量数据保存到数据库中,现在在所有这些完成之前不应返回进度,
但是发生的情况是进度返回为 204,就好像数据检查器已完成并且数据为空一样。
然后在事务开始发生之后,Like datachecker 只将它们添加到队列中。
但是这种情况发生在我导航到带有空 notFound 的另一个页面之后,并且在事务完成后刷新页面并且所有事情都完成时,页面现在有了数据。