我正在编写一个通过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"/>
在此消息之后,它不会抛出任何异常或返回
答案 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");
}