使用多个数据源时出现错误"No Session found for current thread"使用 gorm 和 micronaut



我正试图使用具有多个数据源的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为多个数据源提供正确的配置吗。

这里只有当我们尝试访问使用第二个数据源配置的域时,才会出现问题。

在上面的示例中,Book域配置有称为olap的第二数据源。

static mapping = {
version false
datasource 'olap'
}

但在服务中,我只添加了@Transactional。这意味着服务使用默认数据源。但Book域具有olap数据源。正因为如此,我们得到了No session found错误。

为了解决这个问题,我在访问Book域的方法中添加了@Transactional(connection="olap")。使得域&服务将使用相同的数据源。

修复后,我的服务类如下所示:

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

相关内容

最新更新