我有一个问题,数据库连接没有‘释放’由javers。
我们使用Hibernate 5.0.6,Hikari作为连接池,MSSQL作为我们的数据库。Javer配置如下(代码段):
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‘。
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的通知,它不再需要连接了吗?
发布于 2016-02-03 09:49:16
好的,这是我的解决方案。收集Javer获得的所有连接并关闭它们( close ()不关闭,而是将它们释放到连接池!)在杰弗的工作完成后:
收集连接的类:
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以调用清理:
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;
}
}最后,把它们放在一起:
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();发布于 2016-02-02 07:57:17
您不应该关闭连接,实际上您也不应该为JaVers打开新的连接。
其主要思想是JaVers 重用应用程序打开和关闭的连接和事务。
示例场景:
如果您使用的是JPA,则可以使用与JpaHibernateConnectionProvider捆绑的JaVers:
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会话(与当前线程绑定)中提取连接。
https://stackoverflow.com/questions/35135017
复制相似问题