【问题标题】:How to vacuum database tables in a Spring Boot application?如何在 Spring Boot 应用程序中清理数据库表?
【发布时间】: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


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 2019-06-16
    • 2016-04-26
    相关资源
    最近更新 更多