标签: spring-data-r2dbc

使用 r2dbc 的基于多租户模式的应用程序

我正在开发一个多租户反应式应用程序,使用 Spring-Webflux + Spring-data-r2dbc 和 r2dbc 驱动程序连接到 Postgresql 数据库。多租户部分是基于模式的:每个租户一个模式。因此,根据上下文(例如用户登录),请求将命中数据库的特定架构。

我正在努力研究如何在 r2dbc 中实现这一点。理想情况下,这将是 Hibernate 使用MultiTenantConnectionProvider 的方式(参见示例 16.3)。

到目前为止我发现了什么以及我做了什么:

我可能需要找到一种方法来覆盖它,以便从上下文而不是配置中动态获取模式?

  • 否则,我可以尝试将请求中的架构指定为表前缀:

        String s = "tenant-1";
        databaseClient.execute("SELECT * FROM \"" + s + "\".\"city\"")
                .as(City.class)
                .fetch()
                .all()
    
    Run Code Online (Sandbox Code Playgroud)

但我不能再使用 SpringData,或者我需要重写每个请求以将租户作为参数传递。

任何提示/帮助表示赞赏:)

multi-tenant spring-data-r2dbc r2dbc

8
推荐指数
1
解决办法
3455
查看次数

如何与 Spring Data R2DBC 映射 1:1 关系?

我有这些简化的表格

CREATE TABLE address(
    id VARCHAR(36) NOT NULL PRIMARY KEY,
    zip VARCHAR(5) NOT NULL,
    city VARCHAR(32) NOT NULL
)
CREATE TABLE customer(
    id VARCHAR(36) NOT NULL PRIMARY KEY,
    name VARCHAR(32) NOT NULL,
    address_fk VARCHAR(36) NOT NULL,
    FOREIGN KEY (address_fk) REFERENCES address(id)
)
Run Code Online (Sandbox Code Playgroud)

以及这些简化的 Kotlin 类:

data class Address(val id: String, val zip: String, val city: String)
data class Kunde(val id: String?, val name: String, val address: Address)
Run Code Online (Sandbox Code Playgroud)

当我使用@Column(address_fk)该属性时address,我得到一个消息,没有找到从到 的ConverterNotFoundException转换器。而且看起来也不合适。任何提示表示赞赏。StringAddress@MappedCollection@Column

spring-data spring-data-r2dbc

7
推荐指数
1
解决办法
8969
查看次数

如何在 r2dbc-postgresql 中使用 EnumCodec

我试图使用最新版本的 r2dbc-postgresql (0.8.4) 中的 EnumCodec,但没有成功,我想知道你是否可以帮助我。

\n

我还使用 spring-data-r2dbc 版本 1.1.1。

\n

我从 GitHub 中获取了确切的示例,并在 Postgres 中创建了一个枚举类型 \xe2\x80\x9cmy_enum\xe2\x80\x9d,\n 和一个包含 \xe2\ 的表 \xe2\x80\x9csample_table\xe2\x80\x9d x80\x98name\xe2\x80\x99 (文本)和 \xe2\x80\x98value\xe2\x80\x99 (my_enum)。

\n

然后我按照例子做了:

\n

SQL:

\n
CREATE TYPE my_enum AS ENUM ('FIRST', 'SECOND');\n
Run Code Online (Sandbox Code Playgroud)\n

Java模型:

\n
enum MyEnumType {\n  FIRST, SECOND;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

编解码器注册:

\n
PostgresqlConnectionConfiguration.builder()\n.codecRegistrar(EnumCodec.builder().withEnum("my_enum", MyEnumType.class).build());\n
Run Code Online (Sandbox Code Playgroud)\n

我使用 DatabaseClient 来与数据库通信。\n我尝试使用两种方法插入:

\n
databaseClient.insert().into(SampleTable.class)\n.using(sampleTable).fetch().rowsUpdated();\n
Run Code Online (Sandbox Code Playgroud)\n

或者:

\n
databaseClient.insert().into("sample_table")\n.value("name", sampleTable.getName())\n.value("value", sampleTable.getValue())\n.then();\n
Run Code Online (Sandbox Code Playgroud)\n

其中 SampleTable 是:

\n
@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Builder\n@Table("sample_table")\n@JsonIgnoreProperties(ignoreUnknown = true)\n@JsonInclude(JsonInclude.Include.NON_NULL)\npublic class SampleTable implements Serializable {\n   private String name;\n   @Column("value")\n   @JsonProperty("value")\n …
Run Code Online (Sandbox Code Playgroud)

postgresql enums spring spring-data-r2dbc r2dbc

7
推荐指数
1
解决办法
6306
查看次数

使用 r2dbc 和 flyway 在 Spring Boot 应用程序中设置 h2

我正在玩 Spring Boot 和称为 r2dbc 的反应式 jdbc 驱动程序。在我的主应用程序中,我使用 Postgres 作为数据库,现在我想使用 h2 进行测试。Flyway 迁移正在与设置一起工作,但是当 Spring 应用程序能够插入记录时。

这是我的设置和代码

@SpringBootTest
class CustomerRepositoryTest {

    @Autowired
    CustomerRepository repository;

    @Test
    void insertToDatabase() {
        repository.saveAll(List.of(new Customer("Jack", "Bauer"),
                new Customer("Chloe", "O'Brian"),
                new Customer("Kim", "Bauer"),
                new Customer("David", "Palmer"),
                new Customer("Michelle", "Dessler")))
                .blockLast(Duration.ofSeconds(10));
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误

 :: Spring Boot ::        (v2.3.4.RELEASE)

2020-10-14 15:59:18.538  INFO 25279 --- [           main] i.g.i.repository.CustomerRepositoryTest  : Starting CustomerRepositoryTest on imalik8088.fritz.box with PID 25279 (started by imalik in /Users/imalik/code/private/explore-java/spring-example)
2020-10-14 15:59:18.540  INFO 25279 --- [           main] …
Run Code Online (Sandbox Code Playgroud)

java flyway spring-boot spring-data-r2dbc

7
推荐指数
2
解决办法
2764
查看次数

Spring boot r2dbc transactional:注释哪个方法

我使用 spring-boot 2.4.2 和 webflux 连接到 postgres 数据库。@Transactional我在使用时观察到一种我不明白的行为。

为了展示该行为,我创建了一个示例应用程序,尝试将行添加到两个表中;表“a”和表“b”。对表“a”的插入预计会因重复键冲突而失败。鉴于使用了事务性,我预计不会将任何行添加到表“b”中。

但是,根据我使用的注释方法,@Transactional我会得到不同的结果。

如果我注释控制器方法,一切都会按预期工作,并且不会向表 B 添加任何行。

    @PostMapping("/")
    @Transactional
    public Mono<Void> postEntities() {
        return demoService.doSomething();
    }
Run Code Online (Sandbox Code Playgroud)

演示服务如下所示:

    public Mono<Void> doSomething() {
        return internal();
    }


    public Mono<Void> internal() {
        Mono<EntityA> clash = Mono.just(EntityA.builder().name("clash").build()).flatMap(repositoryA::save);
        Mono<EntityB> ok = Mono.just(EntityB.builder().name("ok").build()).flatMap(repositoryB::save);
        return ok.and(clash);
    }
Run Code Online (Sandbox Code Playgroud)

如果我将@Transactional注释从控制器移至doSomething(),那么事务仍然按预期工作。但是,如果我将@Transactional注释移至internal(),则事务将无法按预期工作。一行被添加到表“b”中。

此示例的完整代码在这里:https ://github.com/alampada/pg-spring-r2dbc-transactional

我不明白为什么将注释移至internal()方法会导致事务处理出现问题。您能解释一下吗?

spring-boot spring-data-r2dbc r2dbc r2dbc-postgresql

7
推荐指数
1
解决办法
3140
查看次数

我应该在基于控制器的 Spring Webflux 服务中使用 Flow 作为返回类型吗

我正在尝试在我们的下一个 Spring Boot 服务中使用 Kotlincoroutinesspring-data-r2dbc( )。databaseClient我已经熟悉这两个概念,但当我们更深入地研究实现细节时,我开始问自己这个问题。

在我看到的大多数示例中,每个返回某种集合的端点在迁移到反应式方法时都会返回 Flow。

虽然没有其他(非阻塞)方法可以使用Mono/来完成此操作Flux,但由于我们想将订阅移交给 engine( Webflux),但情况与 Kotlin 非常不同Flows。Flow 的终端操作是挂起的,这使得它们本质上是非阻塞的。这意味着我可以在获取 Flow 的时间和地点以非阻塞方式终止 Flow,然后继续执行常规操作List

当然,可能存在更复杂的场景,包括底层热门发布者、反应式传输/协议等,但就我而言,这是一个非常传统的服务。我们决定使用反应式方法的唯一原因是它受 IO 限制:对于每个 API 调用,我们需要通过 HTTP/REST 从多个其他服务获取数据,然后执行一些数据库查询,然后返回组合结果。List所以,问题是:如果我可以当场将 Flow 简化为常规层(例如在存储库中),那么将 Flow 分散到多个应用程序层(控制器、服务、存储库)中是否有意义:

    suspend fun findByEvent(id: String): List<MyEntity> =
        databaseClient.execute(MY_QUERY)....all().asFlow().toList()
Run Code Online (Sandbox Code Playgroud)

这样我的应用程序层的其余部分甚至不会知道任何事情Flow(无论如何,整个调用链将保持可挂起状态)?

kotlin spring-boot spring-webflux spring-data-r2dbc kotlin-coroutines

6
推荐指数
0
解决办法
626
查看次数

spring-r2dbc 中忽略更新字段

我正在使用 spring r2dbc 和 ReactiveCrudRepository,我有一个在生成更新查询时需要忽略的字段

@Data
@Table(PRODUCT_TABLE)
public class ProductEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) // Id generated by database
    private Integer id;

    private Integer companyId;

    @Column(insertable=false, updatable = false)
    private String companyName;

    @NotBlank
    private String name;

    private VerificationStatus verificationStatus;
}
Run Code Online (Sandbox Code Playgroud)

如何在更新查询中忽略companyName。我可以使用 @column 在插入查询中忽略它,但它不适用于更新

java spring-webflux spring-data-r2dbc r2dbc

6
推荐指数
1
解决办法
4432
查看次数

在 Spring Boot 中使用持久性 Quartz 调度程序,同时使用 R2DBC

我一直在尝试让 Quartz 在 Spring Boot 中使用 R2DBC 时工作。到目前为止,我还没有弄清楚如何做到这一点。这是因为当创建 JDBC 数据源时,它会尝试初始化我的 R2DBC 存储库,但它无法执行此操作,因为 R2DBC 本质上是反应性的,而 JDBC 本质上是阻塞的。

我考虑过的替代方案

  • 对 Quartz 使用内存数据库---这存在 Quartz 不再持久化作业的问题。我可以通过使用 R2DBC 单独跟踪作业,然后在启动时重新注册所有作业来解决这个问题,但这似乎会重复 Quartz 的许多功能。
  • 查找基于 R2DBC 的调度程序——没有。

相关 Gradle 依赖项

dependencies {
    implementation("io.projectreactor.netty:reactor-netty:0.9.7.RELEASE")

    implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
    implementation("org.springframework.boot:spring-boot-starter-quartz")
    implementation("org.springframework.boot:spring-boot-starter-data-jdbc")

    runtimeOnly("com.h2database:h2")
    implementation("io.r2dbc:r2dbc-h2:0.8.3.RELEASE")
}
Run Code Online (Sandbox Code Playgroud)

我当前的石英配置

@Configuration
class QuartzConfig {
    @Bean
    @QuartzDataSource
    fun dataSource(props: DataSourceProperties): DataSource {
        return props.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
    }
}
Run Code Online (Sandbox Code Playgroud)

相关R2DBC配置:

abstract class R2DbcConfiguration : AbstractR2dbcConfiguration() {
    override fun getCustomConverters(): MutableList<Any> {
        return mutableListOf(
            // some custom converters
        )
    }

    @Bean
    fun connectionFactoryInitializer( …
Run Code Online (Sandbox Code Playgroud)

spring-jdbc kotlin spring-boot quartz spring-data-r2dbc

6
推荐指数
0
解决办法
1226
查看次数

Spring Data R2DBC PostgreSQL 不使用 UUID @Id 保存新记录

我有一个简单的实体,由两个 UUID 组成:

\n
@Table("library")\npublic class LibraryDao {\n    @Id\n    private UUID id;\n    @NonNull\n    private UUID ownerId;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我在 PostgreSQL 中有一个对应的表:

\n
CREATE TABLE IF NOT EXISTS library (id UUID PRIMARY KEY, owner_id UUID NOT NULL);\n
Run Code Online (Sandbox Code Playgroud)\n

我正在使用正确的 R2DBC 驱动程序(io.r2dbc:r2dbc-postgresqlorg.postgresql:postgresql)。

\n

至此,一切正常。我的应用程序运行。但是\xe2\x80\xa6

\n

因为 PostgreSQL 至少根据文档 \xe2\x80\x93 没有 UUID 自动生成功能,所以我在创建新实例时设置了 id LibraryDao

\n

但是,当我save在存储库中调用该方法时,出现异常:Failed to update table [library]. Row with Id [0ed4d7c0-871a-4473-8997-4c9c1ec67a00] does not exist.

\n

似乎save被解释为,如果它不存在则update不会回退。insert

\n …

java postgresql spring-data-r2dbc

6
推荐指数
1
解决办法
7663
查看次数

在 Spring Data R2DBC 中设计一对一和一对多关系

我正在探索在使用 Spring Data R2DBC 时设计一对一和一对多关系时可能的想法。

由于 Spring Data R2DBC 本身仍然不支持关系,因此仍然需要我们自己处理这些关系(与 Spring Data JDBC 不同)。

我想象的是,当涉及到一对一映射时,实现可能如下所示:

@Table("account")
public class Account {
    
    @Id
    private Long id;
    
    @Transient // one-to-one
    private Address address;
    }
Run Code Online (Sandbox Code Playgroud)
@Table("address")
public class Address {
    
    @Id
    private Integer id;
}
Run Code Online (Sandbox Code Playgroud)

而数据库模式定义如下:

--address
CREATE TABLE address
(
    id                  SERIAL PRIMARY KEY
)
    
--account
CREATE TABLE account
(
    id                     SERIAL PRIMARY KEY,
    address_id             INTEGER REFERENCES address(id)
)
Run Code Online (Sandbox Code Playgroud)

由于该Account对象是我的聚合根,我想我应该Address按照 Jens Schaduer 的建议加载该对象:

聚合是形成一个单元的一组对象,它应该始终保持一致。此外,它应该始终被持久化(并加载)在一起。来源:Spring Data JDBC、参考资料和聚合

这让我想到,在像这样的一对一关系的情况下,我实际上应该Account …

spring-boot spring-data-jdbc spring-data-r2dbc r2dbc

6
推荐指数
1
解决办法
5503
查看次数