Java Springboot应用程序在数据库重新启动时失败
我们开发了一个Springboot Java应用程序,我将其放在用于开发环境的docker容器中 Spring引导版本是1.5.6 使用的数据库是SQL server 2016,它再次位于docker(windows容器)上 问题: 每当我重新启动SQL DB容器时,应用程序就会开始给出此错误Java Springboot应用程序在数据库重新启动时失败,java,spring-boot,Java,Spring Boot,我们开发了一个Springboot Java应用程序,我将其放在用于开发环境的docker容器中 Spring引导版本是1.5.6 使用的数据库是SQL server 2016,它再次位于docker(windows容器)上 问题: 每当我重新启动SQL DB容器时,应用程序就会开始给出此错误 2018-10-29 16:00:08,993 ERROR pool-13-thread-1 org.springframework.scheduling.support.TaskUtils$Loggi
2018-10-29 16:00:08,993 ERROR pool-13-thread-1 org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler - Unexpected error occurred in scheduled task.
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy155.findOne(Unknown Source)
at au.com.outware.swepad.tasks.WorkOrderManagerTask.taskFetchAndProcessWorkOrderDetails(WorkOrderManagerTask.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.persistence.PersistenceException: com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1700)
at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:48)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:189)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380)
... 30 common frames omitted
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:206)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.checkClosed(SQLServerConnection.java:724)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.setAutoCommit(SQLServerConnection.java:2615)
at sun.reflect.GeneratedMethodAccessor163.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126)
at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:79)
at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81)
at com.sun.proxy.$Proxy102.setAutoCommit(Unknown Source)
at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.begin(AbstractLogicalConnectionImplementor.java:67)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:238)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:214)
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:52)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1512)
at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:45)
... 32 common frames omitted
2018-10-29 16:00:08,995 WARN pool-30-thread-1 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: null
2018-10-29 16:00:08,996 ERROR pool-30-thread-1 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - The connection is closed.
2018-10-29 16:30:00,017 INFO pool-13-threa
让应用程序工作的唯一方法是重新启动应用程序(容器重新启动)
我们在论坛上搜索并在application.yml中设置此属性
spring.datasource.tomcat.testOnBorrow=true
spring.datasource.tomcat.validation-query=SELECT 1
我们的应用程序yml如下所示
spring:
datasource:
type: org.apache.tomcat.jdbc.pool.XADataSource
tomcat:
test-on-borrow: true
validation-query: select 1
validation-interval: 30000
jpa:
database: sql_server
database-platform: org.hibernate.dialect.SQLServer2012Dialect
generate-ddl: false
hibernate:
ddl-auto: none
我们在yml文件中有一个单独的部分,用于开发、暂存和产品环境
我们正在使用dev profile for dev environment。这是否要求我们在本节中放置tomcat属性
---
spring:
profiles: dev,staging,prod
datasource:
url: "jdbc:sqlserver://${DB_IP}:${DB_PORT};databaseName=${DB_NAME}"
username: "${DB_USER}"
password: "${DB_PASS}"
initialize: false
jpa:
show-sql: true
generate-ddl: false
hibernate:
ddl-auto: none
你知道怎么解决这个问题吗
谢谢。请确保您的数据库正在属性文件中定义的
端口和ip地址上运行(无论是.yaml
还是.properties
)
如果您稍微仔细地看到您的异常并阅读消息,您将很容易识别问题
这里stacktrace说,EntityManager
将无法初始化,因为连接已关闭。
注意:请确认您的数据库是否正在运行
问题1:可用时自动重新连接的连接池配置
我不清楚您使用什么配置文件以及构建什么类型的数据源。但我会发布这个参考指南
使用哪种类型的数据源可以使用属性
具体到这一点
从Spring boot doc()中,我引用-
- 我们更喜欢HikariCP,因为它的性能和并发性。如果HikariCP可用,我们总是选择它
- 否则,如果Tomcat池数据源可用,我们将使用它
- 如果HikariCP和Tomcat池数据源都不可用,如果Commons DBCP2可用,我们就使用它
如果使用spring boot starter jdbc
或
spring boot starter data jpa
“starters”,您会自动获得
对HikariCP的依赖性
因此,除非您特别要求使用Tomcat连接池(您通过spring.datasource.type
在application.yml中使用了该连接池),否则您将得到HikariCp。所以要小心选择
因此,以下是Tomcat和HikariCP的属性,它们可以帮助您自动重新连接:
Tomcat JDBC连接池:
spring.datasource.tomcat.testOnBorrow = true
spring.datasource.tomcat.validation-query = SELECT 1
#connectionTestQuery not needed for JDBC4 drivers. You can add them unless complained
spring.datasource.hikari.connectionTestQuery = SELECT 1
spring.datasource.hikari.connectionInitSql = SELECT 1
Hikari CP:
spring.datasource.tomcat.testOnBorrow = true
spring.datasource.tomcat.validation-query = SELECT 1
#connectionTestQuery not needed for JDBC4 drivers. You can add them unless complained
spring.datasource.hikari.connectionTestQuery = SELECT 1
spring.datasource.hikari.connectionInitSql = SELECT 1
p.S::注意您使用的配置文件和数据源类型。您将tomcat放在其中,在dev、qa和prod中,您将获得默认的HikariCp。留心。
关于DBs的验证查询,参考文章如下:
问题2:经常断开连接的Docker Windows容器
- 尝试安装最新的docker版本
- 如果仍然无法工作,请尝试切换到Docker中的Linux容器
我们找到了解决这个问题的方法。
问题是这句话
类型:org.apache.tomcat.jdbc.pool.XADataSource
我们用
type:org.apache.tomcat.jdbc.pool.DataSource
现在,应用程序可以在连接断开到db后,无需重新启动即可重新连接到db
谢谢大家的想法
毗瑟奴“com.microsoft.sqlserver.jdbc.SQLServerException:连接已关闭。”您能验证数据库是否正在运行吗?也许应用程序在数据库启动之前启动是的,我验证过了。数据库已启动并正在运行。应用程序的初始负载工作正常。然后当数据库重新启动时,我们就面临这个问题。我希望应用程序在重启后db启动后能够恢复,但这并没有发生。如果我可以问的话,可能是重复的,并且您正在本地运行哪个配置文件?@KarthikR:我们正在使用Dev配置文件。db启动、运行且可访问。我清楚地提到,在第一次启动时,应用程序启动、连接到数据库并可以正常工作。该问题仅在数据库重新启动时发生。一旦应用程序重新启动,问题就会得到解决。所以与db无关。