如果我在 hibernate.cfg.xml 文件中放置了错误的连接 URL,我希望能够检测到它并优雅地终止,但我不知道该怎么做;它只是在 hibernate 初始化过程中无限期地卡在 buildSessionFactory() 上:
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
它在一个 try block 中,我试图捕获一个通用异常,但 buildSessionFactory() 从来没有抛出一个异常,它只是挂起。这是我的 hibernate.cfg.xml 中的 URL 元素:
<property name="hibernate.connection.url">jdbc:mysql://123.123.123.123/mydb</property>
我的系统:带有 Tomcat 5.5、Java 1.6、Hibernate 3 和 MySQL 5 的 Ubuntu 9.10。
当我第一次初始化 hibernate 时,它只挂起 22 秒,然后开始吐出有关线程和死锁的警告(从这里开始):
15:16:25,758 WARN ThreadPoolAsynchronousRunner.class: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@a010ba -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
15:16:25,761 WARN ThreadPoolAsynchronousRunner.class: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@a010ba -- APPARENT DEADLOCK!!! Complete Status:
Managed Threads: 3
Active Threads: 3
Active Tasks:
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@109da93 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@1ed1dbe (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@3bc1a1 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1)
Pending Tasks:
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@12549c4
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@10df4e2
Pool thread stack traces:
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0,5,main]
java.net.PlainSocketImpl.socketConnect(Native Method)
java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
java.net.Socket.connect(Socket.java:525)
java.net.Socket.connect(Socket.java:475)
java.net.Socket.<init>(Socket.java:372)
java.net.Socket.<init>(Socket.java:215)
com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:253)
com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:284)
com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2194)
com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:723)
com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
java.lang.reflect.Constructor.newInstance(Constructor.java:513)
com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:302)
com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:282)
com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:135)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171)
com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137)
com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
编辑:这是我的 hibernate.cfg.xml 中的 c3p0 属性
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">100</property>
<property name="hibernate.c3p0.max_size">100</property>
<property name="hibernate.c3p0.max_statements">100</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.timeout">100</property>
最佳答案
正如 BryanD 在评论中提到的,buildSessionFactory()
并没有真正挂起,时间很可能花在了试图重新连接的 c3p0 上。引用 c3p0 documentation :
When a c3p0 DataSource attempts and fails to acquire a Connection, it will retry up to
acquireRetryAttempts
times, with a delay ofacquireRetryDelay
between each attempt. If all attempts fail, any clients waiting for Connections from the DataSource will see an Exception, indicating that a Connection could not be acquired. Note that clients do not see any Exception until a full round of attempts fail, which may be some time after the initial Connection attempt. IfacquireRetryAttempts
is set to 0, c3p0 will attempt to acquire new Connections indefinitely, and calls togetConnection()
may block indefinitely waiting for a successful acquisition.
如果你没有配置它,acquireRetryAttempts
的默认值是 30,所以 buildSessionFactory()
可能确实需要一些时间才能返回。但是,除非您使用小于或等于零的值,在这种情况下,c3p0 将继续尝试无限期地获取连接,它会的。
也许您可以使用较低的值。或者,也许您可以只使用正确的 URL 并停止在异常情况(配置错误)上花费时间。
关于java - 捕获无效 hibernate 连接 URL 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2007749/