EntityManagerFactory.close() 不关闭由 hibernate.connection.datasource-属性 设置的 HikariDataSource
EntityManagerFactory.close() not closing HikariDataSource set by hibernate.connection.datasource-property
我正在使用 Hibernate 5.4.18 和 HikariCP 3.4.5。我的配置是程序化的,我使用 hibernate.connection.datasource
-属性 设置 Hibernate 的底层数据源。奇怪的是,当我随后调用 EntityManagerFactory.close()
-函数时,它不会调用 HikariDataSource 的 close()
-方法,连接将保持打开状态。这是期望的行为吗? Oracle 文档说 EntityManagerFactory.close()
将“关闭工厂,释放它持有的所有资源”。
Kotlin 的最小示例:
fun main() {
val emf = Persistence.createEntityManagerFactory("default", getJpaProperties())
// Fetch underlying HikariDataSource
val ds = emf.unwrap(SessionFactoryImpl::class.java)
.serviceRegistry
.getService<ConnectionProvider>(ConnectionProvider::class.java)
.unwrap(HikariDataSource::class.java)
emf.close()
println(ds.isClosed) // prints "false"
}
private fun getJpaProperties(): Map<String, Any> {
val dataSource = HikariDataSource().apply {
username = "sa"
password = ""
jdbcUrl = "jdbc:h2:mem:test_db"
}
return mapOf(
"hibernate.dialect" to "org.hibernate.dialect.H2Dialect",
"hibernate.connection.datasource" to dataSource
)
}
这是因为您提供了一个数据源实例。如果您初始化一个 DS,您很可能会在代码的其他部分使用它,因此关闭数据源会引入意外行为。这实际上是一个很好的做法,创建资源的“模块”也负责处理它。
如果您提供数据源的详细信息(用户名、密码、class 名称等),Hibernate 将关闭数据源,因为它将由 Hibernate 管理。
关于历史,在过去,DS 将由 J2EE 容器(例如 Tomcat)创建,然后在该容器内的许多应用程序之间共享。 属性 hibernate.connection.datasource
将是指向数据源的 JNDI 位置。
我正在使用 Hibernate 5.4.18 和 HikariCP 3.4.5。我的配置是程序化的,我使用 hibernate.connection.datasource
-属性 设置 Hibernate 的底层数据源。奇怪的是,当我随后调用 EntityManagerFactory.close()
-函数时,它不会调用 HikariDataSource 的 close()
-方法,连接将保持打开状态。这是期望的行为吗? Oracle 文档说 EntityManagerFactory.close()
将“关闭工厂,释放它持有的所有资源”。
Kotlin 的最小示例:
fun main() {
val emf = Persistence.createEntityManagerFactory("default", getJpaProperties())
// Fetch underlying HikariDataSource
val ds = emf.unwrap(SessionFactoryImpl::class.java)
.serviceRegistry
.getService<ConnectionProvider>(ConnectionProvider::class.java)
.unwrap(HikariDataSource::class.java)
emf.close()
println(ds.isClosed) // prints "false"
}
private fun getJpaProperties(): Map<String, Any> {
val dataSource = HikariDataSource().apply {
username = "sa"
password = ""
jdbcUrl = "jdbc:h2:mem:test_db"
}
return mapOf(
"hibernate.dialect" to "org.hibernate.dialect.H2Dialect",
"hibernate.connection.datasource" to dataSource
)
}
这是因为您提供了一个数据源实例。如果您初始化一个 DS,您很可能会在代码的其他部分使用它,因此关闭数据源会引入意外行为。这实际上是一个很好的做法,创建资源的“模块”也负责处理它。
如果您提供数据源的详细信息(用户名、密码、class 名称等),Hibernate 将关闭数据源,因为它将由 Hibernate 管理。
关于历史,在过去,DS 将由 J2EE 容器(例如 Tomcat)创建,然后在该容器内的许多应用程序之间共享。 属性 hibernate.connection.datasource
将是指向数据源的 JNDI 位置。