Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在MVC请求完成之前,Hibernate事务不会启动_Java_Spring_Hibernate_Spring Mvc_Spring Transactions - Fatal编程技术网

Java 在MVC请求完成之前,Hibernate事务不会启动

Java 在MVC请求完成之前,Hibernate事务不会启动,java,spring,hibernate,spring-mvc,spring-transactions,Java,Spring,Hibernate,Spring Mvc,Spring Transactions,我使用spring MVC 3和Hibernate 3.6以及spring tx来管理Hibernate事务 现在,我正在向控制器发出ajax请求,当控制器返回值时,我将导航到另一个页面,并不断检查控制器,直到返回值 这个controllers方法调用还有一些数据库事务要做,我试图做的是在每件事情完成、数据库发送完成并且一切正常时进行导航,但是发生的情况是hibernate的persist()或save()方法退出,但事务没有启动 我调试了代码,发现spring对事务执行某种队列处理,直到对控制

我使用spring MVC 3和Hibernate 3.6以及spring tx来管理Hibernate事务

现在,我正在向控制器发出ajax请求,当控制器返回值时,我将导航到另一个页面,并不断检查控制器,直到返回值

这个controllers方法调用还有一些数据库事务要做,我试图做的是在每件事情完成、数据库发送完成并且一切正常时进行导航,但是发生的情况是hibernate的persist()或save()方法退出,但事务没有启动

我调试了代码,发现spring对事务执行某种队列处理,直到对控制器的请求完成,这意味着它实际上不执行事务,而是说方法save已完成,将事务排队,然后稍后再执行

编辑

这是我的相关代码

           $("#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>")
                }
            })
        }
这是我在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>
现在我注意到了一个更为复杂的行为,dataChecker负责填充notfound列表,在这样做的同时,它将大量数据保存到数据库中,在完成所有操作之前,不应返回进度

但实际情况是,进度返回为204,就好像datachecker已经完成,而数据是空的一样

然后,事务开始发生,就像datachecker只将它们添加到队列中一样


但这是在我导航到另一个带有空notFound的页面后发生的,当事务完成后刷新页面时,页面现在就有了数据。

请注意,默认的Spring事务管理是线程特定的。每个事务状态(及其数据库连接)都存储在ThreadLocal变量(
TransactionSynchronizationManager
)中

这意味着,如果您在一个请求中启动事务(比如线程
http-0
),然后尝试通过从不同线程(比如
http-1
)进行的数据库查询来检查进度,那么您将不会成功第二个线程将有自己的事务,在第一个线程提交更改之前,它不会看到绑定到第一个线程的事务中的数据。

您实际需要的是在某个变量中定期存储和更新第一个线程(
http-0
)的进度,然后其他线程可以读取该进度


更新1:更具体一点-您的
解析器.getProgress()
不能调用数据库来获取正确的进度信息



更新2:刚刚注意到您的
getSession()
方法。独自打开新会话是一个严重的错误。这应该由Spring的事务管理器完成。如果
sessionFactory,您应该抛出一个异常。currentSession()
返回
null

请使用控制器的相关代码和Ajax请求更新您的问题。最重要的部分是事务划分是可见的。这是问题所在,它不是,进度是基于dao方法调用的,当dao方法退出时,它应该调用事务,但它不是这样,它只是退出,然后进度会增加,等等,在完成之后,我的观点是,您不能使用DAO方法来获得进度。您的查询将位于不同的事务中。也许您可以在问题中添加
解析器的示例
…刚刚注意到您的
getSession()
代码。我已经更新了我的问题。注意,打开和关闭会话必须由Spring的事务管理器完成。否则,您将使用AOP配置。您的意思是我不应该自动连接我的工厂吗?因为这就是我正在做的,我正在自动连接我的工厂,然后从它那里获得会话,如何从tx经理那里获得会话?不。。。这与自动连接会话工厂无关。没关系。您不应该调用
sessionFactory.openSession()
。检查我的答案更新2。
<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>
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;