Проблема с расширением приложения Spring WebFlux с помощью реактивного клиента БД: конфликтующие зависимости Maven?

У меня есть небольшое рабочее приложение Spring WebFlux, созданное на основе этого кода:

https://github.com/chang-chao/spring-webflux-reactive-jdbc-sample

Насколько я понял, это некая смесь чисто реактивного программирования и обычных блокирующих реляционных баз данных.

Теперь у меня есть задача добавить в приложение реактивного клиента БД. Я смотрел это руководство:

https://spring.io/guides/gs/accessing-data-r2dbc/

Но как только я добавил в свой pom.xml следующие зависимости:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-r2dbc</artifactId>
    <version>2.3.4.RELEASE</version>
</dependency>

<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-h2</artifactId>
    <version>0.8.4.RELEASE</version>
    <scope>runtime</scope>
</dependency>

мое РАБОЧЕЕ приложение не могло начать говорить, что не может найти bean-компонент репозитория с автоматическим подключением. Эта ошибка исчезла, как только я удалил две зависимости выше.

Первоначальный полный pom.xml РАБОЧЕГО приложения:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.freelance</groupId>
    <artifactId>studentlist</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>student-list</name>
    <description>Spring WebFlux application for managing students</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.3.4.RELEASE</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <version>3.3.10.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.200</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Я предполагаю, что некоторые зависимости конфликтуют друг с другом. Есть ли способ действительно использовать эти зависимости со всеми моими другими зависимостями, чтобы я мог следовать этому руководству?

Я не знаю, нужен ли Java-код приложения для этого вопроса, и если да, то какие. А пока я просто добавлю application.properties:

spring.h2.console.enabled=true
spring.h2.console.path=/h2_console

spring.datasource.url=jdbc:h2:~/studentlist
spring.datasource.platform=h2
spring.datasource.initialization-mode=always
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver

spring.jpa.generate-ddl=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true

logging.level.org.springframework=warn
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=trace
logging.level.org.hibernate.SQL=warn
logging.level.io.netty=warn

spring.datasource.maximum-pool-size=100

Добавляя любую из этих двух зависимостей, spring-boot-starter-data-r2dbc или же r2dbc-h2, без второго достаточно, чтобы вызвать эту ошибку:

2020-10-20 15:31:26.008  WARN 11580 --- [           main] onfigReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentController': Unsatisfied dependency expressed through field 'studentService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentService': Unsatisfied dependency expressed through field 'studentRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.freelance.studentlist.repository.StudentRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2020-10-20 15:31:26.123 ERROR 11580 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field studentRepository in com.freelance.studentlist.service.StudentServiceImpl required a bean of type 'com.freelance.studentlist.repository.StudentRepository' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.freelance.studentlist.repository.StudentRepository' in your configuration.


Process finished with exit code 1

Я удалил зависимость JPA и сейчас пытаюсь заставить все работать только с r2dbc.

Я полагаю, что мое application.properties больше не будет действительным. Не могли бы вы помочь мне изменить его? Я использую этот фрагмент кода из руководства:

public class R2DBCConfiguration extends AbstractR2dbcConfiguration {
    @Bean
    public H2ConnectionFactory connectionFactory() {
        return new H2ConnectionFactory(
                H2ConnectionConfiguration.builder()
                        .url("jdbc:h2:~/studentlist;DB_CLOSE_DELAY=-1;TRACE_LEVEL_FILE=4")
                        .username("sa")
                        .build());
    }
}

Я сильно подозреваю, что такие urlне действует для r2dbc. Что было бы действительной заменой для jdbc:h2:~/studentlist URL в случае r2dbc H2 (не в памяти, а только в локальной БД)?

Как мне изменить этот блок кода в application.properties? URL в частности!

**spring.datasource.url=jdbc:h2:~/studentlist**
spring.datasource.platform=h2
spring.datasource.initialization-mode=always
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver

Пожалуйста, помогите, если знаете! Не могу пока найти подходящий пример в Google...

1 ответ

Решение

В spring.datasource для традиционного источника данных Jdbc, для настройки соединения R2dbc используйте spring.r2dbcпрефикс вместо этого в Spring Boot application.properties.

Посмотрите мой пример Spring R2dbc, если вы новичок в Spring Data R2dbc, документацию в Readme.md.

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