自定义语法元素
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
为了支持简单的供应商特定的 SQL 语法扩展,jOOQ 提供了 纯 SQL 模板 API。 如果 SQL 子句过于复杂,无法用 jOOQ 或此模板 API 表示,或者您需要支持不同的方言,您可以扩展以下类型之一,以直接在 jOOQ 查询中使用
// Simplified API description: public abstract class CustomField<T> implements Field<T> {} public abstract class CustomCondition implements Condition {} public abstract class CustomStatement implements Statement {} public abstract class CustomTable<R extends TableRecord<R>> implements Table<R> {} public abstract class CustomRecord<R extends TableRecord<R>> implements TableRecord<R> {}
实现自定义表及其记录的示例。
这是一个示例 org.jooq.impl.CustomTable
,展示了如何创建带有其字段定义的自定义表,类似于代码生成器正在做的事情。
public class BookTable extends CustomTable<BookRecord> { public static final BookTable BOOK = new BookTable(); public final TableField<BookRecord, String> FIRST_NAME = createField(name("FIRST_NAME"), VARCHAR); public final TableField<BookRecord, String> UNMATCHED = createField(name("UNMATCHED"), VARCHAR); public final TableField<BookRecord, String> LAST_NAME = createField(name("LAST_NAME"), VARCHAR); public final TableField<BookRecord, Short> ID = createField(name("ID"), SMALLINT); public final TableField<BookRecord, String> TITLE = createField(name("TITLE"), VARCHAR); protected BookTable() { super(name("BOOK")); } @Override public Class<? extends BookRecord> getRecordType() { return BookRecord.class; } } public class BookRecord extends CustomRecord<BookRecord> { protected BookRecord() { super(BookTable.BOOK); } }
实现自定义乘法的示例。
这是一个示例 org.jooq.impl.CustomField
,展示了如何创建一个将另一个字段乘以 2 的字段
// Create an anonymous CustomField, initialised with BOOK.ID arguments final Field<Integer> IDx2 = new CustomField<Integer>(BOOK.ID.getName(), BOOK.ID.getDataType()) { @Override public void accept(Context<?> context) { context.visit(BOOK.ID).sql(" * ").visit(DSL.val(2)); } }; // Use the above field in a SQL statement: create.select(IDx2).from(BOOK);
实现特定于供应商的函数的示例。
许多特定于供应商的函数没有得到 jOOQ 的正式支持,但您可以使用 CustomField
自己实现此类支持。这是一个示例,展示了如何实现 Oracle 的 TO_CHAR()
函数,并在 SQL Server 中使用 CONVERT()
模拟它
// Create a CustomField implementation taking two arguments in its constructor class ToChar extends CustomField<String> { final Field<?> arg0; final Field<?> arg1; ToChar(Field<?> arg0, Field<?> arg1) { super("to_char", VARCHAR); this.arg0 = arg0; this.arg1 = arg1; } @Override public void accept(RenderContext context) { context.visit(delegate(context.configuration())); } private QueryPart delegate(Configuration configuration) { switch (configuration.family()) { case ORACLE: return DSL.field("TO_CHAR({0}, {1})", String.class, arg0, arg1); case SQLSERVER: return DSL.field("CONVERT(VARCHAR(8), {0}, {1})", String.class, arg0, arg1); default: throw new UnsupportedOperationException("Dialect not supported"); } } }
上面的 CustomField
实现可以从您自己的自定义 DSL 类中公开
public class MyDSL { public static Field<String> toChar(Field<?> field, String format) { return new ToChar(field, DSL.inline(format)); } }
或者,使用简单的 lambda 实现它
public class MyDSL { public static Field<String> toChar(Field<?> field, String format) { return CustomField.of("to_char", VARCHAR, ctx -> { switch (ctx.family()) { case ORACLE: ctx.visit(DSL.field("TO_CHAR({0}, {1})", String.class, arg0, arg1)); break; case SQLSERVER: ctx.visit(DSL.field("CONVERT(VARCHAR(8), {0}, {1})", String.class, arg0, arg1)); break; default: throw new UnsupportedOperationException("Dialect not supported"); } }); } }
反馈
您对此页面有任何反馈吗? 我们很乐意听到您的反馈!