JPA,Hibernate与c3p0和Postgres。检测数据库连接问题

时间:2017-04-07 12:37:13

标签: java postgresql hibernate jpa c3p0

我正在编写一个通过Hibernate与c3p0池连接到Postgres DB的应用程序。在主界面出现之前,我想检测有效的数据库连接设置和与DB的连接。如果设置无效,我希望向用户显示消息,并建议更改设置或关闭应用程序。 但问题是EntityManagerFactory不会抛出异常甚至在连接失败后返回。

以下是使用错误的连接设置产生错误的代码示例:

public void connect(ConnectionSettingsModel conSet) throws Exception {
    Map<String, String> connectionProperties = new HashMap<>();
    connectionProperties.put("javax.persistence.jdbc.url", conSet.getUrl());
    connectionProperties.put("javax.persistence.jdbc.user", conSet.getUser());
    connectionProperties.put("javax.persistence.jdbc.password", conSet.getPassword());
    connectionProperties.put("hibernate.default_schema", conSet.getSchema());

    System.out.println("Before creating EM");
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("postgres-connect", connectionProperties);
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    System.out.println("After creating EM");
 }
<{1}}中的

c3p0配置:

persistence.xml

具有不存在的用户名的日志示例:

<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"/>
<property name="hibernate.c3p0.min_size" value="0"/>
<property name="hibernate.c3p0.max_size" value="10"/>
<property name="hibernate.c3p0.timeout" value="300"/>
<property name="hibernate.c3p0.idle_test_period" value="3000"/>
<property name="hibernate.c3p0.max_statements" value="50"/>
<property name="hibernate.c3p0.acquireRetryAttempts" value="1"/>

在此消息之后,它不会抛出任何异常或返回

1 个答案:

答案 0 :(得分:1)

您可以考虑修改

<property name="hibernate.c3p0.acquireRetryAttempts" value="1"/>

恢复默认值30(或更高),然后尝试

<property name="hibernate.c3p0.breakAfterAcquireFailure" value="true"/>

然后,如果尝试从数据库获取Connections的完整周期失败(再次,这应该是多次,或者您的应用程序将非常脆弱),那么您的c3p0 DataSource将会中断,并且进一步尝试签出Connection将立即失败。这样做的缺点是,在临时网络或数据库中断后,你将失去c3p0“自我修复”的能力。如果临时中断在采集周期中失败,则必须自己重建DataSource(或重新启动应用程序)。

如果您想要两全其美,请将hibernate.c3p0.acquireRetryAttempts设置为30-ish,将hibernate.c3p0.breakAfterAcquireFailure保留为其默认值false,但请编写您自己的自定义代码以测试可用性你的数据库。修改上面的测试connect()函数(需要重新组织,你只想创建EntityManagerFactory一次),可能就像......一样简单。

public void connect(ConnectionSettingsModel conSet) throws Exception {

    try( Connection con = DriverManager.getConnection( conSet.getUrl(), conSet.getUser(), conSet.getPassword() ) ) {
        /* Nothing to do here, really... */
    } catch ( Exception e ) {
        System.out.println("Trouble connecting with DBMS, please check database url, username, and password.");
        throw e;  
    }

    Map<String, String> connectionProperties = new HashMap<>();
    connectionProperties.put("javax.persistence.jdbc.url", conSet.getUrl());
    connectionProperties.put("javax.persistence.jdbc.user", conSet.getUser());
    connectionProperties.put("javax.persistence.jdbc.password", conSet.getPassword());
    connectionProperties.put("hibernate.default_schema", conSet.getSchema());


    System.out.println("Before creating EM");
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("postgres-connect", connectionProperties);
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    System.out.println("After creating EM");
 }