我目前的尝试(根据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()
}
正确的方法是什么?
答案 0 :(得分:4)
您只需要注入DataSource
,断开连接,执行您的工作,然后关闭连接。
@Service
class VacuumDatabaseService(
private val dataSource: DataSource
) {
fun vacuumAllTables() {
dataSource.connection.use {
it.prepareStatement("VACUUM FULL").execute()
}
}
}
请注意use
的用法,一旦执行该块,它将关闭连接。