【问题标题】:How to obtain column names from SQL query (Jooq,Java)如何从 SQL 查询中获取列名(Jooq,Java)
【发布时间】:2019-05-28 04:18:15
【问题描述】:

您好,我在从 SQL 查询中获取值时遇到问题(在 Java 中使用 jooq 库)?

create table `filetest`(`id` int not null auto_increment, `Meno` varchar(21) null, `Priezvisko` varchar(24) null, `Vek` int null, constraint `pk_filetest` primary key (`id`))

insert into `filetest` (`Meno`, `Priezvisko`, `Vek`) values ('Jack', 'Daniels', '21')

我需要获取(解析/获取)的是值:Meno、Priezvisko、Vek。 是否有可能以某种方式从表列的 sql 查询名称中获取它(使用一些 jooq 方法)?

【问题讨论】:

  • 我不这么认为。我的文章是关于 jooq 和 java... :) (它是关于在 Jooq 中解析 sql)
  • @Noro98 SQL 本身就是一门语言,所有实现都一样。您的问题不依赖于 JOOQ 或 Java。因此,您将在该重复答案中找到您的答案。

标签: java jooq


【解决方案1】:

根据您的问题,我假设您想使用 jOOQ parser API 解析您的 SQL 字符串,然后从 jOOQ 的元模型中提取列名。

使用 jOOQ 3.16 查询对象模型 API

jOOQ 3.16 引入了a new, experimental (as of 3.16) query object model API, which can be traversed,它将在接下来的几个小版本中得到增强。从 jOOQ 3.17 开始,解析 SQL 时:

Query query = ctx.parser().parseQuery(sql);

// The QOM.CreateTable type is available in jOOQ 3.17+
if (query instanceof QOM.CreateTable ct) {
    for (TableElement te : ct.$tableElements()) {
        if (te instanceof Field<?> f) {
            System.out.println(f.getName());
        }
    }
}

早期 jOOQ 版本中的替代方法

目前(从 jOOQ 3.11 开始),元模型无法通过公共 API 获得。您只能通过使用VisitListener 来访问它,这是一个在元模型中包含的每个QueryPart(即表达式树元素)上调用的SPI。这个示例实现可以给你一个想法:

import org.jooq.*;
import org.jooq.impl.*;

public class Columns {
    public static void main(String[] args) {
        var parser =
        DSL.using(new DefaultConfiguration().set(new DefaultVisitListener() {
            @Override
            public void visitStart(VisitContext ctx) {
                if (ctx.queryPart() instanceof Field
                        && !(ctx.queryPart() instanceof Param))
                    System.out.println(((Named) ctx.queryPart()).getQualifiedName());
            }
        })).parser();

        System.out.println("Query 1");
        System.out.println("-------");
        parser.parseQuery("create table `filetest`(`id` int not null auto_increment, `Meno` varchar(21) null, `Priezvisko` varchar(24) null, `Vek` int null, constraint `pk_filetest` primary key (`id`))").getSQL();

        System.out.println();
        System.out.println("Query 2");
        System.out.println("-------");
        parser.parseQuery("insert into `filetest` (`Meno`, `Priezvisko`, `Vek`) values ('Jack', 'Daniels', '21')").getSQL();
    }
}

它将打印:

Query 1
-------
"id"
"Meno"
"Priezvisko"
"Vek"
"id" -- Field is referenced again from the constraint

Query 2
-------
"Meno"
"Priezvisko"
"Vek"

当然,另一种选择是使用反射来访问 jOOQ 的内部。

【讨论】:

  • 你能给我一个例子吗?我无法从您的页面或文档中理解它......并且互联网上没有太多使用 visitListener 从 Query 获取值的示例
  • 我有最后一个问题,我想忽略 id 列,这意味着可能会忽略表中包含带有 incement + 约束 id 的经典 id 的所有列。我不知道是否已经有方法,但我想:以某种方式逐个获取值,如下所示: id` int not null auto_increment Meno varchar(21) null Priezvisko varchar(24) null Vek int null constraint pk_filetest primary key (id) 然后询问 values 是否包含 keywod contraint 或 primary key 或 auto_incement 以忽略那些值。有什么方法可以获取这些完整格式的值吗?
  • @Noro96:我已经向您展示了一个可以用它做任何事情的工具。我建议使用调试器来单步调试它以查看它是如何工作的。请注意,该工具 (VisitListener) 比您立即需要的要强大得多,因此您可能会有很多额外的后续问题,除非您自己尝试了解它的工作原理。或者,考虑到它的强大功能,它可能不是适合您的任务的工具。 jOOQ 的未来版本将允许您直接访问 jOOQ 表达式树。目前没有。
猜你喜欢
  • 2019-03-07
  • 2020-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多