Ank*_*ain 3 mysql spring hibernate
我们使用 Spring 4.2.5、Hibernate 4.1.4、MYSql 来构建 REST 服务。我们面临着非常奇怪的问题,无法理解到底发生了什么并出现以下错误:
\n\n最后一次从服务器成功接收的数据包是在 43417 秒前。最后一次成功发送到服务器的数据包是在 43417 秒前,这比服务器配置的“wait_timeout”值要长。您应该考虑在应用程序中使用之前使连接过期和/或测试连接有效性,增加客户端超时的服务器配置值,或使用 Connector/J 连接属性“autoReconnect=true”来避免此问题。
\n\n为了获得数据库连接,我们使用基于 java 的配置,如下所示:
\n\n @Configuration\n @EnableTransactionManagement\n @ComponentScan({ "api.configuration" })\n\npublic class HibernateConfiguration {\n @Autowired\n private Environment environment;\n\n private static final Logger logger = LoggerFactory.getLogger(HibernateConfiguration.class);\n @Bean\n public LocalSessionFactoryBean sessionFactory() throws PropertyVetoException {\n LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();\n sessionFactory.setDataSource(dataSource());\n sessionFactory.setPackagesToScan(new String[] { "api.domain" });\n sessionFactory.setHibernateProperties(hibernateProperties());\n return sessionFactory;\n }\n\n @Bean\n public DataSource dataSource() {\n DriverManagerDataSource dataSource = new DriverManagerDataSource();\n dataSource.setDriverClassName("com.mysql.jdbc.Driver");\n dataSource.setUrl("jdbc:mysql://localhost:3306/test?autoReconnect=true");\n dataSource.setUsername("test"); \n dataSource.setPassword("test");\n return dataSource;\n }\n\n\n private Properties hibernateProperties() {\n Properties properties = new Properties();\n properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");\n properties.put("hibernate.show_sql", "true");\n properties.put("hibernate.format_sql", "true");\n properties.put("hibernate.hbm2ddl.auto", "update");\n properties.put("connection.autoReconnect", "true");\n properties.put("connection.autoReconnectForPools","true");\n properties.put("connection.is-connection-validation-required", "true");\n\n return properties; \n }\n\n @Bean\n public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws PropertyVetoException {\n LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();\n em.setDataSource(dataSource());\n em.setPackagesToScan(new String[] { "api.domain" });\n\n JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();\n em.setJpaVendorAdapter(vendorAdapter);\n em.setJpaProperties(hibernateProperties());\n\n return em;\n }\n\n @Bean\n public PlatformTransactionManager transactionManager() throws PropertyVetoException{\n JpaTransactionManager transactionManager = new JpaTransactionManager();\n transactionManager.setEntityManagerFactory(entityManagerFactory().getObject() );\n return transactionManager;\n }\n\n @Bean\n public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){\n return new PersistenceExceptionTranslationPostProcessor();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n谷歌搜索发现我们可以通过添加以下两个属性来解决这个问题:
\n\n<property name=\xe2\x80\x9dvalidationQuery\xe2\x80\x9d value=\xe2\x80\x9dSELECT 1\xe2\x80\xb3 />\n\n<property name=\xe2\x80\x9dtestOnBorrow\xe2\x80\x9d value=\xe2\x80\x9dtrue\xe2\x80\x9d />\nRun Code Online (Sandbox Code Playgroud)\n\n由于我们使用 java 配置而不是基于 XML 的配置,因此我们不知道 在 java 类中为validationQuery和testOnBorrow添加的确切属性名称,因为我们有hibernate.show_sql
\n\n请建议
\n数据库终止了其会话和物理连接,但客户端直到现在才知道这一点。
我们先来了解一下问题所在。java.sql.Connection是一个Java对象,代表一些MySQL服务器连接。这是通过 TCP 进行的客户端-服务器通信。如果服务器连接断开或 TCP 连接断开,客户端不知道这一点,因此 Java 对象仍然存在,但无法再与服务器通信。在您的情况下,如果过时的连接闲置一段时间(默认情况下为 8 小时),MySQL 服务器将终止它们。
如果您创建一个裸驱动程序连接,这种情况将非常罕见 - 这种连接会在使用很短一段时间后创建并关闭。在你的示例中,事情非常混乱 - 你同时使用 SessionFactory 和 EntityManagerFactory ,看起来你使用裸连接(并且很难用裸连接得到这个错误),所以我不会对此发表评论。
您找到的选项不适用于 Hibernate。它们用于生产就绪的数据库池之一(我假设是 Tomcat JDBC 池)。因此,您应该使用该池(或另一个池,如 C3P0)并将其配置为定期检查连接 - 这样,从 MySQL 服务器的角度来看,连接就不会过时。以下是C3P0配置的示例:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="jdbcUrl" value="jdbc:h2:mem:qalatraining;DB_CLOSE_DELAY=-1"/>
<property name="driverClass" value="org.h2.Driver"/>
<property name="user" value="sa"/>
<property name="password" value=""/>
<property name="maxPoolSize" value="10"/>
<property name="idleConnectionTestPeriod" value="3600"/>
<property name="testConnectionOnCheckin" value="true"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
现在您应该将此数据源传递给 Hibernate:
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
配置数据库池还有很多内容,您可以在此处找到详细信息,并在此处找到工作示例。
| 归档时间: |
|
| 查看次数: |
18690 次 |
| 最近记录: |