Использование DAO в компоненте, используемом запланированной задачей Spring

Я разрабатываю веб-приложение, используя Struts2 + Spring, и теперь пытаюсь добавить запланированную задачу. Для этого я использую планирование задач 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" />

Так что это работает безупречно в веб-приложении. Но теперь у меня проблема при создании запланированного задания:

<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>

Это выполняет метод sendMail в моем классе emailService каждые 30 секунд. И мой emailService правильно ввел DAO. Дело в том, что я могу извлекать объекты с помощью своего DAO, используя именованные запросы findById, но когда я пытаюсь получить доступ к любому свойству, отображаемому Hibernate, например, к связанным коллекциям или объектам, я получаю «LazyInitializationException: не удалось инициализировать прокси — нет сеанса». . Я не знаю, что не так, так как я считаю, что запланированная задача управляется Spring, поэтому у нее не должно возникнуть проблем с использованием DAO, управляемого Spring. Я должен сказать, что использую фильтр openSessionInView в своих действиях Strut, поэтому, возможно, мне нужно что-то подобное для этой запланированной задачи.

Любая помощь или предложение будут оценены, спасибо!

Изменить. Наконец-то я нашел способ это исправить. Я изменил свой обычный дао на тот, в котором я могу решить, когда начать и зафиксировать транзакцию. Поэтому, прежде чем что-либо делать, я запускаю транзакцию, и тогда все работает нормально. Поэтому я до сих пор точно не знаю, в чем причина проблемы, и если когда-нибудь я смогу использовать свой обычный DAO, на данный момент я остаюсь с этим решением.


person 1000i1    schedule 21.03.2011    source источник


Ответы (1)


OpenSessionInView вам не поможет, потому что у вас нет веб-контекста. Вам нужна декларативная транзакция Spring Управление.

В большинстве случаев вам нужно сделать только этот XML:

<!-- JPA, not hibernate -->
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>      

<tx:annotation-driven transaction-manager="myTxManager" />

<!-- without backing interfaces you probably also need this: -->
<aop:config proxy-target-class="true">

(Аннотируйте свой класс EmailService как @Transactional, чтобы включить это)

person Sean Patrick Floyd    schedule 21.03.2011
comment
Я аннотировал свою электронную почту как @Transactional (что вынудило меня включить CGlib), но ошибка все еще сохраняется. Я продолжаю получать: LazyInitializationException: не удалось инициализировать прокси - нет сеанса - person 1000i1; 21.03.2011
comment
@1000i1 вам не нужен CGLib, если у вас есть резервный интерфейс, см. Механизмы проксирования - person Sean Patrick Floyd; 21.03.2011
comment
В целях тестирования я не возражаю против использования cglib, сейчас я сосредоточен на исправлении LazyInitializationException. Если я смогу избавиться от этого, я посмотрю на эти механизмы проксирования. Спасибо за ваши ответы! - person 1000i1; 21.03.2011
comment
@ 1000i1 Думаю, вам также нужен proxy-target-class=true (см. мое обновление) - person Sean Patrick Floyd; 21.03.2011
comment
@ 1000i1 О, я только что понял, что вы используете JPA, тогда вам понадобится другой менеджер транзакций. Отредактировал мой ответ соответственно. - person Sean Patrick Floyd; 21.03.2011