2012-10-25 28 views
2

我的应用程序使用JPA(Hbernate ORM)连接到部署在JBoss AS 7.x服务器上的SQL Server 2008。如果网络出现故障,再次来到了,我得到了以下异常如何在JBoss AS 7.x网络故障后重新建立连接-JPA

14:59:27,996 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: The connection is closed. 
14:59:28,002 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1361) 
14:59:28,012 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1289) 
14:59:28,020 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:261) 
14:59:28,025 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at com.honeywell.domoweb.dataservice.dao.impl.UserDaoImpl.getUsers(UserDaoImpl.java:372) 
14:59:28,030 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
14:59:28,034 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
14:59:28,039 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
14:59:28,044 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at java.lang.reflect.Method.invoke(Method.java:597) 
14:59:28,047 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
14:59:28,052 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
14:59:28,058 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
14:59:28,064 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
14:59:28,069 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
14:59:28,075 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
14:59:28,080 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at $Proxy66.getUsers(Unknown Source) 
14:59:28,083 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at com.honeywell.domoweb.dataservice.dao.impl.TemplateDaoImpl.getTemplate(TemplateDaoImpl.java:44) 
14:59:28,089 ERROR [stderr] (http-localhost-127.0.0.1-8080-1) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)... 

我GOOGLE了这个问题,并发现这一问题需要在连接池的配置使用autoReconnect的属性再次重新连接的变化,但没“吨发现任何例如,如何与我的连接池settings.Below嵌入autoReconnect的是在Standalone.xml我的连接池的设置文件

<subsystem xmlns="urn:jboss:domain:datasources:1.0"> 
     <datasources> 


      <datasource jndi-name="java:jboss/datasources/DataServiceDS" pool-name="dataServicePool" enabled="true" use-java-context="true"> 
       <connection-url>jdbc:sqlserver://ipaddress:1433;databaseName=myDataBase</connection-url> 
       <driver>sqlserver</driver> 
       <pool> 
        <min-pool-size>10</min-pool-size> 
        <max-pool-size>100</max-pool-size> 
        <prefill>true</prefill> 
       </pool> 
       <security> 
        <user-name>usename</user-name> 
        <password>password</password> 
       </security> 
      </datasource> 
      <drivers> 

       <driver name="sqlserver" module="com.microsoft.sqlserver"> 
        <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</xa-datasource-class> 
       </driver> 
      </drivers> 
     </datasources> 
    </subsystem> 

可否请您让我知道,如何重新连接到数据库,如果网络出现故障并重新连接?

回答

2

你想解决什么问题?

如果您试图在“网络故障”时停止交易失败。这是不可能的。您需要查看“XA”和SQL集群来解决该问题的某些部分。但我不认为你正在寻找这个。

..

如果你想从他们是否有足够的不幸是空闲的SQL连接到JBoss中的连接池是保持的第一个用户不停止应用程序操作。那么是的,你可以做些什么。

的问题是:

  • 的Windows默认情况下,断开活动的TCP连接时,“网络出现故障”其他平台不这样做。对于你,我猜想只有一部分网络出现故障,这意味着SQL服务器如果受到影响就会结束,而不是JBoss结束。

  • JBoss端的连接池将保持TCP连接在池中的空闲连接打开。 JBoss端不知道网络关闭,它可能会短时间与SQL服务器失去联系。当网络出现时,SQL服务器端重置/丢失所有连接。但是JBoss的终端仍然有“半开放的连接”,它仍然认为连接是有效的。

  • 在需要使用SQL之前,JBoss可能会在一段时间内空闲(秒/分钟/小时)。然后它得到一个SQL句柄,并且连接池适时地从闲置的池中返回一个。不知道TCP连接已经死亡。应用程序然后使用它来找出TCP连接被重置,以响应某些数据从客户端发送到服务器和服务器,并说'我没有打开连接'。这会强制SQL驱动程序关闭连接并开始将SQLException返回到JDBC句柄上的操作。

所以下面我笼统地谈论如何帮助缓解或解决问题,请咨询您的支持渠道和SQL文件:

观光考虑:

  • 你的连接池塘文件。我相信JBoss提供了自己的连接池实现。所以虽然这个问题可以在连接池中解决,但不清楚连接池是否与你的JBoss版本以及你正在使用的连接池可能具有适当的功能。

  • 启用TCP保持活动,这些是TCP协议执行的低级ping/pong,通常可以在几秒钟内完成。默认情况下,1小时对于SQL来说可能太长,可能5分钟更好。

  • 启用的连接池,以检查/验证连接是它给应用程序之前良好和有效的。这可能会使用内部ping/pong检查,或者可能会执行“SELECT 1”。这可能是最简单的/最快的解决方案,完全解决了这个问题,但是然后可以在使用前将额外的往返可观的性能影响。

  • 启用仅当连接已经闲置超过某些限制(也许60秒)长的上述点。这可减轻SQL在相当闲置时启用时的性能影响。

  • 看看你的SQL驱动程序支持自定义的TCP数据平/乒乓机制,看看的连接池实现支持使用它。

  • 使用简短的最大空闲时间。

  • 下空闲连接的最大数目。

  • 如果连接不在事务中并且如果这是第一个失败的语句(通常唯一的选项更改是autocommit = off,那么'BEGIN TRANSACTION'这种情况对于驱动程序来说可能会检测到并无缝地恢复)。

建议步骤也许看C3P0的连接池,如果你有一个选择,选择外部的第三方开源缓冲池使用。这在JBoss环境中可能并非如此。

6

您可以添加

<check-valid-connection-sql>select 1 </check-valid-connection-sql> 

到数据源配置,或任何你想要的其他SQL语句。 这个sql语句将在连接池每次从连接池检出时执行,并且如果语句失败,即连接被关闭,它将被销毁并重新创建/重新连接到sql server。这将确保您的应用程序(hibernate)始终能够正常工作。

3

也有难以找到类似问题的例子。对于jboss7添加了以下几行数据源配置

<datasource> 
    ... 
    <validation> 
    <check-valid-connection-sql>select 1 from dual</check-valid-connection-sql> 
    <validate-on-match>false</validate-on-match> 
    <background-validation>true</background-validation> 
    </validation> 
    ... 
</datasource>