如何清理 Spring 引导应用程序中的数据库表?

How to vacuum database tables in a Spring Boot application?

我目前的尝试(根据 )如下所示:

@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()
    }

正确的方法是什么?

您只需注入 DataSource,从中获取连接,执行作业,然后关闭连接。

@Service
class VacuumDatabaseService(
        private val dataSource: DataSource
) {

    fun vacuumAllTables() {
        dataSource.connection.use {
            it.prepareStatement("VACUUM FULL").execute()
        }
    }
}

注意 use 的用法,它会在块执行后关闭连接。