Hibernate事务系列问题

1.org.hibernate.TransactionException: JDBC begin transaction failed:

org.hibernate.TransactionException: JDBC begin transaction failed: 
	at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:76)
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160)
	at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1426)
	at sun.reflect.GeneratedMethodAccessor45.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
	at com.sun.proxy.$Proxy43.beginTransaction(Unknown Source)
	at com.cmri.bcatp.dao.impl.UserDaoImpl.loadConfig(UserDaoImpl.java:119)
	at com.cmri.bcatp.service.impl.UserServiceImpl.loadConfig(UserServiceImpl.java:153)
	at com.cmri.bcatp.controller.LoginController.getUserConfig(LoginController.java:115)
	at com.cmri.bcatp.controller.LoginController.login(LoginController.java:62)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at com.cmri.bcatp.filter.SessionFilter.doFilter(SessionFilter.java:44)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:744)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 2,868,187 milliseconds ago.  The last packet sent successfully to the server was 2,868,193 milliseconds ago.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
	at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1117)
	at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3871)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2484)
	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2788)
	at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:5282)
	at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:881)
	at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:72)
	... 55 more
Caused by: java.net.SocketException: Connection reset by peer: socket write error
	at java.net.SocketOutputStream.socketWrite0(Native Method)
	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
	at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
	at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3852)
	... 61 more

原因:

This exception occured usually when a DB Connection stale.

Stale means: connection killed by the server, but still considered alive by the pool. You need to configure connection testing in the connection. For this approach inC3P0 you have to using following configuration:

需要修改:testConnectionOnCheckin ,testConnectionOnCheckout,checkoutTimeout ,idleConnectionTestPeriod,preferredTestQuery等配置。

参考一个:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  
        destroy-method="close">  
        <property name="jdbcUrl" value="jdbc:mysql://192.168.1.21:3306/game_admin?autoReconnect=true&useUnicode=true&characterEncoding=utf-8"/>  
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>  
        <property name="user" value="linyu"/>  
        <property name="password" value="com.123"/>  
        <!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3-->   
        <property name="initialPoolSize" value="2"/>  
        <!-- 连接池中保留的最小连接数,默认为:3-->   
        <property name="minPoolSize" value="2"/>  
        <!--连接池中保留的最大连接数。默认值: 15 -->     
        <property name="maxPoolSize" value="15"/>  
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 -->     
        <property name="acquireIncrement" value="2"/>  
        <!--定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次-->     
         <property name="acquireRetryAttempts" value="0"/>    
         <!--重新尝试的时间间隔,默认为:1000毫秒-->     
          <property name="acquireRetryDelay" value="1000" />    
         <!--最大空闲时间,3600秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 -->     
        <property name="maxIdleTime" value="3600"/>  
         <!--c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效,只要有一个不为0,则语句的缓存就能生效。如果默认值: 0-->     
        <property name="maxStatements" value="0"/>  
         <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。默认值: 0 -->     
        <property name="maxStatementsPerConnection" value="0"/>  
        <!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。测试的表必须在初始数据源的时候就存在。Default: null-->  
        <property name="preferredTestQuery" value="select 1"/>  
         <!--每1800秒检查所有连接池中的空闲连接。Default: 0 -->  
        <property name="idleConnectionTestPeriod" value="1800"/>  
        <!-- 获取连接时测试有效性,每次都验证连接是否可用 -->  
        <property name="testConnectionOnCheckout" value="false"/>  
    </bean></span>
官网文档:http://www.mchange.com/projects/c3p0/#configuring_connection_testing

 If you don't know what to do, try this:

   1. If you know your driver supports the JDBC 4 Connection.isValid(...) method and you are using c3p0-0.9.5 or above, don't set a preferredTestQuery. If your driver does not support this method (or if you are not sure), try SELECT 1 for your preferredTestQuery, if you are running MySQL or Postgres. For other databases, look for suggestions here. Leave automatedTestTable undefined.

    2.Begin by setting testConnectionOnCheckout to true and get your application to run correctly and stably. If you are happy with your application's performance, you can stop here! This is the simplest, most reliable form of Connection-testing, but it does have a client-visible performance cost.

  3.  If you'd like to improve performance by eliminating Connection testing from clients' code path:

        a. Set testConnectionOnCheckout to false

        b. Set testConnectionOnCheckin to true

        c. Set idleConnectionTestPeriod to 30, fire up you application and observe. This is a pretty robust setting, all Connections will tested on check-in and every 30 seconds thereafter while in the pool. Your application should experience broken or stale Connections only very rarely, and the pool should recover from a database shutdown and restart quickly. But there is some overhead associated with all that Connection testing.

        d. If database restarts will be rare so quick recovery is not an issue, consider reducing the frequency of tests by idleConnectionTestPeriod to, say, 300, and see whether clients are troubled by stale or broken Connections. If not, stick with 300, or try an even bigger number. Consider setting testConnectionOnCheckin back to false to avoid unnecessary tests on checkin. Alternatively, if your application does encounter bad Connections, consider reducing idleConnectionTestPeriod and set testConnectionOnCheckin back to true. There are no correct or incorrect values for these parameters: you are trading off overhead for reliability in deciding how frequently to test. The exact numbers are not so critical. It's usually easy to find configurations that perform well. It's rarely worth spending time in pursuit of "optimal" values here.

So, when should you stick with simple and reliable (Step 2 above), and when is it worth going for better performance (Step 3)? In general, it depends on how much work clients typically do with Connections once they check them out. If clients usually make complex queries and/or perform multiple operations, adding the extra cost of one fast test per checkout will not much affect performance. But if your application typically checks out a Connection and performs one simple query with it, throwing in an additional test can really slow things down.

That's nice in theory, but often people don't really have a good sense of how much work clients perform on average. The best thing to do is usually to try Step 3, see if it helps (however you measure performance), see if it hurts (is your application troubled by broken Connections? does it recover from database restarts well enough?), and then decide. You can always go back to simple, slow, and robust. Just set testConnectionOnCheckout to true, testConnectionOnCheckin to false, and set idleConnectionTestPeriod to 0.

But do, always, be sure that your tests themselves are performant, either because your JDBC driver supports Connection.isValid(...) or because you have set an efficient preferredTestQuery !!!

特别注意:

mysql 数据库链接默认的超时时长为28800秒,2、c3p0 的几个参数意思;
通过以上信息的收集隐隐知道了问题所在(mysql经过28800秒也就是8个小时后关掉空闲链接,而c3p0是经过6000000妙才断开链接,就
有可能出现c3po保持的连接有可能已经被mysql关掉了,自然就出现了hibernate不能打开session。


可参考:http://stackoverflow.com/questions/10658473/jdbc-begin-failed

http://stackoverflow.com/questions/12808731/what-does-testconnectiononcheckin-in-c3p0-mean

http://blog.csdn.net/t12x3456/article/details/7650404

http://blog.csdn.net/jiangguilong2000/article/details/42365479

http://blog.csdn.net/yzh54ak/article/details/6697052


困扰很久,根据上述的说法也未得到解决,功夫不负有心人得到解决之道。

http://www.tuicool.com/articles/iM3qqyu

使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案

原因分析:

MySQL服务器默认的“wait_timeout”是28800秒即8小时,意味着如果一个连接的空闲时间超过8个小时,MySQL将自动断开该连接,而连接池却认为该连接还是有效的(因为并未校验连接的有效性),当应用申请使用该连接时,就会导致上面的报错。

解决方案( 解决这个问题的办法有三种,推荐第二种 ):

1. 增加 MySQL 的 wait_timeout 属性的值 

修改mysql安装目录下的配置文件 my.ini文件(如果没有此文件, 复制“my-default.ini”文件,生成“复件 my-default.ini”文件。将“复件 my-default.ini”文件重命名成“my.ini” ),在文件中设置: 


wait_timeout=31536000
interactive_timeout=31536000

这两个参数的默认值是8小时(60*60*8=28800)。

注意:


2. 减少连接池内连接的生存周期

减少连接池内连接的生存周期, 使之小于 上一项中所设置的wait_timeout 的值  

修改 c3p0 的配置文件, 在 Spring 的配置文件中设置:

 <bean id="dataSource"  class="com.mchange.v2.c3p0.ComboPooledDataSource">  	
 <property name="maxIdleTime"value="1800"/>  
 <!--other properties -->  
 </bean>

3. 定期使用连接池内的连接

定期使用连接池内的连接,使得它们不会因为闲置超时而被 MySQL 断开。 

修改 c3p0 的配置文件,在  Spring 的配置文件中设置:

 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  
 <property name="preferredTestQuery" value="SELECT 1"/>  
 <property name="idleConnectionTestPeriod" value="18000"/>  
 <property name="testConnectionOnCheckout" value="true"/>  
 <!--other properties --></bean>


你可能感兴趣的:(Hibernate,事务)