gpt4 book ai didi

spring - @Transactional on Spring shutdown 正确关闭 Hsqldb

转载 作者:行者123 更新时间:2023-12-04 21:18:58 26 4
gpt4 key购买 nike

这个问题的核心是:是否可以从由 Spring 关闭 Hook 触发的方法执行事务?

目前,我有一个实现 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 中 Autowiring 到此类:
@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();
}

}

最佳答案

我找到了关闭 HsqlDB 数据库的解决方法,但它涉及避免使用 Spring 的 EntityManager 和 @Transactional,因为它们在服务器关闭期间显然不起作用。我修改后的 HsqlDBShutdownService 如下。关键的变化是,我没有使用 EntityManager 来调用查询,而是手动创建了一个新的 jdbc 连接,并以这种方式调用查询。这避免了对@Transactional 的要求:

@Service
public class HsqlDBShutdownService {

@Autowired
private ApplicationContext applicationContext;

@PersistenceContext
private EntityManager entityManager;

@Autowired
private HyperSqlDbServer hyperSqlDbServer;

public void executeShutdownQuery() {

Connection conn = null;
try {
JdbcTemplate jdbcTemplate = new JdbcTemplate(this.applicationContext.getBean(DataSource.class));
conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
conn.setAutoCommit(true);
jdbcTemplate.execute("SHUTDOWN");
} catch(Exception ex) {
ex.printStackTrace();
} finally {
try {
if(conn != null)
conn.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}

@Transactional
public void closeEntityManager() {
entityManager.close();
}

@PostConstruct
public void setHsqlDBShutdownService() {
hyperSqlDbServer.setShutdownService(this);
}

}

服务器现在可以成功重新启动,而不会留下 Hsqldb 锁定文件。

关于spring - @Transactional on Spring shutdown 正确关闭 Hsqldb,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16201704/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com