使用 JPA 执行 VACUUM FULL

问题描述 投票:0回答:3

我正在使用 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“无结果”

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

java postgresql jpa vacuum
3个回答
5
投票

正如 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();
}

2
投票

这是一个不需要转换为 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);
  }
});

0
投票

我正在根据其他答案分享两个版本的工作示例。

    static int vacuum1(final EntityManager em) throws SQLException {
        final var session = em.unwrap(Session.class);
        assert session instanceof JdbcSessionOwner;
        final var access = ((JdbcSessionOwner) session).getJdbcConnectionAccess();
        final var connection = access.obtainConnection();
        try (var statement = connection.prepareStatement("VACUUM")) {
            return statement.executeUpdate();
        }
    }

    static void vacuum2(final EntityManager em) {
        final var session = em.unwrap(Session.class);
        session.doWork(c -> {
            assert session instanceof JdbcSessionOwner;
            try (var statement = c.prepareStatement("VACUUM")) {
                try {
                    final var result = statement.executeUpdate();
                    assert result == 0;
                } catch (final SQLException sqle) {
                    throw new RuntimeException(sqle);
                }
            }
        });
    }
© www.soinside.com 2019 - 2024. All rights reserved.