使用JPA执行VACUUM FULL

5
我使用PostgreSQL数据库,想要使用JPA EntityManager来启动VACUUM FULL。
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 "没有结果"。

正确的启动这个SQL命令的方式是什么?


这真的是应该在JPA范围内完成的事情吗?我的意思不是说这是坏事,但这不是一些DBA的事情吗?你是想使用JPA开发DBA工具吗?但仍然是一个有趣的方面。 - pirho
1
获取底层连接并回退到原始的JDBC?请参阅此处以获取连接的机制:https://dev59.com/BXA75IYBdhLWcg3wDUq2 - Alan Hay
2个回答

4
正如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”就足以让它被注入。 - Marcel

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);
  }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接