首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >永远使用Javers连接

永远使用Javers连接
EN

Stack Overflow用户
提问于 2016-02-01 16:07:54
回答 2查看 710关注 0票数 0

我有一个问题,数据库连接没有‘释放’由javers。

我们使用Hibernate 5.0.6,Hikari作为连接池,MSSQL作为我们的数据库。Javer配置如下(代码段):

代码语言:javascript
复制
JaversBuilder.javers().
    registerJaversRepository(SqlRepositoryBuilder.sqlRepository().
        withConnectionProvider(() -> ((SessionFactoryImpl) sessionFactory).getServiceRegistry().
            getService(org.hibernate.engine.jdbc.connections.spi.ConnectionProvider.class).getConnection()).
        withDialect(DialectName.MSSQL).
        build()).
    build();

以这种方式获取连接很好。如果没有可用的连接,则连接池将打开数据库连接。然而,javers获得的连接永远是'inUse‘。

代码语言:javascript
复制
61366 [Hikari Housekeeping Timer (pool HikariPool-0)] DEBUG HikariPool  - Before cleanup pool stats HikariPool-0 (total=100, inUse=100, avail=0, waiting=1)
61366 [Hikari Housekeeping Timer (pool HikariPool-0)] DEBUG HikariPool  - After cleanup pool stats HikariPool-0 (total=100, inUse=100, avail=0, waiting=1)
61366 [HikariCP connection filler (pool HikariPool-0)] DEBUG HikariPool  - After fill pool stats HikariPool-0 (total=100, inUse=100, avail=0, waiting=1)

我必须手动关闭连接吗?如果我尝试这样做(只需在1秒后关闭给Javer的每一个连接),连接池就会被清除。然而,这种办法不是一种选择。

我有什么好怀念的吗?如果我必须手动关闭连接,至少有可能收到Javer的通知,它不再需要连接了吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-03 09:49:16

好的,这是我的解决方案。收集Javer获得的所有连接并关闭它们( close ()不关闭,而是将它们释放到连接池!)在杰弗的工作完成后:

收集连接的类:

代码语言:javascript
复制
public class ConnectionCleanup {

    private static final Logger LOG = LoggerFactory.getLogger(ConnectionCleanup.class);
    private static final ThreadLocal<List<Connection>> connections = new ThreadLocal<>();

    public static void add(final Connection connection) {
        List<Connection> listConnections = connections.get();
        if (listConnections == null) {
            listConnections = new ArrayList<>();
            connections.set(listConnections);
        }
        listConnections.add(connection);
    }

    public static void cleanup() {
        final List<Connection> listConnections = connections.get();
        if (listConnections == null) {
            return;
        }
        for (final Connection con : listConnections) {
            try {
                if (!con.isClosed()) {
                    con.close();
                }
            } catch (final Exception ex) {
                LOG.error("Caught an", ex);
            }
        }
        connections.set(null);
    }
}

在Javer工作完成后包装SqlRepository以调用清理:

代码语言:javascript
复制
public class CleanupJaversSqlRepository implements JaversRepository {

    private final JaversSqlRepository repository;

    public CleanupJaversSqlRepository(final JaversSqlRepository repository) {
        this.repository = repository;
    }

    @Override
    public Optional<CdoSnapshot> getLatest(final GlobalId globalId) {
        final Optional<CdoSnapshot> latest = repository.getLatest(globalId);
        ConnectionCleanup.cleanup();
        return latest;
    }

    @Override
    public void persist(final Commit commit) {
        repository.persist(commit);
        ConnectionCleanup.cleanup();
    }

    @Override
    public CommitId getHeadId() {
        final CommitId commitId = repository.getHeadId();
        ConnectionCleanup.cleanup();
        return commitId;
    }

    @Override
    public void setJsonConverter(final JsonConverter jsonConverter) {
        repository.setJsonConverter(jsonConverter);
        ConnectionCleanup.cleanup();
    }

    @Override
    public void ensureSchema() {
        repository.ensureSchema();
        ConnectionCleanup.cleanup();
    }

    @Override
    public List<CdoSnapshot> getStateHistory(
            final GlobalId globalId,
            final QueryParams queryParams) {
        final List<CdoSnapshot> stateHistory = repository.getStateHistory(globalId, queryParams);
        ConnectionCleanup.cleanup();
        return stateHistory;
    }

    @Override
    public List<CdoSnapshot> getPropertyStateHistory(
            final GlobalId globalId,
            final String propertyName,
            final QueryParams queryParams) {
        final List<CdoSnapshot> stateHistory = repository.getPropertyStateHistory(
                globalId, propertyName, queryParams);
        ConnectionCleanup.cleanup();
        return stateHistory;
    }

    @Override
    public List<CdoSnapshot> getStateHistory(
            final ManagedType givenClass,
            final QueryParams queryParams) {
        final List<CdoSnapshot> stateHistory = repository.getStateHistory(givenClass, queryParams);
        ConnectionCleanup.cleanup();
        return stateHistory;
    }

    @Override
    public List<CdoSnapshot> getPropertyStateHistory(
            final ManagedType givenClass,
            final String propertyName,
            final QueryParams queryParams) {
        final List<CdoSnapshot> stateHistory = repository.getPropertyStateHistory(
                givenClass, propertyName, queryParams);
        ConnectionCleanup.cleanup();
        return stateHistory;
    }

    @Override
    public List<CdoSnapshot> getValueObjectStateHistory(
            final EntityType ownerEntity,
            final String path,
            final QueryParams queryParams) {
        final List<CdoSnapshot> stateHistory = repository.getValueObjectStateHistory(
                ownerEntity, path, queryParams);
        ConnectionCleanup.cleanup();
        return stateHistory;
    }
}

最后,把它们放在一起:

代码语言:javascript
复制
JaversBuilder.javers().
                registerJaversRepository(new CleanupJaversSqlRepository(SqlRepositoryBuilder.sqlRepository().
                        withConnectionProvider(() -> {
                            final Connection connection = ((SessionFactoryImpl) sessionFactory).
                                    getServiceRegistry().getService(
                                            org.hibernate.engine.jdbc.connections.spi.ConnectionProvider.class).
                                    getConnection();
                            ConnectionCleanup.add(connection);
                            return connection;
                        }).
                        withDialect(DialectName.MSSQL).
                        build())).
                build();
票数 0
EN

Stack Overflow用户

发布于 2016-02-02 07:57:17

您不应该关闭连接,实际上您也不应该为JaVers打开新的连接。

其主要思想是JaVers 重用应用程序打开和关闭的连接和事务。

示例场景:

  1. 应用程序从池中获取连接。
  2. 应用程序执行一些DML操作,例如插入新的Person#1
  3. JaVers借用app的连接并为Person#1插入审计记录
  4. 应用程序提交(或回滚)事务并返回到池的连接

如果您使用的是JPA,则可以使用与JpaHibernateConnectionProvider捆绑的JaVers:

代码语言:javascript
复制
package org.javers.spring.jpa;
... //

public class JpaHibernateConnectionProvider implements ConnectionProvider{

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Connection getConnection() {

        SessionImpl session =  (SessionImpl)entityManager.unwrap(Session.class);

        return session.connection();
    }
}

如果使用的是裸Hibernate,则可以编写类似的代码,从当前Hibernate会话(与当前线程绑定)中提取连接。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35135017

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档