這個問題的核心是:是否有可能從Spring關機掛鉤觸發的方法執行交易?@Transactional在春季關機正常關機Hsqldb
目前我在這個問題發現,實現SmartLifeCycle一個HyperSqlDbServer類: In a spring bean is it possible to have a shutdown method which can use transactions?
我有一個標記事務那類被調用作爲停止方法的一部分的方法:
@Transactional
public void executeShutdown() {
hsqlDBShutdownService.executeShutdownQuery();
hsqlDBShutdownService.closeEntityManager();
}
在該方法中使用的服務是一個黑客一點,我不得不這樣做,因爲我不能在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)
...
所以我原來的問題表示,但如果有人對我怎麼能執行這個查詢另一種方式一個想法,我會嘗試爲好。
僅供參考,我也試過@PreDestroy註釋,但得到相同的TransactionRequiredException。
編輯:爲了完整起見,我使用的是JpaTransactionManager接口和整個我的項目@Transactional註釋工作,除了在關機...
編輯2:數據源和事務管理器配置:
@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'不起作用。 – 2013-04-24 23:40:09
調試顯示該對象上沒有代理服務器。所以我想,結合原始TransactionRequiredException確認註釋不起作用。那麼,作爲智能生命週期停止方法的一部分,執行交易是不可能的? – mag382 2013-04-25 13:59:04
@ mag32就是這樣。如果您使用交易管理器配置更新您的問題,我們可以仔細查看。 – 2013-04-25 13:59:51