我有一个使用Hibernate和Hikari DataSource的Spring Boot项目。如果我有一些功能需要注入SessionFactory对象来获取会话对象,在几天内,所有与数据库操作相关的方法都会出现异常(只有重新启动才能解决此问题):
org.springframework.transaction.CannotCreateTransactionException:
Could not open JPA EntityManager for transaction; nested exception is
javax.persistence.PersistenceException:
org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection at
......
Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 -
Connection is not available, request timed out after 30001ms.
看起来是手动使用session引起了这个问题。(我有一个类似的项目,具有相同的配置和功能,但没有注入SessionFactory和Session...而且我根本就没有这样的问题)
application.yaml:
spring:
jpa:
properties:
hibernate:
dialect : org.hibernate.dialect.PostgreSQLDialect
current_session_context_class: org.springframework.orm.hibernate5.SpringSessionContext
DataSourceConfig
的翻译是:数据源配置
@EnableJpaRepositories("com.my.project.config")
@Configuration
public class DataSourceConfig {
@Inject
private AppProperties properties;
@Bean(name = "dataSource")
public DataSource dataSource() {
AppProperties.DatabaseProperties dbProps = properties.getDatabaseProperties();
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(org.postgresql.Driver.class.getName());
dataSource.setJdbcUrl(
dbProps.getProtocol().concat("://")
.concat(dbProps.getDbHost()).concat(":")
.concat(dbProps.getDbPort()).concat("/")
.concat(dbProps.getDbname())
);
dataSource.setUsername(dbProps.getUsername());
dataSource.setPassword(dbProps.getPassword());
dataSource.setMaximumPoolSize(30);
dataSource.setMinimumIdle(30);
return dataSource;
}
@Bean
public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf) {
return hemf.getSessionFactory();
}
}
LogRepositoryImpl
的翻译是日志仓库实现
@Repository
public class LogRepositoryImpl implements LogRepository {
@Autowired
private SessionFactory sessionFactory;
@Override
public List<Log> getLogs(int offset, int count) {
Criteria criteria = getSession().createCriteria(Log.class);
return criteria.setFirstResult(offset).setMaxResults(count).list();
}
@Override
public void save(Log log) {
getSession().save(log);
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
}
dataSource.setMaximumPoolSize(30),dataSource.setMinimumIdle()并没有解决这个问题。