Kir*_*kov 19 hibernate spring-boot hikaricp
我有一个带有 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.
Run Code Online (Sandbox Code Playgroud)
似乎手动使用会话会导致此问题。(我有类似的项目,具有相同的配置和功能,但没有注入 SessionFactory 和 Session ......我根本没有这样的问题)
应用程序.yaml :
spring:
jpa:
properties:
hibernate:
dialect : org.hibernate.dialect.PostgreSQLDialect
current_session_context_class: org.springframework.orm.hibernate5.SpringSessionContext
Run Code Online (Sandbox Code Playgroud)
数据源配置
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
dataSource.setMaximumPoolSize(30), dataSource.setMinimumIdle(); 没有解决这个问题
小智 16
我们最近遇到了这个问题,但连接池错误消息最终只是诱饵。
真正的问题是第三方系统不接受更多消息,从而阻塞了每个线程。如果线程之前从 HikariCP 获取了连接,则连接永远不会返回到池中。因此,我们拥有与池连接一样多的成功连接。
在这种情况下:使用所选工具(任何 APM、VisualVM 或类似工具)检查 JVM 上阻塞线程的数量,并使用线程转储检查阻塞线程在何处停止。
在我看来,这像是事务边界的问题,它不会将连接释放回池中。你能试着@Transactional上你的LogRepositoryImpl课吗?
@Repository
@Transactional
public class LogRepositoryImpl implements LogRepository {
. . .
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
81899 次 |
| 最近记录: |