Java 从Grails控制器启动的新线程的Hibernate会话问题
我有一个运行良好的Grails2.2.4项目。最近我遇到了一个问题。该应用程序打印一份报告,并以PDF格式下载。客户在DB中有大量记录用于该报告,因此生成该报告需要花费大量时间。因此,我需要将其添加为一个新线程,以便在后台运行并生成报告并将其发送给用户 因此,我创建了一个新类,该类实现Runnable并调用从controller调用的相同服务Java 从Grails控制器启动的新线程的Hibernate会话问题,java,spring,multithreading,hibernate,grails,Java,Spring,Multithreading,Hibernate,Grails,我有一个运行良好的Grails2.2.4项目。最近我遇到了一个问题。该应用程序打印一份报告,并以PDF格式下载。客户在DB中有大量记录用于该报告,因此生成该报告需要花费大量时间。因此,我需要将其添加为一个新线程,以便在后台运行并生成报告并将其发送给用户 因此,我创建了一个新类,该类实现Runnable并调用从controller调用的相同服务 public class JasperReportProcessor implements Runnable { private static fi
public class JasperReportProcessor implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(JasperReportProcessor.class);
private ReportProcessor reportProcessor;
private Parties party;
private String bObject;
private String contextUrl;
private String shipmentIds;
private Map<String, String> parameters;
private Locale locale;
public JasperReportProcessor() {}
public JasperReportProcessor(final ReportProcessor reportProcessor, final Parties party,
final String bObject, final String contextUrl, final String shipmentIds, final Map<String, String> parameters) {
this.reportProcessor = reportProcessor;
this.party = party;
this.bObject = bObject;
this.contextUrl = contextUrl;
this.shipmentIds = shipmentIds;
this.parameters = parameters;
this.locale = locale;
}
@Override
public void run() {
SessionFactory sessionFactory = DataSQLSupport.getSessionFactory();
Session currentSession = null;
Transaction tx =null;
try {
currentSession = sessionFactory.openSession();
tx = currentSession.beginTransaction();
LOG.info("THREAD STARTED for REPORT....................");
//Below code was earlier called directly from Controller.
Object[] reportData = this.reportProcessor.process(this.party, this.bObject, this.contextUrl, this.shipmentIds, this.parameters, this.locale);
LOG.info("REPORT generated....{}", reportData[0]);
LOG.info("THREAD ENDED...........");
tx.commit();
} catch (Exception ex) {
LOG.error("OMG ERROR in THREAD....", ex);
tx.rollback();
} finally {
currentSession.flush();
currentSession.close();
}
}
}
@Component
class DataSQLSupport{
private static SESSION_FACTORY;
public DataSQLSupport() {}
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
SESSION_FACTORY = sessionFactory;
}
public static SessionFactory getSessionFactory(){
return SESSION_FACTORY;
}
public static List<Object[]> getDataList(final String dataQuery) {
Session currentSession = SESSION_FACTORY.getCurrentSession();
Query query = currentSession.createSQLQuery(dataQuery);
return (List<Object[]>) query.list();
}
}
我已尝试在datasource.groovy中添加以下内容
hibernate.current_session_context_class = 'thread'
我还尝试从服务而不是控制器调用线程,但也没有成功。我还打开了线程中的事务
我已经搜索了解决方案,但主要是配置问题。但由于我的项目在从控制器直接调用报表生成服务时正常工作,因此只有在创建新线程时才会出现问题。所以这似乎不是配置问题
我还添加了在新线程中创建新会话的代码,但这似乎不起作用
另外,问题只在于src/java类代码(我在上面添加了)。来自新线程的其他服务中的DB交互工作正常。该问题仅与getCurrentSession有关。openSession在grails的src.java类中工作得非常好。
请提出可能的问题。以下是我在异步处理线程池中根据Quartz插件的功能进行会话的步骤:
// Inject persistence interceptor
PersistenceContextInterceptor persistenceInterceptor
void myMethod() {
persistenceInterceptor.init()
// insert code here. Transactions are handled by service classes.
persistenceInterceptor.flush()
persistenceInterceptor.clear()
persistenceInterceptor.destroy()
}
我希望这能对您有所帮助。以下是我在异步处理线程池中根据Quartz插件的功能进行会话的步骤:
// Inject persistence interceptor
PersistenceContextInterceptor persistenceInterceptor
void myMethod() {
persistenceInterceptor.init()
// insert code here. Transactions are handled by service classes.
persistenceInterceptor.flush()
persistenceInterceptor.clear()
persistenceInterceptor.destroy()
}
我希望这对你有帮助
// Inject persistence interceptor
PersistenceContextInterceptor persistenceInterceptor
void myMethod() {
persistenceInterceptor.init()
// insert code here. Transactions are handled by service classes.
persistenceInterceptor.flush()
persistenceInterceptor.clear()
persistenceInterceptor.destroy()
}