【问题标题】:Catch invalid hibernate connection URL error捕获无效的休眠连接 URL 错误
【发布时间】:2010-01-05 17:13:24
【问题描述】:

如果我在 hibernate.cfg.xml 文件中输入了错误的连接 URL,我希望能够检测到它并优雅地终止,但我不知道怎么做;它只是在休眠初始化过程中无限期地挂在 buildSessionFactory() 上:

SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();

它在一个 try 块中,我试图捕获一个通用异常,但 buildSessionFactory() 从来没有抛出一个,它只是挂起。这是我的 hibernate.cfg.xml 中的 URL 元素:

<property name="hibernate.connection.url">jdbc:mysql://123.123.123.123/mydb</property>

我的系统:Ubuntu 9.10 和 Tomcat 5.5、Java 1.6、Hibernate 3 和 MySQL 5。

当我第一次初始化休眠时,它只挂起 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>

【问题讨论】:

  • 您看到的延迟很可能是由 c3p0 的 acquireRetryDelay 和 acquireRetryAttempts 属性引起的,它们会在暂停一小段时间(默认为 1 秒)后重试连接。总的来说,花很多精力让你的应用处理简单的配置错误似乎很愚蠢(除非你的设置有什么我不明白的地方)。
  • 感谢您的回复。请参阅我对 Pascal 答案的评论。

标签: java mysql hibernate url connection


【解决方案1】:

正如 BryanD 在评论中提到的,buildSessionFactory() 并没有真正挂起,时间很可能花在尝试重新连接的 c3p0 上。引用c3p0documentation

当 c3p0 数据源尝试获取连接但失败时,它将重试最多 acquireRetryAttempts 次,每次尝试之间有 acquireRetryDelay 的延迟。如果所有尝试都失败,任何等待来自数据源的连接的客户端都会看到一个异常,表明无法获取连接。请注意,在整轮尝试失败之前,客户端不会看到任何异常,这可能是在初始连接尝试之后的一段时间。如果acquireRetryAttempts 设置为0,c3p0 将无限期地尝试获取新连接,并且对getConnection() 的调用可能会无限期地阻塞等待成功获取。

如果您没有配置它,acquireRetryAttempts 的默认值是 30,因此buildSessionFactory() 确实可能需要一些时间才能返回。但是,除非您使用小于或等于零的值,在这种情况下 c3p0 将继续尝试无限期地获取连接,它会。

也许您可以使用较低的值。或者,也许您可​​以使用正确的 URL 并停止在异常情况(配置错误)上花费时间。

【讨论】:

  • 感谢您的信息。我尝试设置 c3p0.acquireRetryAttempts=1 (并确认它是使用调试输出设置的),但它的行为完全相同。我只问这一切,因为我正在几个不同的服务器上测试我的应用程序,当我忘记更新连接 URL 时,应用程序无限期挂起时,我浪费了大量时间来找出问题所在。我认为可能有一个简单的修复程序来捕获此错误,以使自己和其他人免于在将来浪费时间调试配置错误...
猜你喜欢
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-27
  • 2015-10-01
相关资源
最近更新 更多