Сердце этого вопроса: возможно ли выполнить транзакцию с помощью метода, инициированного крюком отключения Spring?@Transactional при выключении пружины для правильного выключения Hsqldb
На данный момент у меня есть класс HyperSqlDbServer, который реализует SmartLifeCycle, как найти в этом вопросе: In a spring bean is it possible to have a shutdown method which can use transactions?
У меня есть метод в этом классе, который отмечен транзакционный, которая вызывается как часть методы остановки:
@Transactional
public void executeShutdown() {
hsqlDBShutdownService.executeShutdownQuery();
hsqlDBShutdownService.closeEntityManager();
}
служба, используемая в этом методе является немного рубить, что я должен был сделать, потому что я не мог autowire в EntityManager к этому классу:
@Service
public class HsqlDBShutdownService {
@PersistenceContext
private EntityManager entityManager;
@Autowired
private HyperSqlDbServer hyperSqlDbServer;
@Transactional
public void executeShutdownQuery() {
entityManager.createNativeQuery("SHUTDOWN").executeUpdate();
}
@Transactional
public void closeEntityManager() {
entityManager.close();
}
@PostConstruct
public void setHsqlDBShutdownService() {
hyperSqlDbServer.setShutdownService(this);
}
}
Вы можете заметить, что все, что я действительно пытаюсь выполнить, вызывает запрос «SHUTDOWN» перед остановкой сервера. Без этого файл блокировки hsqldb хранится при перезагрузке сервера, а сервер выдает исключение.
Код выше выдает следующее исключение:
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)
...
Так что мой первоначальный вопрос стоит, но если кто-нибудь есть мысли о том, как я мог бы выполнить этот запрос еще один способ, которым я постараюсь, что хорошо.
FYI, я также пробовал аннотацию @PreDestroy, но получаю такое же TransactionRequiredException.
Edit: Для полноты, я использую JpaTransactionManager и @Transactional аннотаций работать на протяжении всего моего проекта, за исключением остановки ...
Edit 2: Datasource и менеджер транзакций конфигурации:
@Configuration
@EnableTransactionManagement
@PropertySource("classpath:persistence.properties")
public class PersistenceConfig implements TransactionManagementConfigurer {
private static final String PASSWORD_PROPERTY = "dataSource.password";
private static final String USERNAME_PROPERTY = "dataSource.username";
private static final String URL_PROPERTY = "dataSource.url";
private static final String DRIVER_CLASS_NAME_PROPERTY = "dataSource.driverClassName";
@Autowired
private Environment env;
@Bean
@DependsOn("hsqlDb")
public DataSource configureDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty(DRIVER_CLASS_NAME_PROPERTY));
dataSource.setUrl(env.getProperty(URL_PROPERTY));
dataSource.setUsername(env.getProperty(USERNAME_PROPERTY));
dataSource.setPassword(env.getProperty(PASSWORD_PROPERTY));
return dataSource;
}
@Bean
@DependsOn("hsqlDb")
public LocalContainerEntityManagerFactoryBean configureEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(configureDataSource());
entityManagerFactoryBean.setPackagesToScan("com.mycompany.model.db");
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties jpaProperties = new Properties();
jpaProperties.put(org.hibernate.cfg.Environment.DIALECT, env.getProperty(org.hibernate.cfg.Environment.DIALECT));
jpaProperties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, env.getProperty(org.hibernate.cfg.Environment.HBM2DDL_AUTO));
jpaProperties.put(org.hibernate.cfg.Environment.SHOW_SQL, env.getProperty(org.hibernate.cfg.Environment.SHOW_SQL));
jpaProperties.put(org.hibernate.cfg.Environment.HBM2DDL_IMPORT_FILES_SQL_EXTRACTOR, env.getProperty(org.hibernate.cfg.Environment.HBM2DDL_IMPORT_FILES_SQL_EXTRACTOR));
jpaProperties.put(org.hibernate.cfg.Environment.HBM2DDL_IMPORT_FILES, env.getProperty(org.hibernate.cfg.Environment.HBM2DDL_IMPORT_FILES));
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
@Override
@Bean()
@DependsOn("hsqlDb")
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new JpaTransactionManager();
}
}
Попробуйте отладить эту строку и посмотрите на тип объекта вашего экземпляра 'HsqlDBShutdownService'. Он должен быть проксированным. Если это не так, ваш '@ Transactional' не работает. –
Отладка не показывает прокси-сервера на этом объекте. Поэтому я предполагаю, что в сочетании с оригинальным TransactionRequiredException подтверждается, что аннотация не работает. Так что просто невозможно выполнить транзакцию как часть метода остановки SmartLifecycle? – mag382
@ mag32 Вот и все. Если вы обновите свой вопрос с помощью конфигурации менеджера транзакций, мы можем поближе рассмотреть его. –