R2DBC响应式数据库访问与JDBC对比
解释R2DBC(Reactive Relational Database Connectivity)的架构原理,对比其与JDBC的差异、支持的数据库种类、以及如何在Spring Data R2DBC中实现响应式数据访问。
回答
专业代码师
1. R2DBC核心架构
- 接口提供者:
io.r2dbc.spi.ConnectionFactory - 连接工厂:创建响应式数据库连接
ConnectionFactory factory = ConnectionFactories.get( "r2dbcs:mysql://localhost:3306/db"); - 核心接口:
ConnectionFactory→Publisher<? extends Connection>Connection→Publisher<? extends Result>Result→Publisher<? extends T>Batch→Publisher<? 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一级缓存