簡體   English   中英

是否可以結合MyBatis和QueryDSL / jOOQ?

[英]Is it possible to combine MyBatis and QueryDSL/jOOQ?

MyBatis提供了映射,本地緩存和開箱即用的日志記錄。
因此,QueryDSL / jOOQ提供SQL語句的編譯時檢查和IDE自動完成。
是否可以將它們結合起來?

換句話說, 我想用QueryDSL或jOOQ創建一個查詢,然后使用MyBatis的一些粘合代碼/適配器執行它

我已經檢查過:

  • 我考慮用QueryDSL生成SQL查詢字符串,並在MyBatis中使用它們的'@SelectProvider'注釋,但它似乎是一個死胡同:MyBatis在其SQL字符串中需要“$ {xxx}”,但QueryDSL只生成查詢基於實際的Java類型,因此即使對於ID也不起作用。
  • MyBatis Generator作為QueryDSL / jOOQ的替代品:非常差的替代方案,因為它實際上生成了一個樣板代碼,您稍后將需要維護和擴展
  • MyBatis SQL Builder作為QueryDSL / jOOQ的替代品:比QueryDSL或jOOQ弱得多,例如它不提供列名的編譯時檢查,它更麻煩,並且它依賴於使代碼復雜化的'@SelectProvider'

我將從高層回答 - 所以我不深入研究QueryDSL和jOOQ之間的實際差異,在討論的這一點上,“只是”在Java中提供了類型安全的嵌入式SQL。 但是,我會從jOOQ的角度給出答案,因為我知道API要好得多。

免責聲明:我是從為jOOQ背后的公司工作的人的角度給出這個答案的。

是的你可以:

是的,您可以將jOOQ與MyBatis結合使用。 例如,您可以從jOOQ查詢中提取查詢字符串,如下所示:

Select<?> query =
DSL.using(configuration)
   .select(TABLE.A, TABLE.B)
   .from(TABLE)
   .where(TABLE.C.eq(1));

String sql = query.getSQL();
List<Object> bindvalues = query.getBindValues();

許多人實際上使用這種技術然后使用Spring JDBC而不是jOOQ運行查詢。 他們這樣做的主要原因是因為他們已經廣泛使用了Spring JDBC,並且他們不希望在他們的堆棧上有兩種類型的查詢執行。

但你為什么要這樣:

您添加到堆棧中的每個API也會增加堆棧行為的復雜性和一組規則。 另一方面,您有一組要從這些API實現的功能。 讓我們來識別這些功能:

  1. 鍵入安全的嵌入式SQL
  2. 高速緩存
  3. 記錄
  4. 將非規范化SQL結果映射到您的域

1)類型安全的嵌入式SQL

這是一個明智的做法。 你可能不想使用MyBatis。 這種實現(正如您所發現的)更多地是一個概念證明。 所以你選擇了jOOQ

2)緩存

這是我個人認為你太快就得出結論的東西。 MyBatis有許多非常簡單的實現,但在緩存的情況下,我很確定你想要實現一個更通用的緩存策略,例如使用新的JSR-107緩存支持,就像Spring中的那個一樣因為緩存並不是真正與SQL緊密耦合的。

3)記錄

例如,jOOQ實現了很容易掛鈎到日志記錄掛鈎 ,但您也可以使用JDBC跟蹤日志庫或JDBC驅動程序的功能來使用 JDBC級別的日志記錄

4)映射

我說過緩存的內容在這里也是如此。 MyBatis為您的映射算法提供了一個簡單的默認實現,當您轉向更復雜的映射方案時,這可能很快就不夠了。 對於jOOQ,btw也是如此,它也實現了POJO的默認映射您可以以任何方式覆蓋它 但很像緩存,映射並不是一個應該在SQL級別上解決的問題。 你會發現更好的工具用於映射本身 - 例如Model Mapper內置jOOQ支持 ,順便說一下 )。 或者如果你在Java 8環境中,你可以使用常規的函數編程技術來映射東西 ,例如:

DSL.using(configuration)
   .select(
       COLUMNS.TABLE_NAME,
       COLUMNS.COLUMN_NAME,
       COLUMNS.TYPE_NAME
   )
   .from(COLUMNS)
   .orderBy(
       COLUMNS.TABLE_CATALOG,
       COLUMNS.TABLE_SCHEMA,
       COLUMNS.TABLE_NAME,
       COLUMNS.ORDINAL_POSITION
   )
   .fetch()

上圖:jOOQ代碼。 下圖:Java 8映射代碼

   .stream()
   .collect(groupingBy(
       r -> r.getValue(COLUMNS.TABLE_NAME),
       LinkedHashMap::new,
       mapping(
           r -> new Column(
               r.getValue(COLUMNS.COLUMN_NAME),
               r.getValue(COLUMNS.TYPE_NAME)
           ),
           toList()
       )
   ))
   .forEach(
       (table, columns) -> {
            System.out.println(
                "CREATE TABLE " + table + " (");

            System.out.println(
                columns.stream()
                       .map(col -> "  " + col.name +
                                    " " + col.type)
                       .collect(Collectors.joining(",\n"))
            );

           System.out.println(");");
       }
  );

這是本文底部的示例,它顯示了如何查詢所有表的H2 INFORMATION_SCHEMA ,並將結果映射到CREATE TABLE語句

結論:

許多API傾向於引誘您使用它們,因為它們具有非核心“功能”,例如緩存或映射,它們實際上是SQL API的非核心功能。 您可以通過簡單的用例和寵物/貓/狗或作者/書籍應用程序快速啟動並運行,但您將遇到更復雜的問題。 在您的用例中,類型安全的嵌入式SQL功能是您希望使用類似jOOQ的原因。 您正在尋找的其他功能都不是非常令人信服的使用MyBatis的原因(其核心功能是外部SQL文件,這與嵌入SQL的jOOQ完全相反)。

所以,我給你的建議是:找出你想要在堆棧中使用的每個功能的最佳工具,看看這些工具是否易於組合。 我們在實現jOOQ時非常謹慎,以允許任何第三方應用程序非常容易地插入jOOQ(例如緩存,日志記錄,映射),因為這些功能不是jOOQ的核心功能。

就像給Lukas添加一個非常完整的答案。

從我的基准測試來看,MyBatis在映射方面存在一些嚴重的性能問題,Jooq是一個更好的性能曲線。 那是Jooq在mapper上的問題。

https://github.com/arnaudroger/SimpleFlatMapper#local-mysql

在此輸入圖像描述

SimpleFlatMapper也是與querydsl和spring數據的集成點。 我不知道你可以將自己的映射與Jooq集成,並將其添加到積壓中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM