Quarkus应用中基于原生SQL的方案搭建方法咨询
Quarkus下替代JDBI的原生SQL方案建议
针对你从Dropwizard转Quarkus、想要保留JDBI式原生SQL开发体验的需求,给你几个实用的落地方向:
1. 基于Quarkus Reactive Postgres Driver封装轻量映射层
Quarkus响应式驱动确实样板代码冗余,但可以自己封装一套简化工具,对齐JDBI的使用习惯:
- 写一个通用
SqlExecutor类,封装预编译语句创建、参数绑定逻辑,利用Mutiny.PgPool自动管理连接和语句缓存。 - 自定义和JDBI一致的
RowMapper接口,实现结果到实体的映射,直接支持Postgres JSONB、PostGIS等特性:
public interface RowMapper<T> { T map(Row row); } public class UserMapper implements RowMapper<User> { @Override public User map(Row row) { return new User( row.getInteger("id"), row.getString("username"), row.getJsonb("profile") // 直接处理Postgres JSONB类型 ); } }
- 封装通用查询方法,减少重复代码:
@ApplicationScoped public class SqlExecutor { private final Mutiny.PgPool pgPool; public SqlExecutor(Mutiny.PgPool pgPool) { this.pgPool = pgPool; } public <T> Uni<T> querySingle(String sql, RowMapper<T> mapper, Map<String, Object> params) { return pgPool.preparedQuery(sql) .execute(Tuple.of(params)) .onItem().transform(rowSet -> rowSet.iterator().hasNext() ? mapper.map(rowSet.iterator().next()) : null ); } }
- 事务直接用Quarkus的
@ReactiveTransactional注解,配合Mutiny的Uni链式调用即可实现事务控制。
2. 直接使用Quarkus JDBI扩展(核心功能可用)
虽然扩展处于早期阶段,但JDBI的核心特性它都已支持:
- 注解式SQL、
@Bind参数绑定、@UseRowMapper结果映射这些用法和原生JDBI完全一致,你原来的Dao代码几乎可以直接复用:
@RegisterRowMapper(UserMapper.class) public interface UserDao { @SqlQuery("SELECT * FROM users WHERE id = :id") User getUser(@Bind("id") int id); @SqlUpdate("INSERT INTO users(id, username) VALUES(:id, :username)") @Transactional void insertUser(@BindBean User user); }
- 缺失的文档可以直接参考JDBI官方核心文档,因为Quarkus扩展只是做了框架集成,核心逻辑还是JDBI原生实现。
- 遇到问题可以去Quarkus的GitHub仓库搜已有issue,不少常见问题已经有社区给出的解决方案。
3. 用Quarkus SQL Client配合自定义映射
Quarkus官方主推的SQL Client(阻塞/响应式双版本),优化后也能接近JDBI的开发体验:
- 开启预编译语句缓存配置,减少重复编译开销:在
application.properties中添加quarkus.datasource.sql-client.prepared-statement-cache-size=20。 - 结果映射可以用Quarkus自带的
RowMapper,或者用MapStruct自动生成映射代码,避免手动编写样板:
@Mapper(componentModel = "cdi") public interface UserRowMapper extends RowMapper<User> { @Mapping(source = "profile", target = "profile") User map(Row row); }
- 批处理用SQL Client的
batchAPI简化实现:
public Uni<Void> batchInsertUsers(List<User> users) { return pgPool.preparedQuery("INSERT INTO users(id, username) VALUES($1, $2)") .executeBatch(users.stream() .map(user -> Tuple.of(user.getId(), user.getUsername())) .collect(Collectors.toList())) .onItem().ignore(); }
内容的提问来源于stack exchange,提问作者Arie
相关产品推荐
相关产品推荐

