【问题标题】:Adding resources to classpath in kotlin/java/spring boot, using gradle as build tool将资源添加到 kotlin/java/spring boot 中的类路径,使用 gradle 作为构建工具
【发布时间】:2020-02-14 13:47:18
【问题描述】:

我正在尝试将 import.sql 从资源添加到类路径,以便它由休眠加载,并且在应用程序启动时将一些测试数据导入数据库。

我正在使用带有以下插件的 kotlin 和 gradle:

  • jvm
  • plugin.spring
  • plugin.jpa
  • org.springframework.boot
  • io.spring.dependency-management

从 IntelliJ 运行应用程序(bootRun 任务)时,资源位于 build/resources/main,java 类位于 build/classes/java/main。因此,当休眠尝试加载 import.sql 时找不到它,因为 java 类路径位于 build/classes/java/main 中(尝试运行 getResources("") 并返回该文件夹)。生成的文件夹结构、application.properties 和 gradle build 可以在下面找到。

application.properties

logging.level.org.hibernate.*=TRACE
logging.level.org.hibernate.SQL=trace
spring.datasource.data=classpath://import.sql

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/console

build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

val kotlinVersion = "1.3.50"
val springBootVersion = "2.1.9.RELEASE"
val h2Version = "1.4.200"
val hibernateVersion = "5.4.6.Final"
val snippetsDir = "./build/generated-snippets"
val test = "./gradle/test"

group = "org.testkotlin"
version = "0.0.1-SNAPSHOT"

java{
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    gradlePluginPortal()
    mavenCentral()
}

extra["snippetsDir"] = file(snippetsDir)

plugins {
    idea
    kotlin("jvm") version "1.3.50"
    kotlin("plugin.spring") version "1.3.50"
    kotlin("plugin.jpa") version "1.3.50"
    id("org.springframework.boot") version "2.1.9.RELEASE"
    id("io.spring.dependency-management") version "1.0.8.RELEASE"
    id("org.asciidoctor.convert") version "1.5.8"
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-data-rest")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.hibernate:hibernate-core:$hibernateVersion")
    runtimeOnly("com.h2database:h2:$h2Version")
    annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

tasks.test {
    outputs.dir(snippetsDir)
}

tasks.asciidoctor {
    inputs.dir(snippetsDir)
    dependsOn(test)
}

tasks.bootRun {
    doFirst {
        classpath = files("$buildDir/classes/main", "$buildDir/resources/main")
    }
}

所以我的问题是:

  • 如何向类路径添加资源?
  • 是否可以修改bootRun 任务来执行此操作(doFirst 不是一个选项,因为任务依赖于预先不存在的classes/java)?
  • bootRun 或 gradle build 中是否有一些属性可以启用此功能?
  • 最终我怎样才能让休眠自动识别import.sql,而无需手动将其移动到build/classes/java/main

【问题讨论】:

    标签: java hibernate spring-boot gradle kotlin


    【解决方案1】:

    您正确定义了资源文件夹,带有 Spring Boot 插件的 Gradle 会自动将其添加到类路径中。如果这没有发生,Spring 也将无法加载您的 application.properties 文件,我认为它可以。

    我还假设您想使用 Hibernate 加载数据,因为如果您有一个名为 import.sql 的文件,这是默认行为。但只有当ddl-auto 属性设置为createcreate-drop,而你的设置为update 时,它才会这样做。

    您也可以让 Spring Boot 处理数据源初始化而不是 Hibernate,但它仍然只会在(重新)创建模式时发生,而不是仅在连接到它时发生。

    另外,即使这不是你的问题的原因,我不认为 Spring 中的类路径资源应该以斜杠为前缀,但至少不应该是两个 (classpath://import.sql)。

    【讨论】:

    • 必须刷新 gradle 依赖项,重新导入 gradle 项目,更改为 create 或 create-drop,然后它按预期工作,谢谢。
    【解决方案2】:

    首先,Spring Boot 中的资源应该放在src/main/resources 文件夹中,而不是build/classes/java/mainbuild 包是bootRun 任务的产物,每次运行它都会改变。

    展望春天documentation:

    Spring Boot 默认启用它并从标准位置 schema.sql 和 data.sql(在类路径的根目录中)加载 SQL。

    这意味着 Spring 在类路径(资源文件夹)的根目录中查找 import.sql 文件。在 IntelliJ 中它看起来像这样:

    【讨论】:

    • 在运行 gradle build 任务时,默认情况下将来自 src/main/resources 的资源复制到 build/resources/main - 我没有在那里手动复制它们。
    • 您还应该从 application.properties 中删除属性 spring.datasource.data=classpath://import.sql
    • 你在 Github 上有这个项目的存储库吗?我可以尝试克隆它并在本地运行它以查看问题所在。
    猜你喜欢
    • 2018-06-24
    • 2018-10-19
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多