Spring boot Springboot和H2关闭死锁

Spring 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

目前,我能够在使用h2和spring引导的组合时创建死锁。外面有很多问题,看起来有点类似,但显然它们已经解决了,我不完全确定是Spring还是h2做了一些奇怪的事情

首先对死锁进行visualvm跟踪(滚动至底部查看锁):

RepositoryTest.kt

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"
}