在 Spring 计划任务使用的 Bean 上使用 DAO
我正在使用 Struts2 + Spring 开发一个 Web 应用程序,现在我正在尝试添加计划任务。我正在使用 Spring 的任务调度来做到这一点。在我的 applicationContext 中,我有:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
然后我有我的 DAO,它使用这个entityManagerFactory:
<bean id="dao" class="data.GenericDAO" />
所以这在 Web 应用程序中可以完美地工作。但现在我在创建计划任务时遇到了问题:
<task:scheduled-tasks scheduler="notifier">
<task:scheduled ref="emailService" method="sendMail" fixed-rate="30000" />
</task:scheduled-tasks>
<task:scheduler id="notifier" pool-size="10" />
<bean id="emailService" class="services.emailService" >
<property name="dao" ref="dao" />
</bean>
这会每 30 秒在我的 emailService 类上执行一次 sendMail 方法。我的 emailService 已正确注入 DAO。问题是,我可以使用 findById 命名查询通过 DAO 获取对象,但是当我尝试访问 Hibernate 映射的任何属性(例如相关集合或实体)时,我收到“LazyInitializationException:无法初始化代理 - 无会话” 。我不知道出了什么问题,因为我相信计划任务是由 Spring 管理的,所以使用 Spring 管理的 DAO 应该没有问题。我必须说我在 struts 操作上使用 openSessionInView 过滤器,所以也许我需要类似的东西来完成这个计划任务。
任何帮助或建议将不胜感激,谢谢!
编辑:最后我找到了解决这个问题的方法。我用一个我可以决定何时开始和提交事务的常规 Dao 进行了更改。因此,在做任何事情之前,我都会启动一个事务,然后一切正常。所以我仍然不知道到底是什么原因导致了这个问题,以及是否有一天我能够使用我的常规 DAO,目前我仍然使用这个解决方案。
I'm developing a web application using Struts2 + Spring, and now I'm trying to add a scheduled task. I'm using Spring's task scheduling to do so. In my applicationContext I have:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
And then I have my DAO that uses this entityManagerFactory:
<bean id="dao" class="data.GenericDAO" />
So this works flawlessly within the web application. But now I have a problem when creating the scheduled task:
<task:scheduled-tasks scheduler="notifier">
<task:scheduled ref="emailService" method="sendMail" fixed-rate="30000" />
</task:scheduled-tasks>
<task:scheduler id="notifier" pool-size="10" />
<bean id="emailService" class="services.emailService" >
<property name="dao" ref="dao" />
</bean>
This executes the method sendMail on my emailService class every 30 seconds. And my emailService has the DAO injected correctly. The thing is that I can fetch objects with my DAO using the findById named queries, but when I try to access any property mapped by Hibernate, such as related collections or entities, I get an "LazyInitializationException: could not initialize proxy - no Session ". I don't know what's wrong, since I believe the scheduled task is being managed by Spring, so it should have no problem using a Spring managed DAO. I must say that I'm using the openSessionInView filter on my struts actions, so maybe I need something similar for this scheduled task.
Any help or suggestion will be appreciated, thanks!
Edit: Finally I found a way to fix this. I changed my regular Dao with one where I can decide when to start and commit the transaction. So before doing anything I start a transaction and then everything works OK. So I still don't know exactly what causes the problem and if someday I'll be able to use my regular DAO, for the moment I'm staying with this solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
OpenSessionInView 不会帮助你,因为你没有网络上下文。你需要 Spring 的 声明式事务管理。
在大多数情况下,您需要做的只是这个 XML:(
将您的
EmailService
类注释为@Transactional
以启用此功能)OpenSessionInView won't help you, because you don't have a web context. You need Spring's Declarative Transaction Management.
In most cases, what you need to do is just this XML:
(Annotate your
EmailService
class as@Transactional
to enable this)