gpt4 book ai didi

Spring @Async 生成 LazyInitializationExceptions

转载 作者:行者123 更新时间:2023-12-02 11:57:32 25 4
gpt4 key购买 nike

Spring MVC 应用程序需要执行需要几分钟的密集计算作业。客户端希望以异步方式运行此作业。但是在我在方法上启用 @Async 注释后(请参阅代码 1)并收到错误(请参阅代码 2)。我的 web.xml 和 web-appliaiton-context.xml 也如下所示。我试图找到一种解决方法来解决这个问题,但失败了。请帮忙。

代码1:

@Service
public class AsyncServiceImpl implements AsyncServiceInt{

protected int pertArrSize = 1000;
@Autowired
protected TblvDao tblvDao1 = null;

@Override
@Async
public void startSlowProcess(Integer scenarioId) throws SecurityException, IllegalArgumentException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
batchUpdateSummaryPertSim(scenarioId);

}

public void batchUpdateSummaryPertSim(Integer scenarioId) throws SecurityException, IllegalArgumentException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException
{
double[] summaryArry = new double[pertArrSize];
summaryArry = summaryPertSim_env(scenarioId, summaryArry);
}

@Transactional
private double[] summaryPertSim_env(Integer scenarioId,
double[] summaryArry) throws IOException, ClassNotFoundException, SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException {
ScenarioTblv scenario = tblvDao1.getScenarioTblv(scenarioId);
TblvResultSaved savedResult = scenario.getTblvResultSaved();
TblvScenarioCategory4 tblvScenarioCategory4 = new TblvScenarioCategory4();
List<TblvScenarioCategory4> tblvScenarioCategory4List = scenario
.getTblvScenarioCategory4List();
Double min = 0.0, max = 0.0, ml = 0.0;
Integer conf = 4;
if (savedResult.getEnvDist() != null) {

byte[] st = (byte[]) savedResult.getEnvDist();
ByteArrayInputStream baip = new ByteArrayInputStream(st);
ObjectInputStream ois = new ObjectInputStream(baip);

summaryArry = (double[]) ois.readObject();
} else {
for (int i = 0; i < tblvScenarioCategory4List.size(); i++) {
tblvScenarioCategory4 = tblvScenarioCategory4List.get(i);

vTblvScenarioEffectChoose v = tblvDao1
.getvTblvScenarioEffectChooseById(tblvScenarioCategory4
.getId());

if (v.getC1id() == 1) {
tblvScenarioCategory4.setImpactYearlyUnitsSim(pertArrSize);
min = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.getLowValue();
max = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.getHighValue();
ml = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.getMostValue();
conf = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue().getConf();
if ((conf == null) || (conf == 0))
conf = 4;

double[] MOPertArr;

MOPertArr = getPertArry(min, max, ml, conf, pertArrSize);

double[] benefitResult = new double[pertArrSize];

for (int j = 0; j < pertArrSize; j++) {
tblvScenarioCategory4.setSimIndex(j);
tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.setHighValue(MOPertArr[j]);
benefitResult[j] = tblvScenarioCategory4.getHighPvSum();
summaryArry[j] = summaryArry[j] + benefitResult[j];
}
tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.setHighValue(max);
}

}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(summaryArry);
byte[] summaryArryAsBytes = baos.toByteArray();
savedResult.setEnvDist(summaryArryAsBytes);
tblvDao1.saveTblvResultSaved(savedResult);
}
return summaryArry;
}

代码2:

 10:26:06,233 ERROR org.hibernate.LazyInitializationException:42 - failed to lazily initialize a collection of role: com.pb.prism.model.db.ScenarioTblv.tblvScenarioCategory4List, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.pb.prism.model.db.ScenarioTblv.tblvScenarioCategory4List, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
at com.pb.prism.util.AsyncServiceImpl.summaryPertSim_env(AsyncServiceImpl.java:446)
at com.pb.prism.util.AsyncServiceImpl.batchUpdateSummaryPertSim(AsyncServiceImpl.java:41)
at com.pb.prism.util.AsyncServiceImpl.startSlowProcess(AsyncServiceImpl.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:80)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">


<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.pb.prism.listener.MTAServletContextListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/web-application-context.xml</param-value>
</context-param>
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Enables Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Handles all requests into the application -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value />
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>

web-appliation-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="com.pb.prism" />

<!-- Imports the configurations of the different infrastructure systems of the application -->
<import resource="data-access-context.xml" />
<import resource="security-context.xml" />
<import resource="webmvc-context.xml" />

<bean id="applicationContextProvider" class="com.pb.prism.context.ApplicationContextProvider"></bean>

<!-- Configure the multipart resolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="2000000"/>
</bean>


<task:annotation-driven executor="myExecutor" />
<task:executor id="myExecutor" pool-size="5"/>
</beans>

最佳答案

这里的问题是,Spring 的 AOP 代理不会扩展,而是包装您的服务实例来拦截调用。这样做的效果是,从服务实例内对“this”的任何调用都会直接在该实例上调用,并且不能被包装代理拦截(代理甚至不知道任何此类调用)。(如 Spring @Transaction method call by the method within the same class, does not work? 中所述)

一个可能的解决方案是从服务中提取事务代码,并将其放入单独的类中。这样就可以拦截对事务方法的调用,并且可以进行事务了。

例如。

@Service
public class AsyncServiceImpl implements AsyncServiceInt{

@Autowired private SlowProcess slowProcess;

@Override
@Async
public void startSlowProcess(Integer scenarioId) {
slowProcess.execute(param);
}

..

public class SlowProcess {

@Transactional
public double[] execute() { .. }

}

关于Spring @Async 生成 LazyInitializationExceptions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17278385/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com