【发布时间】:2019-08-28 15:05:15
【问题描述】:
我当前的尝试(根据this answer)如下所示:
@Service
class VacuumDatabaseService(
private val entityManager: EntityManager
) {
fun vacuumAllTables() {
val session = entityManager.unwrap(org.hibernate.Session::class.java)
val sessionImpl = session as org.hibernate.internal.SessionImpl
val connection = sessionImpl.connection()
connection.prepareStatement("VACUUM FULL").execute()
}
}
但它会抛出:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No transactional EntityManager available
使用@Transactional 注释函数会导致:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException
Caused by: org.postgresql.util.PSQLException: ERROR: VACUUM cannot run inside a transaction block
以下方法有效,但感觉非常错误:
@Transactional
fun vacuumAllTables() {
val session = entityManager.unwrap(org.hibernate.Session::class.java)
val sessionImpl = session as org.hibernate.internal.SessionImpl
val connection = sessionImpl.connection()
connection.prepareStatement("END TRANSACTION; VACUUM FULL;").execute()
}
正确的方法是什么?
【问题讨论】:
-
为什么要通过 EntityManager 和 Hibernate Session 来获得 JDBC 连接?为什么不简单地注入 Jdbc 数据源,从中获取连接,完成工作并关闭它?
-
@JBNizet 因为我不知道这是可能的。 :D 非常感谢您的评论。以下工作正常:
class VacuumDatabaseService(private val dataSource: DataSource) { fun vacuumAllTables() { dataSource.connection.prepareStatement("VACUUM FULL;").execute() } } -
您愿意将此解决方案作为答案发布,以便我接受吗?
-
你真的需要关闭连接:
dataSource.connection.use { it.prepareStatement()... }
标签: postgresql hibernate spring-boot kotlin vacuum