Ошибка при подключении к jpa с использованием библиотеки micronaut-data-hibernate-jpa

Я хочу использовать JPA для микронавта. Для этого я используюio.micronaut.data:micronaut-data-hibernate-jpa:1.0.0.M1библиотека. Всякий раз, когда я запускаю свое приложение и попадаю в конечную точку для получения данных, я получаю следующую ошибку:

{
    message: "Internal Server Error: No backing RepositoryOperations configured for repository. Check your configuration and try again"
} 

Я попытался найти ошибки, но не нашел. Прикрепляю сюда свои файлы. Пожалуйста помоги.

build.gradle

plugins {
    id "net.ltgt.apt-eclipse" version "0.21"
    id "com.github.johnrengelman.shadow" version "5.0.0"
    id "application"
}



version "0.1"
group "micronaut.test"

repositories {
    mavenCentral()
    maven { url "https://jcenter.bintray.com" }
}

configurations {
    // for dependencies that are needed for development only
    developmentOnly 
}

dependencies {
    annotationProcessor platform("io.micronaut:micronaut-bom:$micronautVersion")
    annotationProcessor "io.micronaut:micronaut-inject-java"
    annotationProcessor "io.micronaut:micronaut-validation"
    annotationProcessor "org.projectlombok:lombok:1.16.20"
    annotationProcessor 'io.micronaut.data:micronaut-data-processor:1.0.0.M1'

    implementation platform("io.micronaut:micronaut-bom:$micronautVersion")
    compile 'io.micronaut.data:micronaut-data-hibernate-jpa:1.0.0.M1'
    implementation "io.micronaut:micronaut-inject"
    implementation "io.micronaut:micronaut-validation"
    implementation "io.micronaut:micronaut-runtime"
    implementation "io.micronaut:micronaut-http-server-netty"
    implementation "io.micronaut:micronaut-http-client"
    implementation 'nl.topicus:spanner-jdbc:1.1.5'



    runtimeOnly "ch.qos.logback:logback-classic:1.2.3"
    testAnnotationProcessor platform("io.micronaut:micronaut-bom:$micronautVersion")
    testAnnotationProcessor "io.micronaut:micronaut-inject-java"
    testImplementation "org.junit.jupiter:junit-jupiter-api"
    testCompile "org.junit.jupiter:junit-jupiter-engine:5.1.0"
    testImplementation "io.micronaut.test:micronaut-test-junit5"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
}

test.classpath += configurations.developmentOnly

mainClassName = "micronaut.test.Application"
// use JUnit 5 platform
test {
    useJUnitPlatform()
}
tasks.withType(JavaCompile){
    options.encoding = "UTF-8"
    options.compilerArgs.add('-parameters')
}

shadowJar {
    mergeServiceFiles()
}

run.classpath += configurations.developmentOnly
run.jvmArgs('-noverify', '-XX:TieredStopAtLevel=1', '-Dcom.sun.management.jmxremote')

Репозиторий:

package micronaut.test.repo;

import io.micronaut.data.annotation.Repository;
import io.micronaut.data.repository.CrudRepository;
import micronaut.test.entity.Partner;

@Repository
public interface PartnerRepository extends CrudRepository<Partner,Integer> {
}

Обслуживание:

package micronaut.test.service;


import micronaut.test.entity.Partner;
import micronaut.test.repo.PartnerRepository;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;

@Singleton
public class SpannerService {
    private PartnerRepository partnerRepository;

    @Inject
    public SpannerService(PartnerRepository partnerRepository) {
        this.partnerRepository = partnerRepository;
    }

    public List<Partner> getPartners() {
        return (List<Partner>) partnerRepository.findAll();
    }
}

Контроллер:

package micronaut.test.controller;

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
import micronaut.test.entity.Partner;
import micronaut.test.service.SpannerService;

import javax.inject.Inject;
import java.util.List;

@Controller("/micronaut")
public class MainController {

    private SpannerService spannerService;

    @Inject
    public MainController(SpannerService spannerService) {
        this.spannerService = spannerService;
    }

    @Get("/data")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Partner> getPartners() {
        return spannerService.getPartners();
    }

}

трассировки стека:

io.micronaut.context.exceptions.ConfigurationException: No backing RepositoryOperations configured for repository. Check your configuration and try again
        at io.micronaut.data.intercept.DataIntroductionAdvice.findInterceptor(DataIntroductionAdvice.java:108)
        at io.micronaut.data.intercept.DataIntroductionAdvice.intercept(DataIntroductionAdvice.java:76)
        at io.micronaut.aop.MethodInterceptor.intercept(MethodInterceptor.java:40)
        at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:150)
        at micronaut.test.repo.PartnerRepository$Intercepted.findAll(Unknown Source)
        at micronaut.test.service.SpannerService.getPartners(SpannerService.java:22)
        at micronaut.test.controller.MainController.getPartners(MainController.java:32)
        at micronaut.test.controller.$MainControllerDefinition$$exec2.invokeInternal(Unknown Source)
        at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:144)
        at io.micronaut.context.DefaultBeanContext$BeanExecutionHandle.invoke(DefaultBeanContext.java:2792)
        at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:235)
        at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:122)
        at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$19(RoutingInBoundHandler.java:1408)
        at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:71)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.Flowable.subscribe(Flowable.java:14865)
        at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.Flowable.subscribe(Flowable.java:14865)
        at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.internal.operators.flowable.FlowableSwitchIfEmpty.subscribeActual(FlowableSwitchIfEmpty.java:32)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.Flowable.subscribe(Flowable.java:14865)
        at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.Flowable.subscribe(Flowable.java:14868)
        at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52)
        at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52)
        at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52)
        at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.Flowable.subscribe(Flowable.java:14865)
        at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.Flowable.subscribe(Flowable.java:14865)
        at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
        at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run(ExecutorScheduler.java:288)
        at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run(ExecutorScheduler.java:253)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [io.micronaut.data.operations.RepositoryOperations] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
        at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:1903)
        at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:582)
        at io.micronaut.data.intercept.DataIntroductionAdvice.findInterceptor(DataIntroductionAdvice.java:105)
        ... 43 common frames omitted

2 ответа

Решение

В настоящее время Micronaut из коробки поддерживает только поставщиков источников данных Tomcat JDBC, Apache DBCP2 и Hikari (см. https://micronaut-projects.github.io/micronaut-sql/latest/guide/).

Вы можете добавить эту строку в свой build.gradle, который добавляет реализацию поставщика Tomcat JDBC Data Source в ваш проект:

runtime "io.micronaut.configuration:micronaut-jdbc-tomcat"

Или вы можете выбрать другую реализацию, например Apache DBCP2:

runtime "io.micronaut.configuration:micronaut-jdbc-dbcp"

Или Хикари:

runtime "io.micronaut.configuration:micronaut-jdbc-hikari"

За nl.topicus:spanner-jdbc поставщик источника данных, вы должны реализовать свой собственный DatasourceFactory а также DatasourceConfiguration для Микронавта потому что пока никого нет.

Вы можете вдохновить себя io.micronaut.configuration:micronaut-jdbc-tomcat. Источники здесь: https://github.com/micronaut-projects/micronaut-sql/tree/master/jdbc-tomcat/src/main/java/io/micronaut/configuration/jdbc/tomcat

Например DatasourceFactory тогда может выглядеть так:

@Factory
public class DatasourceFactory implements AutoCloseable {
    private static final Logger LOG = LoggerFactory.getLogger(DatasourceFactory.class);
    private List<nl.topicus.jdbc.CloudSpannerDataSource> dataSources = new ArrayList<>(2);

    private final DataSourceResolver dataSourceResolver;

    /**
     * Default constructor.
     * @param dataSourceResolver The data source resolver
     */
    public DatasourceFactory(@Nullable DataSourceResolver dataSourceResolver) {
        this.dataSourceResolver = dataSourceResolver == null ? DataSourceResolver.DEFAULT : dataSourceResolver;
    }

    /**
     * @param datasourceConfiguration A {@link DatasourceConfiguration}
     * @return An Apache Tomcat {@link DataSource}
     */
    @Context
    @EachBean(DatasourceConfiguration.class)
    public DataSource dataSource(DatasourceConfiguration datasourceConfiguration) {
        nl.topicus.jdbc.CloudSpannerDataSource ds = new nl.topicus.jdbc.CloudSpannerDataSource();
        ds.setJdbcUrl(datasourceConfiguration.getJdbcUrl());
        ...
        dataSources.add(ds);
        return ds;
    }

    @Override
    @PreDestroy
    public void close() {
        for (nl.topicus.jdbc.CloudSpannerDataSource dataSource : dataSources) {
            try {
                dataSource.close();
            } catch (Exception e) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Error closing data source [" + dataSource + "]: " + e.getMessage(), e);
                }
            }
        }
    }
}

В любом случае вы все равно можете использовать Google Cloud Spanner DB с поставщиками источников данных, такими как Hikari и Apache DBCP2. Например:

runtime 'nl.topicus:spanner-jdbc:1.1.5'
runtime "io.micronaut.configuration:micronaut-jdbc-hikari"

Первая строка добавляет драйвер JDBC, а вторая строка добавляет поставщика источника данных, который будет использовать spanner-jdbc Драйвер JDBC.

Известно, что Google Cloud Spanner использует другой диалект, чем другие базы данных для Hibernate ORM. Я думаю, что этот диалект довольно новый. Взгляните на этот репозиторий 1. Может быть, это будет полезно для вас, не обязательно для решения вашей текущей проблемы, но даст вам другую перспективу.

Другие вопросы по тегам