JSONタイプを返すjOOQでPL / pgSQLユーザー定義関数のSELECTクエリを実行する方法

NikolaS:

PL / pgSQLのユーザー定義関数をjOOQコードにキャストする正しい方法を見つけることに問題があります。PL / pgSQLのユーザー定義関数はJSON型を返し、どういうわけかjOOQで調整/キャストする必要があります。例をGoogleで検索しましたが、見つかりませんでした。

念のため、ここにPL / pgSQLのユーザー定義関数を示します。

create or replace function public.get_order_by_order_id8(o_id bigint) returns json as
$BODY$
DECLARE
    total_oi_price double precision;
    book_price double precision;
    total_price double precision;
    oi_amount integer;
    order_items json;
    item_recs RECORD;
    book_json json;
    single_order_item json;
    found_order "vertx-jooq-cr".public.orders;
    found_user json;
    _item_id bigint;
    item_array json[];
BEGIN
    select * into found_order
    from "vertx-jooq-cr".public.orders
    where order_id = o_id;

    select json_build_object('user_id', "vertx-jooq-cr".public.users.user_id, 'username', "vertx-jooq-cr".public.users.username)
    into found_user
    from "vertx-jooq-cr".public.users
    INNER JOIN "vertx-jooq-cr".public.orders as o USING (user_id)
    WHERE o.order_id = o_id;

    total_price = 0.00;

    FOR item_recs IN SELECT *
        FROM public.order_item AS oi WHERE oi.order_id = o_id
    LOOP
        select public.get_book_by_book_id(item_recs.book_id) into book_json
        from public.order_item
        where public.order_item.order_item_id IN (item_recs.order_item_id);

        select price INTO book_price FROM book AS b WHERE b.book_id = item_recs.book_id;
        select amount INTO oi_amount FROM order_item AS oi WHERE oi.amount = item_recs.amount;
        
        total_oi_price = book_price * oi_amount;

        SELECT json_build_object('order_item_id', item_recs.order_item_id,
        'amount', item_recs.amount,
        'book', book_json,
        'order_id', item_recs.order_id,
        'total_order_item_price', trunc(total_oi_price::double precision::text::numeric, 2)) INTO single_order_item;
        total_price := total_price + total_oi_price;
        item_array = array_append(item_array, single_order_item);
    END LOOP;
    order_items = array_to_json(item_array);

    return (select json_build_object(
        'order_id', found_order.order_id,
        'total_price', trunc(total_price::double precision::text::numeric, 2),
        'order_date', found_order.order_date,
        'user', found_user,
        'order_items', order_items
    ));

end;
$BODY$
LANGUAGE 'plpgsql';

...そして上記の関数を使用している別のもの。

CREATE OR REPLACE FUNCTION get_all_orders() RETURNS JSON AS
$BODY$
DECLARE
    single_order RECORD;
    single_order_json json;
    orders_array json[];
BEGIN

    FOR single_order IN SELECT * FROM public.orders ORDER BY order_id
    LOOP
        SELECT get_order_by_order_id(single_order.order_id) INTO single_order_json;
        orders_array = array_append(orders_array, single_order_json);
    END LOOP;

    return (select json_build_object(
        'orders', orders_array
    ));
END;
$BODY$
LANGUAGE 'plpgsql';

両方の関数は私のMavenプロジェクトで正常にコード生成されており、最後の関数はそれget_all_orders() に対してSELECT操作を実行してJSONオブジェクトをjOOQコードで返すために必要です。

以下は、他のクラスRoutines.javaKeys.java生成される**。jooqパッケージDefaultCatalog.javaのクラスです。

/**
 * Convenience access to all stored procedures and functions in public
 */
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Routines {

    /**
     * Call <code>public.get_all_orders</code>
     */
    public static JSON getAllOrders(Configuration configuration) {
        GetAllOrders f = new GetAllOrders();

        f.execute(configuration);
        return f.getReturnValue();
    }

    /**
     * Get <code>public.get_all_orders</code> as a field.
     */
    public static Field<JSON> getAllOrders() {
        GetAllOrders f = new GetAllOrders();

        return f.asField();
    }

// other methods left out for code brevity

/**
     * Call <code>public.get_order_by_order_id</code>
     */
    public static JSON getOrderByOrderId(Configuration configuration, Long oId) {
        GetOrderByOrderId f = new GetOrderByOrderId();
        f.setOId(oId);

        f.execute(configuration);
        return f.getReturnValue();
    }

    /**
     * Get <code>public.get_order_by_order_id</code> as a field.
     */
    public static Field<JSON> getOrderByOrderId(Long oId) {
        GetOrderByOrderId f = new GetOrderByOrderId();
        f.setOId(oId);

        return f.asField();
    }

    /**
     * Get <code>public.get_order_by_order_id</code> as a field.
     */
    public static Field<JSON> getOrderByOrderId(Field<Long> oId) {
        GetOrderByOrderId f = new GetOrderByOrderId();
        f.setOId(oId);

        return f.asField();
    }
}

そしてGetAllOrders.java、これは**.jooq.routinesパッケージにある私のルーチンクラスです

/**
 * This class is generated by jOOQ.
 */
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class GetAllOrders extends AbstractRoutine<JSON> {

    private static final long serialVersionUID = 917599810;

    /**
     * The parameter <code>public.get_all_orders.RETURN_VALUE</code>.
     */
    public static final Parameter<JSON> RETURN_VALUE = Internal.createParameter("RETURN_VALUE", org.jooq.impl.SQLDataType.JSON, false, false);

    /**
     * Create a new routine call instance
     */
    public GetAllOrders() {
        super("get_all_orders", Public.PUBLIC, org.jooq.impl.SQLDataType.JSON);

        setReturnParameter(RETURN_VALUE);
    }
}

最後に、これはjOOQでSELECTクエリを実行するための私のjOOQコードです。

Future<JsonObject> ordersFuture = queryExecutor.transaction(qe -> qe
                .query(dsl -> dsl
                    .select(new Routines().getAllOrders())
            )); 

... qe.query()メソッドの定義を以下に示します。

@Override
    public <R extends Record> Future<QueryResult> query(Function<DSLContext, ? extends ResultQuery<R>> queryFunction) {
        return executeAny(queryFunction).map(ReactiveQueryResult::new);
    }

発生する問題

"型の不一致:Future <オブジェクト>からFuture <JsonObject>に変換できません"

"型の不一致:Future <QueryResult>からFuture <Object>に変換できません"

ところで、私はこれがjOOQ 3.13.1を使用するvertx -jooq実装であることを言及する必要があります。
どんな助け/提案でも大歓迎です。

更新
ここでリクエストされたように、型とシグネチャtransaction()メソッドの最初にありません(詳細はこちら

/**
     * Convenience method to perform multiple calls on a transactional QueryExecutor, committing the transaction and
     * returning a result.
     * @param transaction your code using a transactional QueryExecutor.
     *                    <pre>
     *                    {@code
     *                    ReactiveClassicGenericQueryExecutor nonTransactionalQueryExecutor...;
     *                    Future<QueryResult> resultOfTransaction = nonTransactionalQueryExecutor.transaction(transactionalQueryExecutor ->
     *                      {
     *                          //make all calls on the provided QueryExecutor that runs all code in a transaction
     *                          return transactionalQueryExecutor.execute(dslContext -> dslContext.insertInto(Tables.XYZ)...)
     *                              .compose(i -> transactionalQueryExecutor.query(dslContext -> dslContext.selectFrom(Tables.XYZ).where(Tables.XYZ.SOME_VALUE.eq("FOO")));
     *                      }
     *                    );
     *                    }
     *                    </pre>
     * @param <U> the return type.
     * @return the result of the transaction.
     */
    public <U> Future<U> transaction(Function<ReactiveClassicGenericQueryExecutor, Future<U>> transaction){
        return beginTransaction()
                .compose(queryExecutor -> transaction.apply(queryExecutor) //perform user tasks
                        .compose(res -> queryExecutor.commit() //commit the transaction
                                .map(v -> res))); //and return the result
    }

...そしてexecuteAny()(詳細はこちらから入手可能):

 /**
     * Executes the given queryFunction and returns a <code>RowSet</code>
     * @param queryFunction the query to execute
     * @return the results, never null
     */
    public Future<RowSet<Row>> executeAny(Function<DSLContext, ? extends Query> queryFunction) {
        Query query = createQuery(queryFunction);
        log(query);
        Promise<RowSet<Row>> rowPromise = Promise.promise();
        delegate.preparedQuery(toPreparedQuery(query)).execute(getBindValues(query),rowPromise);
        return rowPromise.future();
    }

...そしてReactiveQueryResultについてはこちら

UPDATE2:
これは、get_all_orders()JSONタイプのPL / pgSQLで作成された関数の結果です

{
  "orders": [
    {
      "order_id": 1,
      "total_price": 29.99,
      "order_date": "2019-08-22T10:06:33",
      "user": {
        "user_id": 1,
        "username": "test"
      },
      "order_items": [
        {
          "order_item_id": 1,
          "amount": 1,
          "book": {
            "book_id": 1,
            "title": "Harry Potter and the Philosopher's Stone",
            "price": 29.99,
            "amount": 400,
            "is_deleted": false,
            "authors": [
              {
                "author_id": 4,
                "first_name": "JK",
                "last_name": "Rowling"
              }
            ],
            "categories": [
              {
                "category_id": 2,
                "name": "Lyric",
                "is_deleted": false
              }
            ]
          },
          "order_id": 1,
          "total_order_item_price": 29.99
        }
      ]
    },
    {
      "order_id": 2,
      "total_price": 29.99,
      "order_date": "2019-08-22T10:10:13",
      "user": {
        "user_id": 1,
        "username": "test"
      },
      "order_items": [
        {
          "order_item_id": 2,
          "amount": 1,
          "book": {
            "book_id": 1,
            "title": "Harry Potter and the Philosopher's Stone",
            "price": 29.99,
            "amount": 400,
            "is_deleted": false,
            "authors": [
              {
                "author_id": 4,
                "first_name": "JK",
                "last_name": "Rowling"
              }
            ],
            "categories": [
              {
                "category_id": 2,
                "name": "Lyric",
                "is_deleted": false
              }
            ]
          },
          "order_id": 2,
          "total_order_item_price": 29.99
        }
      ]
    }
  ]
}
ルーク・エダー:

あなたの質問の真ん中から:

Future<JsonObject> ordersFuture = queryExecutor.transaction(qe -> qe.query(...)); 

// Where
<R extends Record> Future<QueryResult> query(
  Function<DSLContext, ? extends ResultQuery<R>> queryFunction
) { ... }

Javaコンパイラは、あなたを変換することはできませんFuture<QueryResult>Future<JsonObject>追加の型推論の問題があり、そのままではわかりにくいエラーメッセージが表示される場合がありますが、それが私が見ているものです。

どういうわけかからFuture<QueryResult>明示的にマッピングする必要がありFuture<JsonObject>ます。いずれの場合も、transaction()メソッドはこの変換を行いません。

<U> Future<U> transaction(
  Function<ReactiveClassicGenericQueryExecutor, Future<U>> transaction
) { ... }

<U>ここ型はメソッドQueryResultからバインドされますquery()

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

PHPでMSSQLユーザー定義関数を実行する

分類Dev

EF6でOracleユーザー定義関数を実行する方法

分類Dev

puppetスクリプトを実行するユーザーを変数として定義する方法

分類Dev

Oracleユーザー定義の集計関数をJavaで実装する方法

分類Dev

ユーザー定義関数を別のセルに実行するVBAExcel

分類Dev

ユーザー定義型(UDT)のリストで「含む」を使用してクエリを実行する

分類Dev

実行するc ++システム関数のユーザー定義ディレクトリ

分類Dev

方法:(日付)値の範囲に対してユーザー定義関数を実行する

分類Dev

<forcedType>タグを使用して生成されたユーザー定義のPL / pgSQL関数のjOOQでINPUTパラメーターの適切な値の型を生成することを修正するにはどうすればよいですか?

分類Dev

変数定義に関するユーザー入力の問題を伴うajaxリクエスト

分類Dev

node.jsを使用してOracleユーザー定義関数を実行する方法

分類Dev

node.jsを使用してOracleユーザー定義関数を実行する方法

分類Dev

PL / SQLでは、ユーザー定義関数からクエリの結果をどのように返しますか。

分類Dev

ユーザー定義のdo.callのwhat関数を実装する正しい方法は何ですか?

分類Dev

SQLServerユーザー定義関数からエラーを報告する方法

分類Dev

SQLServerユーザー定義関数からエラーを報告する方法

分類Dev

関数からポインタを返すユーザー定義のリンクリスト

分類Dev

PHPでmysqlユーザー定義関数を作成する方法

分類Dev

何百万もの行を処理するユーザー定義のPython関数を最適化する方法は?

分類Dev

Python2.7では、メインスクリプトおよびその他のユーザー定義関数から変数を使用する方法

分類Dev

SQLサーバーのユーザー定義関数を作成する方法

分類Dev

CakePHP3クエリでMySQLユーザー定義変数を使用するselect

分類Dev

Tinkercad:Arduinoでユーザー定義クラス「タイプに名前を付けない」を返す関数

分類Dev

postgreSQLでユーザー定義関数のコメントを取得する方法

分類Dev

SQLServerのユーザー定義関数内でopenxmlを使用する方法

分類Dev

ユーザー定義のタイプによってフィルタリングするときjooqでwhere句を形成する方法

分類Dev

sqldfクエリにユーザー定義変数を含める方法は?

分類Dev

BigQueryのユーザー定義関数はクエリを劇的に遅くします

分類Dev

ユーザー定義の引数に基づいてスロットルを実行する方法は?

Related 関連記事

  1. 1

    PHPでMSSQLユーザー定義関数を実行する

  2. 2

    EF6でOracleユーザー定義関数を実行する方法

  3. 3

    puppetスクリプトを実行するユーザーを変数として定義する方法

  4. 4

    Oracleユーザー定義の集計関数をJavaで実装する方法

  5. 5

    ユーザー定義関数を別のセルに実行するVBAExcel

  6. 6

    ユーザー定義型(UDT)のリストで「含む」を使用してクエリを実行する

  7. 7

    実行するc ++システム関数のユーザー定義ディレクトリ

  8. 8

    方法:(日付)値の範囲に対してユーザー定義関数を実行する

  9. 9

    <forcedType>タグを使用して生成されたユーザー定義のPL / pgSQL関数のjOOQでINPUTパラメーターの適切な値の型を生成することを修正するにはどうすればよいですか?

  10. 10

    変数定義に関するユーザー入力の問題を伴うajaxリクエスト

  11. 11

    node.jsを使用してOracleユーザー定義関数を実行する方法

  12. 12

    node.jsを使用してOracleユーザー定義関数を実行する方法

  13. 13

    PL / SQLでは、ユーザー定義関数からクエリの結果をどのように返しますか。

  14. 14

    ユーザー定義のdo.callのwhat関数を実装する正しい方法は何ですか?

  15. 15

    SQLServerユーザー定義関数からエラーを報告する方法

  16. 16

    SQLServerユーザー定義関数からエラーを報告する方法

  17. 17

    関数からポインタを返すユーザー定義のリンクリスト

  18. 18

    PHPでmysqlユーザー定義関数を作成する方法

  19. 19

    何百万もの行を処理するユーザー定義のPython関数を最適化する方法は?

  20. 20

    Python2.7では、メインスクリプトおよびその他のユーザー定義関数から変数を使用する方法

  21. 21

    SQLサーバーのユーザー定義関数を作成する方法

  22. 22

    CakePHP3クエリでMySQLユーザー定義変数を使用するselect

  23. 23

    Tinkercad:Arduinoでユーザー定義クラス「タイプに名前を付けない」を返す関数

  24. 24

    postgreSQLでユーザー定義関数のコメントを取得する方法

  25. 25

    SQLServerのユーザー定義関数内でopenxmlを使用する方法

  26. 26

    ユーザー定義のタイプによってフィルタリングするときjooqでwhere句を形成する方法

  27. 27

    sqldfクエリにユーザー定義変数を含める方法は?

  28. 28

    BigQueryのユーザー定義関数はクエリを劇的に遅くします

  29. 29

    ユーザー定義の引数に基づいてスロットルを実行する方法は?

ホットタグ

アーカイブ