#hibernate #spring #aop
#спящий режим #spring #aop
Вопрос:
Я совсем новичок в AOP-Spring. Я застрял с проблемой транзакции (тестирование отката с помощью AOP). Я предполагаю, что я могу делать что-то в основном неправильно. или есть конфликт с существующими конфигурациями.
Мой конфигурационный файл Spring
<beans...>
<!-- This TX is I am interested in -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="mySqlDataSource"/>
</bean>
<bean id="registriesTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="registriesDataSource"/>
</bean> <!-- There are 2 datasorce for AS400 and a transaction for one of them-->
<aop:config>
<aop:advisor pointcut="execution(* se.unox.pejl.service.PejlAnalysisService.* (..))" advice-ref="txMySqlAdvice"/>
<! --- many more -->
</aop:config>
<tx:advice id="txMySqlAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="*" />
<tx:method name="cleanPejlValues" propagation="REQUIRED" rollback-for="Throwable"/>
</tx:attributes>
</tx:advice>
</beans>
Моя реализация сервиса
public class PejlAnalysisServiceImpl implements PejlAnalysisService, InitializingBean {
@Override
public void cleanPejlValues() {
List<String> idsToDelete= pejlDataDao.getPejlIds(Calendar.getInstance().getTime(), pejlType);
logger.debug("TRYING TO DELETE these IDS: " idsToDelete);
numDeletedValues = cisternDao.deleteCistern(idsToDelete);
logger.debug("DELETED " numDeletedValues);
numDeletedValues = pejlDataDao.deletePejlValues(idsToDelete);
}
}
Мой DAO, из которого я выбрасываю исключение
public class PejlDataDaoMySqlImpl extends GenericDaoImpl<PejlDataInValue,String> implements PejlDataDao {
@Override
public int deletePejlValues(List<String> pejlIds) {
throw new RuntimeException("THROW INTENTIONALLY");
}
}
Я хочу, чтобы удаленные строки CisternDao (таблица tbl_cistern) были откатаны после того, как я (намеренно) создаю исключение из другого Dao, которое предполагает удаление данных из родительской таблицы.
Однако мой откат не работает. Данные таблицы tbl_cistern по-прежнему отсутствуют.
Что я делаю не так? (Я использую Spring 3.1, Spring AOP -3.1, Hibernate 3.6, Tomcat6)
===============================================================================
Редактировать.
Вот мой AOP StackTrace. Он говорит откат, но мои строки из первой таблицы все еще отсутствуют. Это существующее приложение. Интересно, мешает ли DomainServiceImpl TX.
2011-10-12 11:46:27,726 DEBUG - Creating new transaction with name [se.unox.pejl.service.impl.PejlAnalysisServiceImpl.cleanPejlValues]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-Throwable
2011-10-12 11:46:27,726 DEBUG - Creating new transaction with name [se.unox.pejl.service.impl.PejlAnalysisServiceImpl.cleanPejlValues]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-Throwable
2011-10-12 11:46:27,726 DEBUG - Acquired Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver] for JDBC transaction
2011-10-12 11:46:27,726 DEBUG - Acquired Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver] for JDBC transaction
2011-10-12 11:46:27,727 DEBUG - Switching JDBC Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver] to manual commit
2011-10-12 11:46:27,727 DEBUG - Switching JDBC Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver] to manual commit
2011-10-12 11:46:27,727 DEBUG - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] to thread [http-8080-1]
2011-10-12 11:46:27,727 DEBUG - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] to thread [http-8080-1]
2011-10-12 11:46:27,727 DEBUG - Initializing transaction synchronization
2011-10-12 11:46:27,727 DEBUG - Initializing transaction synchronization
2011-10-12 11:46:27,728 DEBUG - Getting transaction for [se.unox.pejl.service.impl.PejlAnalysisServiceImpl.cleanPejlValues]
2011-10-12 11:46:27,728 DEBUG - Getting transaction for [se.unox.pejl.service.impl.PejlAnalysisServiceImpl.cleanPejlValues]
2011-10-12 11:46:27,729 DEBUG - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] bound to thread [http-8080-1]
2011-10-12 11:46:27,729 DEBUG - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] bound to thread [http-8080-1]
2011-10-12 11:46:27,729 DEBUG - Participating in existing transaction
2011-10-12 11:46:27,729 DEBUG - Participating in existing transaction
2011-10-12 11:46:27,729 DEBUG - Getting transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,729 DEBUG - Getting transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,730 DEBUG - Bound value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] to thread [http-8080-1]
2011-10-12 11:46:27,730 DEBUG - Bound value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] to thread [http-8080-1]
2011-10-12 11:46:27,730 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,730 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,734 DEBUG - Completing transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,734 DEBUG - Completing transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,734 DEBUG - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] bound to thread [http-8080-1]
2011-10-12 11:46:27,734 DEBUG - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] bound to thread [http-8080-1]
2011-10-12 11:46:27,734 DEBUG - Participating in existing transaction
2011-10-12 11:46:27,734 DEBUG - Participating in existing transaction
2011-10-12 11:46:27,734 DEBUG - Getting transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,734 DEBUG - Getting transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,735 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,735 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,735 DEBUG - Completing transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,735 DEBUG - Completing transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,735 DEBUG - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] bound to thread [http-8080-1]
2011-10-12 11:46:27,735 DEBUG - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] bound to thread [http-8080-1]
2011-10-12 11:46:27,735 DEBUG - Participating in existing transaction
2011-10-12 11:46:27,735 DEBUG - Participating in existing transaction
2011-10-12 11:46:27,735 DEBUG - Getting transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,735 DEBUG - Getting transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,735 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,735 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,737 DEBUG - Completing transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,737 DEBUG - Completing transaction for [se.unox.pejl.service.impl.DomainServiceImpl.getDomainData]
2011-10-12 11:46:27,737 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,737 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,789 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:27,789 DEBUG - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] bound to thread [http-8080-1]
2011-10-12 11:46:28,396 DEBUG - Completing transaction for [se.unox.pejl.service.impl.PejlAnalysisServiceImpl.cleanPejlValues] after exception: java.lang.RuntimeException: THROWN INTENTIONALLY
2011-10-12 11:46:28,396 DEBUG - Completing transaction for [se.unox.pejl.service.impl.PejlAnalysisServiceImpl.cleanPejlValues] after exception: java.lang.RuntimeException: THROWN INTENTIONALLY
2011-10-12 11:46:28,396 DEBUG - Applying rules to determine whether transaction should rollback on java.lang.RuntimeException: THROWN INTENTIONALLY
2011-10-12 11:46:28,396 DEBUG - Applying rules to determine whether transaction should rollback on java.lang.RuntimeException: THROWN INTENTIONALLY
2011-10-12 11:46:28,396 DEBUG - Winning rollback rule is: RollbackRuleAttribute with pattern [Throwable]
2011-10-12 11:46:28,396 DEBUG - Winning rollback rule is: RollbackRuleAttribute with pattern [Throwable]
2011-10-12 11:46:28,396 DEBUG - Triggering beforeCompletion synchronization
2011-10-12 11:46:28,396 DEBUG - Triggering beforeCompletion synchronization
2011-10-12 11:46:28,397 DEBUG - Removed value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] from thread [http-8080-1]
2011-10-12 11:46:28,397 DEBUG - Removed value [org.springframework.orm.hibernate3.SessionHolder@160088f] for key [org.hibernate.impl.SessionFactoryImpl@1a0280d] from thread [http-8080-1]
2011-10-12 11:46:28,397 DEBUG - Initiating transaction rollback
2011-10-12 11:46:28,397 DEBUG - Initiating transaction rollback
2011-10-12 11:46:28,397 DEBUG - Rolling back JDBC transaction on Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver]
2011-10-12 11:46:28,397 DEBUG - Rolling back JDBC transaction on Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver]
2011-10-12 11:46:28,398 DEBUG - Triggering afterCompletion synchronization
2011-10-12 11:46:28,398 DEBUG - Triggering afterCompletion synchronization
2011-10-12 11:46:28,398 DEBUG - Clearing transaction synchronization
2011-10-12 11:46:28,398 DEBUG - Clearing transaction synchronization
2011-10-12 11:46:28,398 DEBUG - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] from thread [http-8080-1]
2011-10-12 11:46:28,398 DEBUG - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@6113e0] for key [org.apache.commons.dbcp.BasicDataSource@ee003d] from thread [http-8080-1]
2011-10-12 11:46:28,399 DEBUG - Releasing JDBC Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver] after transaction
2011-10-12 11:46:28,399 DEBUG - Releasing JDBC Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver] after transaction
2011-10-12 11:46:28,399 DEBUG - Returning JDBC Connection to DataSource
2011-10-12 11:46:28,399 DEBUG - Returning JDBC Connection to DataSource
2011-10-12 11:30:36,577 DEBUG - Releasing JDBC Connection [jdbc:mysql://localhost:3306/pejldatastorenorway?autoReconnect=true, UserName=dbpejl@localhost, MySQL-AB JDBC Driver] after transaction
Ответ №1:
Попробуйте изменить выражения AOP, чтобы также включить интерфейсы служб (если они не охвачены). У меня были проблемы, когда мои интерфейсы служб находились в пакете, отличном от реализаций служб, и если они не охватываются выражением AOP, транзакции не запускаются / не фиксируются / не выполняются.
Кроме того, если это веб-приложение, рассмотрите возможность отказа от AOP в пользу Spring OpenSessionInViewFilter, который открывает сеанс при поступлении запроса и фиксирует / откатывает его после возврата / возврата.
Наконец, я использую IntelliJ IDE, которая имеет отличную поддержку Spring — вы можете щелкнуть объявление AOP в XML-файле и увидеть всплывающий список всех методов, соответствующих шаблону, — действительно помогает при отладке AOP.
Комментарии:
1. Я думаю, что вы здесь на правильном пути. Попробуйте отладить свой код и посмотреть, действительно ли совет вызывается, когда он должен быть первым, и только после этого иметь дело с фактической бизнес-логикой внутри него. Кроме того, я всегда находил намного понятнее и понятнее определять мои точки аспекта как определенную аннотацию, а затем помещать эту аннотацию поверх желаемых методов.
2. Спасибо за одиночный снимок указателя. Я отлаживаю, но все еще в замешательстве. См. Редактирование выше.
3. Я проголосовал за полезное, спасибо за новые идеи. 🙂 Но об изменениях (удаление AOP или использование IntelliJ) я могу изменять только столько, сколько приложение уже используется годами. Зависит от того, как долго я буду работать над этим проектом. И да. Я изменю его на аннотацию (@Transactional) вместо существующей конфигурации XML.
Ответ №2:
Я думаю, вам нужно добавить <aop:aspectj-autoproxy/>
в свой контекст. Это инструкция по применению аспектов к вашим компонентам. aop:config
и tx:advice
просто настройте аспект, который, я думаю, не применяется.
Вы также можете проверить, являются ли ваши классы аспектированными, и транзакции запускаются / откатываются, включив ведение журнала информации для spring.
В качестве дополнительного примечания, если вы используете java 1.5 или более позднюю версию, намного лучше / проще использовать аннотации (@Transactional) вместо конфигурации на основе XML.
Комментарии:
1. извините <aop:aspectj-autoproxy/> не помогло. 🙁
2. Я избавился от конфигурации на основе XML и теперь использую @Trasactional. проблема по-прежнему сохраняется. В журналах говорится, что он откатывается (что-то), но данные в базе данных MySQL исчезли.
3. Что такое механизм хранения — если это MyISAM, я думаю, он не поддерживает транзакции. Вам нужно перейти на InnoDB.
4. Его InnoDB. У меня был hibernate.dialect=org.hibernate.dialect. MySQLDialect в моей конфигурации. Уже пробовал изменить его на hibernate.dialect=org.hibernate.dialect. MySQLInnoDBDialect также пытался Проблема решается путем изменения транзакции на HibernateTransactionManager.
5. не диалект — механизм хранения, связанный с таблицей в базе данных. Вы можете найти информацию о том, как проверить и изменить — electrictoolbox.com/mysql-table-storage-engine
Ответ №3:
Понял. Или я должен сказать, что проблема решена, не совсем понятно, почему.
Изменен мой класс компонента транзакции из org.springframework.jdbc.datasource.DataSourceTransactionManager
Для
org.springframework.orm.hibernate3.HibernateTransactionManager
И его работа.
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> -->
<property name="sessionFactory" ref="mySqlSessionFactory"></property>
<!-- <property name="dataSource" ref="mySqlDataSource"/> -->
</bean>
Сейчас слишком оцепенел, иду домой. Кто-нибудь может пролить свет на то, почему это так?
Комментарии:
1. Если вы выполняете удаление через спящий режим, я думаю, что проблема не решена. Спящий режим не отправляет инструкции delete в базу данных, поэтому переход на HibernateTransactionManager (что правильно) может маскировать исходную проблему. Вы можете проверить это, вызвав session . flush() перед выдачей исключения. Я все еще думаю, что проблема связана с механизмом хранения mysql.
2. Не могли бы вы указать, почему использование HibernateTransactionManager лучше? Спасибо.
3. static.springsource.org/spring/docs/2.0.x/reference /… имеет некоторую информацию. По сути, вы хотите, чтобы для всей транзакции был создан один сеанс гибернации вместо одного для каждого вызова dao. HibernateTransactionManager обеспечит это.
4. ВЫБЕРИТЕ ИМЯ_ТАБЛИЦЫ, ДВИЖОК ИЗ information_schema. ТАБЛИЦЫ, В КОТОРЫХ TABLE_SCHEMA = ‘pejldatastorenorway’ возвращал «InnoDB».
5. Еще одна вещь — как hibernate sessionfactory получает источник данных, вводится ли он через spring или напрямую настраивается в hibernate.cfg.xml . Это одна из причин, по которой он не будет работать с DataSourceTransactionManager, но будет работать после изменения на HibernateTransactionManager.