【问题标题】:Java Return result of JOOQ queryJOOQ查询的Java返回结果
【发布时间】:2021-06-08 09:32:51
【问题描述】:

我有一个问题。最近有人告诉我如果我与数据库交互就使用 JOOQ,所以我一直在修改我的代码以与 JOOQ 正常工作,但我正在努力解决如何从数据库中选择数据并返回它的方式。我有以下SqlConn 类:

package com.company.database;

import org.jooq.DSLContext;
import org.jooq.Result;
import org.jooq.Record;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import java.sql.*;
import java.util.HashMap;

public class SqlConn {

    private final String SERVER = "database.me:3306";
    private final String DATABASE = "testdb";
    private final String USERNAME = "test";
    private final String PASSWORD = "test";
    private final String URL = "jdbc:mysql://" + SERVER + "/" + DATABASE;
    

    public HashMap<String, String> getMarketCoins() {
        
        HashMap<String, String> returnValue = new HashMap<>();
        
        try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
            DSLContext create = DSL.using(conn, SQLDialect.MYSQL);
            Result<Record> result = create.select().from("MarketCoins").fetch();

            for (Record r : result) {
                returnValue.put(r.getValue("Market").toString(), r.getValue("Coin").toString());
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        
        return returnValue;
    }
}

现在这段代码可以正常工作,但这只是一个从 1 个特定表中收集数据的函数。我之前的代码是构建的,我可以提供一个查询,代码将执行查询并返回结果,但是使用新的 JOOQ 方法,我似乎需要为每个不同的查询和表创建一个函数。我看了这个关于 JOOQ 的初学者教程:https://www.youtube.com/watch?v=4H3AGK_hNMA,但在这个视频中,他还为不同的数据库调用创建了多个函数。这是正确的,还是有更好的方法可以轻松地从我的数据库中获取数据,无论哪个表都无关紧要?我的数据库中有很多表,所以这意味着我需要编写很多函数:(

请告诉我!

【问题讨论】:

  • 在jOOQ之前你是怎么做到的?

标签: java mysql database jooq


【解决方案1】:

正如您所链接的tutorial 中所建议的,jOOQ 最好使用code generator。您的特定查询可以这样实现:

public Map<String, String> getMarketCoins() {
    return
    create().select(MARKET_COINS.MARKET, MARKET_COINS.COIN)
            .from(MARKET_COINS)
            .fetchMap(MARKET_COINS.MARKET, MARKET_COINS.COIN);
}

几点说明:

  1. MARKET_COINS 是为您的表生成的同名类。它包含类型安全的列信息,例如MARKET_COINS.MARKET,类型为Field&lt;String&gt;。因此,String 类型已经可供您使用。您无需执行任何操作
  2. 我假设您将使用一个连接池(例如hikari)并向您的类注入一个DSLContext 实例(例如使用Spring)。您仍然可以使用DriverManager,但通常最好使用连接池。不过,这与您的 jOOQ 使用无关
  3. 始终在您的 SELECT 子句中指定明确的列列表,如果您不打算处理额外的列,则永远不要使用 SELECT *
  4. jOOQ 有一个有用的ResultQuery.fetchMap() 方法,因此您不必手动循环结果
  5. jOOQ 是关于dynamic SQL。以不必重复这些模式的方式编写查询应该很简单,例如如果您经常需要从表中获取键和值:
public <R extends Record, K, V> Map<K, V> getKeyValue(
    TableField<R, K> key, TableField<R, V> value
) {
    return
    create().select(key, value)
            .from(key.getTable())
            .fetchMap(key, value);
}

现在,调用它,例如使用:

Map<String, String> result = getKeyValue(MARKET_COINS.MARKET, MARKET_COINS.COIN);

这显然再次从code generator 的使用中获益良多。

【讨论】:

  • 好的,谢谢,但这意味着当我想在名为Orders 的表上执行SELECT 时,我需要为此创建一个新函数吗?
  • @A.Vreeswijk:你不需要。您可以将所有内容放在 65839 行长的方法中。 jOOQ 不会评判你。
  • @A.Vreeswijk:我很抱歉昨天的尖刻回复:) 我知道当你开始处理这些事情时这似乎很复杂。这个关于在哪里实现 SQL 逻辑的特殊问题并不严格与 jOOQ(甚至 JDBC)有关。这是一个架构问题:“我在哪里实现任何种逻辑”,对此没有明显的答案。使用 jOOQ,您可以非常轻松地重构常见的 SQL 逻辑,因为 jOOQ 使动态 SQL 变得容易。但这真的对你有要求吗?很难说。
  • @A.Vreeswijk:如果您必须编写 50 个不同的查询,那么您必须编写 50 个不同的查询。这没什么不好。人们已经这样做了很长时间。大多数情况下,他们将 SQL 查询“隐藏”在某个层中,他们称之为“DAO”(数据访问对象)或“存储库”或“服务”等。这些包装对象类型上的每个方法都代表一个或多个查询。随着您的继续,将会有一些常见的模式,您可以按照我的说明进行重构。
猜你喜欢
  • 2013-10-01
  • 2017-09-10
  • 1970-01-01
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 2016-08-14
  • 2021-02-17
  • 1970-01-01
相关资源
最近更新 更多