在explisit销毁服务注册表之后,Hibernate保持连接

时间:2017-12-13 14:19:17

标签: java hibernate database-connection connection-pooling

我的目标是在构建期间生成DDL。我exec-maven-plugingoal一起执行以下main方法:

public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
        SessionFactoryImpl sessionFactory = null;
        try {
            Persistence.generateSchema(PERSISTENCE_UNIT, null);
        } finally {
            sessionFactory = emf.unwrap(SessionFactoryImpl.class);
            sessionFactory.getServiceRegistry().destroy();
        }
}

我的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="ddl-gen">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <class>***</class>
        <class>***</class>
        <class>***</class>

        <properties>


            <property name="javax.persistence.schema-generation.scripts.action" value="create"/>
            <property name="javax.persistence.schema-generation.scripts.create-target"
                      value="${project.basedir}/src/main/resources/META-INF/sql/init.sql"/>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://***/~/***"/>
            <property name="hibernate.connection.username" value="sa"/>
            <property name="hibernate.connection.password" value=""/>



        </properties>

    </persistence-unit>

</persistence>

但问题是Hibernate即使我明确地这样做也不会杀死数据库连接。执行没有完成,过程是无止境的

日志:

16:11:41.062 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Not binding SessionFactory to JNDI, no JNDI name configured
16:11:41.062 [main] DEBUG org.hibernate.jpa.internal.schemagen.JpaSchemaGenerator - wasInitiallyAutoCommit=false
16:11:41.062 [main] INFO org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
16:11:41.066 [main] DEBUG org.hibernate.service.internal.AbstractServiceRegistryImpl - Implicitly destroying ServiceRegistry on de-registration of all child ServiceRegistries
16:11:41.066 [main] INFO org.hibernate.orm.connections - HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://***/~/***]
16:11:41.067 [main] DEBUG org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl - Implicitly destroying Boot-strap registry on de-registration of all child ServiceRegistries
16:12:10.932 [pool-2-thread-1] DEBUG org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl - Connection pool now considered primed; min-size will be maintained

有趣的是我有[pool-2-thread-1]这意味着Hibernate会创建新池。因为没有explisit kill我有这个日志:

public static void main(String[] args) {
    Persistence.generateSchema(PERSISTENCE_UNIT, null);
}

16:07:26.890 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Not binding SessionFactory to JNDI, no JNDI name configured
16:07:26.895 [main] DEBUG org.hibernate.jpa.internal.schemagen.JpaSchemaGenerator - wasInitiallyAutoCommit=false
16:07:26.896 [main] INFO org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
16:07:54.274 [pool-1-thread-1] DEBUG org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl - Connection pool now considered primed; min-size will be maintained

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。

Hibernate的问题在于他无法关闭连接。 (这在我的解决方案中没有修复)。

所以这个想法并不是每代都建立这种联系。 Hibernate提供虚拟ConnectionProvider.class

org.hibernate.engine.jdbc.connections.internal.UserSuppliedConnectionProviderImpl

这对此目的不利,因为它会抛出RuntimeException

见下文:

@Override
public Connection getConnection() throws SQLException {
    throw new UnsupportedOperationException( "The application must supply JDBC connections" );
}

所以我的想法是创建ConnectionProvider.class的自定义实现,并使用persistence.xml<property name="hibernate.connection.provider_class" value="com.akhambir.ddl.ddl_gen.DLLGeneratorConnectionProvider"/>在我的持久性单元中使用它。

DLLGeneratorConnectionProvider.class内部没有实现,只是从Connection返回未实现的匿名StatementgetConnection(),这有助于避免为HibernatePersistenceProvider.class创建真正的连接。

还可以在GitHub上的构建时找到我可行的模式生成版本:https://github.com/akhambir/jpa2.1-schema-generator-with-hibernate