使用模型 API 创建普通 JOOQ SQL 查询

Creating a plain JOOQ SQL query using the Model API

我一直在使用 JOOQ,它似乎是一个非常有用的库,可以生成 SQL 查询。但是,我坚持动态生成它们。例如,下面是我想做的(注意,我只是想用它来做 SQL 构建而不生成任何代码)

DSLContext context = DSL.using(SQLDialect.DEFAULT);

List<Field<?>> select = getSelect(String fields ...); // gets the selection fields
Select query = create.select(select)
      .from(name("table"));

if(where)
   query = query.addWhere(Conditions...);
if(groupBy)
   query = query.groupBy(List<Field<?>> ...);
if(orderBy)
   query = query.orderBy(List<Field<?>> ...);

不幸的是,我只能找到一种方法来一步完成它们,如下所示:

query.select()
      .from(...)
      .where(...)
      .orderBy(...)
      .fetch();

如果 .where、.orderBy 可以接受 null,然后不将这些子句添加到 SQL(如果它们为 null),则上述内容可能会有用,但似乎这是不可能的。

这是我的问题:

有没有一种方法可以动态创建一个 SELECTION 查询,然后在不使用任何代码生成的情况下验证它,因为我的用例只涉及构建一个纯字符串 SQL?这个答案: 似乎不再有效,因为我在 3.6.x 中找不到工厂方法,这种用例的最佳方法是什么?

虽然我可以设置值并执行 .getSQL() 以获得带有 ? 的 SQL,但还有一个步骤是获取绑定变量,以便我将其传递给 PreparedStatement , 是否可以一步完成?

如何将其与 JDBCTemplate 集成?

首先,您在问题标题中使用了术语 模型 API,但您没有使用 模型 API,您正在使用 DSL API,它更适合 "static SQL queries"。所以,这将是更合适的 API 用法:

List<Field<?>> select = getSelect(String fields ...);
SelectQuery<?> query = create.selectQuery();
query.addFrom(table(name("table")));

if(where)
   query.addWhere(Conditions...);
if(groupBy)
   query.addGroupBy(List<Field<?>> ...);
if(orderBy)
   query.addOrderBy(List<Field<?>> ...);

关于您的具体问题:

getSQL() 与绑定变量一起使用

事实上,默认情况下,jOOQ 总是会在其 SQL 语句中生成绑定变量,这在大多数数据库中是性能方面更好的默认选择。 Here's some background information on that topic.

如果你真的想要内联绑定变量,使用Query.getSQL(ParamType.INLINED). However, you probably want to keep using bind variables, so you can extract them from the query as follows, using Query.getBindVariables():

String sql = query.getSQL();
List<Object> variables = query.getBindVariables();

手册中这些部分的更多信息:

正在使用 JDBCTemplate 执行查询

下面是一个示例,说明如何使用上述 getSQL()getBindVariables() 方法 (from the manual) 将执行绑定到 JPA 的本机查询 API:

static List<Object[]> nativeQuery(EntityManager em, org.jooq.Query query) {

    // Extract the SQL statement from the jOOQ query:
    Query result = em.createNativeQuery(query.getSQL());

    // Extract the bind values from the jOOQ query:
    List<Object> values = query.getBindValues();
    for (int i = 0; i < values.size(); i++) {
        result.setParameter(i + 1, values.get(i));
    }

    return result.getResultList();
}

它与 JDBCTemplate 的工作方式相同。