Spring boot Springboot和H2关闭死锁
目前,我能够在使用h2和spring引导的组合时创建死锁。外面有很多问题,看起来有点类似,但显然它们已经解决了,我不完全确定是Spring还是h2做了一些奇怪的事情 首先对死锁进行visualvm跟踪(滚动至底部查看锁): RepositoryTest.ktSpring boot Springboot和H2关闭死锁,spring-boot,kotlin,h2,deadlock,spring-boot-test,Spring Boot,Kotlin,H2,Deadlock,Spring Boot Test,目前,我能够在使用h2和spring引导的组合时创建死锁。外面有很多问题,看起来有点类似,但显然它们已经解决了,我不完全确定是Spring还是h2做了一些奇怪的事情 首先对死锁进行visualvm跟踪(滚动至底部查看锁): RepositoryTest.kt package com.example.deadlock import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Auto
package com.example.deadlock
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import kotlin.test.assertEquals
@SpringBootTest(classes = [Application::class])
class RepositoryTest @Autowired constructor(private val repository: Repository) {
@Test
fun initialCount() {
assertEquals(0, repository.findAll().size)
}
}
为了完整性起见,这是有问题的build.gradle:
buildscript {
ext {
kotlinVersion = "1.3.31"
springVersion = "2.1.5.RELEASE"
}
repositories {
mavenCentral()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springVersion}"
}
}
plugins {
id "org.jetbrains.kotlin.jvm" version "1.3.31"
id "org.springframework.boot" version "2.1.5.RELEASE"
id "idea"
}
apply plugin: "org.springframework.boot"
apply plugin: "io.spring.dependency-management"
group = "com.example.deadlock"
version = "0.0.1-SNAPSHOT"
description = "Deadlock with Spring and h2"
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
compileJava.options.encoding = "UTF-8"
tasks.withType(Test) {
useJUnitPlatform()
outputs.upToDateWhen {false}
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-reflect"
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework:spring-jdbc"
compile "com.h2database:h2"
// Test setups
testCompile "org.junit.jupiter:junit-jupiter-api"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
testCompile "org.springframework.boot:spring-boot-starter-test"
}
至少在我的机器上,通过运行/gradlew clean assembly
,然后进行循环/gradlew测试,可以很容易地再现
出于某种原因,如果两个测试是相同的,那么它就不起作用,而且(毫不奇怪)我无法用一个测试重现
从我所看到的情况来看,可能会有两个关机挂钩,最终在解决问题上相互竞争。然而,我并不完全确定。在询问之后不久,我当然发现:
看起来确实是同一个问题。现在,我已经在两个测试中添加了@DirtiesContext
,目前它们已经运行了15次以上,没有问题来自我在一旁遇到的问题:运行——没有并行的会产生相同的结果(即,测试应按顺序运行。相同是指@Test
中的代码相同,这由于某种原因导致错误消失。)
package com.example.deadlock
import org.springframework.jdbc.core.JdbcTemplate
class Repository constructor(private val template: JdbcTemplate) {
fun findAll(): List<String> =
template.queryForList("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='jfdksaiufd'", String::class.java)
}
package com.example.deadlock
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping(path = ["/foo"],
produces = [MediaType.APPLICATION_JSON_UTF8_VALUE])
class Controller(private val repository: Repository) {
@GetMapping
fun banks(): List<String> {
val banks = repository.findAll()
return emptyList()
}
}
package com.example.deadlock
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
@SpringBootTest(classes = [Application::class])
@AutoConfigureMockMvc
class EndpointTest @Autowired constructor(private val mockMvc: MockMvc) {
@Test
fun empty() {
val mvcRequest = MockMvcRequestBuilders.get("/foo").accept(MediaType.APPLICATION_JSON_UTF8)
mockMvc.perform(mvcRequest)
.andExpect(status().isOk)
.andExpect(content().string("[]"))
}
}
package com.example.deadlock
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import kotlin.test.assertEquals
@SpringBootTest(classes = [Application::class])
class RepositoryTest @Autowired constructor(private val repository: Repository) {
@Test
fun initialCount() {
assertEquals(0, repository.findAll().size)
}
}
buildscript {
ext {
kotlinVersion = "1.3.31"
springVersion = "2.1.5.RELEASE"
}
repositories {
mavenCentral()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springVersion}"
}
}
plugins {
id "org.jetbrains.kotlin.jvm" version "1.3.31"
id "org.springframework.boot" version "2.1.5.RELEASE"
id "idea"
}
apply plugin: "org.springframework.boot"
apply plugin: "io.spring.dependency-management"
group = "com.example.deadlock"
version = "0.0.1-SNAPSHOT"
description = "Deadlock with Spring and h2"
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
compileJava.options.encoding = "UTF-8"
tasks.withType(Test) {
useJUnitPlatform()
outputs.upToDateWhen {false}
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-reflect"
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework:spring-jdbc"
compile "com.h2database:h2"
// Test setups
testCompile "org.junit.jupiter:junit-jupiter-api"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
testCompile "org.springframework.boot:spring-boot-starter-test"
}