如何通过JOOQ生成支持findById返回Optional类型的DAO
jOOQ DAO生成Optional返回查询方法的可行方案
存在两种成熟的落地方式,都可以实现省略手动空校验的需求:
方案1:通用DAO接口扩展(推荐,无侵入,无需修改生成逻辑)
不需要调整jOOQ的代码生成器核心逻辑,只需要定义通用父接口,配置生成的DAO自动继承即可:
- 定义通用基础DAO接口
public interface BaseDao<ID, E> { // 匹配jOOQ原生DAO的findById方法签名 E findById(ID id); // 默认实现Optional包装的查询方法 default java.util.Optional<E> findOptionalById(ID id) { return java.util.Optional.ofNullable(findById(id)); } }
- 调整jOOQ代码生成配置,让所有生成的DAO自动实现该接口,以Maven插件配置为例:
<generator> <strategy> <matchers> <daoInterfaces> <daoInterface> <expression>.*</expression> <daoImplements>com.your.common.package.BaseDao</daoImplements> </daoInterface> </daoInterfaces> </matchers> </strategy> </generator>
配置完成后重新生成代码,所有DAO都会自带findOptionalById方法,可直接使用你期望的写法:
var entity = dao.findOptionalById(id) .orElseThrow(() -> new SpecificRuntimeException());
方案2:自定义代码生成器,生成内置Optional方法
如果不想新增父接口,可以通过继承jOOQ默认的Java代码生成器,在DAO生成阶段自动插入findOptionalById方法:
import org.jooq.codegen.JavaGenerator; import org.jooq.codegen.JavaWriter; import org.jooq.meta.TableDefinition; public class OptionalDaoGenerator extends JavaGenerator { @Override protected void generateDaoClassBody(TableDefinition table, JavaWriter out) { super.generateDaoClassBody(table, out); // 仅当表有单主键时生成该方法 if (table.getPrimaryKey() == null || table.getPrimaryKey().getColumns().size() != 1) { return; } // 获取主键类型、实体类类型 String pkType = getType(table.getPrimaryKey().getColumns().get(0).getType()); String entityType = getTableType(table); // 写入findOptionalById方法 out.println("public java.util.Optional<%s> findOptionalById(%s id) {", entityType, pkType); out.println(" return java.util.Optional.ofNullable(findById(id));"); out.println("}"); } }
之后在代码生成插件配置中,将生成器类指定为你自定义的OptionalDaoGenerator全类名即可。
注意事项
不建议直接修改原生findById方法的返回值为Optional,会破坏jOOQ原生DAO的接口规范,后续版本升级容易出现兼容问题,新增单独的findOptionalById是更稳妥的方案。
内容的提问来源于stack exchange,提问作者Alex Korotkov
相关产品推荐
相关产品推荐

