CodeWalk

R2DBC响应式数据库访问与JDBC对比

作者:专业代码师 · 2026-05-30 12:55

解释R2DBC(Reactive Relational Database Connectivity)的架构原理,对比其与JDBC的差异、支持的数据库种类、以及如何在Spring Data R2DBC中实现响应式数据访问。

回答

专业代码师

1. R2DBC核心架构

  • 接口提供者io.r2dbc.spi.ConnectionFactory
  • 连接工厂:创建响应式数据库连接
    ConnectionFactory factory = ConnectionFactories.get(
        "r2dbcs:mysql://localhost:3306/db");
    
  • 核心接口
    • ConnectionFactoryPublisher<? extends Connection>
    • ConnectionPublisher<? extends Result>
    • ResultPublisher<? extends T>
    • BatchPublisher<? extends Result>

2. R2DBC vs JDBC | 特性 | JDBC | R2DBC | |------|------|------| | 模型 | 同步阻塞 | 异步响应式 | | 线程 | 每个请求独占一个线程 | EventLoop复用 | | 返回类型 | ResultSet | Flux / Mono | | 连接池 | HikariCP(阻塞) | 响应式连接池(r2dbc-pool) | | 事务 | Connection API | 响应式事务管理 |

3. Spring Data R2DBC示例

@Table("users")
public class User {
    @Id Long id;
    String name;
    String email;
}

public interface UserRepository extends ReactiveCrudRepository<User, Long> {
    Mono<User> findByName(String name);
    Flux<User> findByEmailEndingWith(String suffix);
}

// 使用
@Service
public class UserService {
    public Flux<User> searchUsers(String keyword) {
        return userRepository.findByNameContaining(keyword);
    }
}

4. 支持的数据库

  • ✅ PostgreSQL(r2dbc-postgresql)
  • ✅ MySQL/MariaDB(r2dbc-mysql)
  • ✅ H2(r2dbc-h2)
  • ✅ SQL Server(r2dbc-mssql)
  • ✅ Oracle(r2dbc-oracle)

5. 事务管理

@Transactional
public Mono<Void> transfer(Long from, Long to, BigDecimal amount) {
    return Mono.from(connectionFactory.create())
        .flatMapMany(conn -> 
            conn.createStatement("UPDATE account SET balance = balance - $1 WHERE id = $2")
                .bind(0, amount).bind(1, from)
                .execute()
                .flatMap(Result::getRowsUpdated)
        );
}

6. 限制

  • 不支持JPA(JPA是阻塞API)
  • 不支持@ManyToMany懒加载
  • 复杂关联查询需手动编写
  • 不支持Hibernate一级缓存