【问题标题】:Perform VACUUM FULL with JPA使用 JPA 执行 VACUUM FULL
【发布时间】:2018-04-09 12:03:23
【问题描述】:

我正在使用 PostgreSQL 数据库,我想使用 JPA EntityManager 启动 VACUUM FULL

版本 1

public void doVacuum(){
  entityManager.createNativeQuery("VACUUM FULL").executeUpdate()
}

抛出 TransactionRequiredException

第 2 版

@Transactional
public void doVacuum(){
  entityManager.createNativeQuery("VACUUM FULL").executeUpdate()
}

抛出 PersistenceException "VACUUM 不能在事务块内运行"

第 3 版

public void doVacuum(){
  entityManager.createNativeQuery("VACUUM FULL").getResultList()
}

执行真空,但之后我得到 PersistenceException "No results"

启动这条sql命令的正确方法是什么?

【问题讨论】:

  • 这真的应该在 JPA 范围内完成吗?我并不是说这是坏事,但这不是 DBA 的事吗?您是否正在尝试使用 JPA 开发 DBA 工具?但仍然很有趣。
  • 获取底层连接并回退到原始 JDBC?有关获取连接的机制,请参见此处:stackoverflow.com/questions/3493495/…

标签: java postgresql jpa vacuum


【解决方案1】:

这是一个不需要强制转换为 Hibernate Session 的内部实现的解决方案。请记住,VACUUM 不能在事务块中运行,这就是为什么您需要将autoCommit 设置为true

Session session = entityManager.unwrap(Session.class);
session.doWork(new Work() {
  @Override
  public void execute(Connection connection) throws SQLException {
    connection.setAutoCommit(true);
    connection.prepareStatement("VACUUM FULL").execute();
    connection.setAutoCommit(false);
  }
});

【讨论】:

    【解决方案2】:

    正如 Alay Hay 所说,使用底层连接将起作用:

    public void doVacuum(){
      org.hibernate.Session session = entityManager.unwrap(org.hibernate.Session);
      org.hibernate.internal.SessionImpl sessionImpl = (SessionImpl) session;  // required because Session doesn't provide connection()
      java.sql.Connection connection = sessionImpl.connection();
      connection.prepareStatement("VACUUM FULL").execute();
    }
    

    【讨论】:

    • 这取决于您处理数据库连接的方式或您使用的框架。我目前正在使用 Spring,所以一个带注释的字段“@PersistenceContext private EntityManager enitityManger”足以让它注入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多