hibernate 使用带有Micronaut的GORM使用多个数据源时出现“找不到当前线程的会话”错误

bsxbgnwa  于 2022-11-14  发布在  Go
关注(0)|答案(1)|浏览(133)

我正在尝试使用具有多个数据源的GORM在Micronaut中构建应用程序。
Micronaut版本为3.6.2。
当我尝试获取以下错误的数据时:

org.springframework.dao.DataAccessResourceFailureException: Could not obtain current Hibernate Session; nested exception is org.hibernate.HibernateException: No Session found for current thread
    at org.grails.orm.hibernate.GrailsHibernateTemplate.getSession(GrailsHibernateTemplate.java:335)
    at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:284)
    at org.grails.orm.hibernate.GrailsHibernateTemplate.get(GrailsHibernateTemplate.java:364)
    at org.grails.orm.hibernate.AbstractHibernateGormStaticApi.get(AbstractHibernateGormStaticApi.groovy:120)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper.get(GormEntity.groovy:553)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper$get.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
    at com.example.domain.Book.get(Book.groovy)
    at com.example.service.$BookServiceImplementation.$tt__get(BookService.groovy)
    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.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1268)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1035)
    at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:1029)
    at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:1012)
    at org.codehaus.groovy.runtime.InvokerHelper.invokeMethodSafe(InvokerHelper.java:101)
    at com.example.service.$BookServiceImplementation$_get_closure1.doCall(BookService.groovy)
    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.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:274)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1035)
    at groovy.lang.Closure.call(Closure.java:412)
    at groovy.lang.Closure.call(Closure.java:428)

您可以在下面找到源代码:
Build.gradle

plugins {
    id("groovy") 
    id("com.github.johnrengelman.shadow") version "7.1.2"
    id("io.micronaut.application") version "3.5.3"
    id("io.micronaut.test-resources") version "3.5.3"
}

version = "0.1"
group = "com.example"

repositories {
    mavenCentral()
}

dependencies {

    implementation("io.micronaut:micronaut-http-client")
    implementation("io.micronaut:micronaut-jackson-databind")
    implementation("io.micronaut:micronaut-management")
    implementation("io.micronaut.beanvalidation:micronaut-hibernate-validator")
    implementation("io.micronaut.groovy:micronaut-hibernate-gorm")
    implementation("io.micronaut.groovy:micronaut-runtime-groovy")
    implementation("io.micronaut.sql:micronaut-jdbc-hikari")
    compileOnly("io.micronaut:micronaut-http-validation")
    runtimeOnly("ch.qos.logback:logback-classic")
    runtimeOnly("mysql:mysql-connector-java")
    runtimeOnly("org.apache.tomcat:tomcat-jdbc")
    implementation("io.micronaut:micronaut-validation")
    annotationProcessor "io.micronaut:micronaut-inject-java"
    annotationProcessor "io.micronaut:micronaut-inject-groovy"
    implementation("io.micronaut.security:micronaut-security-jwt")
}

application {
    mainClass.set("com.example.Application")
}
java {
    sourceCompatibility = JavaVersion.toVersion("1.8")
    targetCompatibility = JavaVersion.toVersion("1.8")
}

graalvmNative.toolchainDetection = false
micronaut {
    runtime("netty")
    testRuntime("junit5")
    processing {
        incremental(true)
        annotations("com.example.*")
    }
    testResources {
        additionalModules.add("jdbc-mysql")
    }
}

控制器

package com.example.web.controller

import com.example.domain.Book
import com.example.service.BookService
import grails.gorm.transactions.Transactional
import io.micronaut.http.HttpResponse
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.PathVariable
import io.micronaut.security.annotation.Secured
import io.micronaut.security.rules.SecurityRule
import jakarta.inject.Inject

@Controller("/book")
@Secured(SecurityRule.IS_ANONYMOUS)
class BookController {

    @Inject
    BookService bookService

    @Get(uri = '/{id}', produces = MediaType.APPLICATION_JSON)
    @Transactional
    HttpResponse<?> getBook(@PathVariable Long id) {
        Book book = bookService.get(id)
        HttpResponse.ok(booko)
    }

}

服务

package com.example.service

import com.example.domain.Book
import grails.gorm.services.Service

@Service(Book)
interface BookService {

    Book get(Serializable id)

}

package com.example.domain

import grails.gorm.annotation.Entity

@Entity
class Book {

    String name
    int pages

    static mapping = {
        version false
        datasource 'olap'
    }

}

更新:

我也试过下面这样的服务,但没有成功。

package com.example.service

import com.example.domain.Book
import grails.gorm.transactions.Transactional
import jakarta.inject.Singleton

@Transactional
@Singleton
class BookService {

    Book get(Long bookId) {
        Book.findById(bookId)
    }

}

更新2:

只有在访问第二个数据源时才会出现“找不到当前线程的会话”错误。此错误似乎与多个数据源有关。
有人能用GORM为多个数据源提供正确的配置吗?

syqv5f0l

syqv5f0l1#

在这里,只有当我们尝试访问配置了第二个数据源的域时,才会发生问题。
在上面的示例中,Book域配置了名为olap的第二个数据源。

static mapping = {
    version false
    datasource 'olap'
}

但在服务中,我只添加了@Transactional。这意味着服务使用默认数据源。但Book域有olap数据源。因此,我们收到No session found错误。
为了解决这个问题,我将@Transactional(connection="olap")添加到访问Book域的方法中。以致域和服务都将使用相同数据源。
修复后,我的服务等级如下所示:

package com.example.service

import com.example.domain.Book
import grails.gorm.transactions.Transactional
import jakarta.inject.Singleton

@Transactional
@Singleton
class BookService {

    @Transactional(connection="olap")
    Book get(Long bookId) {
        Book.findById(bookId)
    }

}

相关问题