為什么項目中用了JOOQ后大家都不愿再用Mybatis东羹?

前言

今天給大家介紹一個新的ORM框架->JOOQ,可能很多朋友還沒有聽說過這個框架忠烛,碼農(nóng)哥之前也是一直在使用Mybatis框架作為Java工程中的持久層訪問框架属提,但是最近的一些項目采用JOOQ框架開發(fā)后,碼農(nóng)哥表示再也不想用Mybatis了!

為什么這么說呢冤议?因為JOOQ在代碼層面要比Mybatis簡潔得多斟薇,而且性能也非常優(yōu)異。相信大家都有過這樣的體會恕酸,我們在項目工程中使用Mybatis進(jìn)行數(shù)據(jù)庫相關(guān)代碼的編寫時堪滨,為了提高工程效率,一般會在數(shù)據(jù)庫模型設(shè)計完成后蕊温,一次性使用Mybatis代碼插件(如:mybatis-generator)袱箱,來生成Mybatis數(shù)據(jù)庫訪問的實體類代碼以及XML、Mapper等映射代碼义矛,從而盡量以面向?qū)ο蟮姆绞絹聿僮骱驮L問數(shù)據(jù)庫发笔。而通過這樣的方式,雖然在工程效率上提高了很多凉翻,但是從代碼的簡潔和優(yōu)雅性上來說就會讓人感覺特別的啰嗦了讨,因為自動生成的代碼并不完全都是你在項目中能夠用得到的。

所以制轰,有些對代碼有追求的同學(xué)就會以比較簡潔的方式來手寫SQL代碼量蕊。如在@Mapper接口中編寫這樣的代碼:

@Select("select max(t.balance_id) from balance t where t.country=#{country}\n")
String selectMaxId(Map<String, String> paramMap);

而雖然這種方式可以減少很多無用的代碼量,但是在業(yè)務(wù)邏輯比較復(fù)雜的場景下這種方式顯然又會大大降低開發(fā)的效率艇挨,因為通過這樣的方式不僅SQL編寫的通用層度需要我們花費額外的時間去考慮残炮,而且由于Java面向?qū)ο蟮木幊谭绞?/strong>,我們還需要花費很多的時間來將數(shù)據(jù)庫查詢結(jié)果映射成為實體對象缩滨,所以使用Mybatis進(jìn)行持久層開發(fā)時有時候真的是讓人又愛又恨势就!

那么有沒有一種新的ORM框架既能夠保持Mybatis的靈活性又不像Hibernate那樣重呢?畢竟大家也都是從Hibernate的魔爪中逃離出來后才選擇使用Mybatis直到今天的脉漏!在軟件工程領(lǐng)域就是這樣苞冯,有痛點的地方就一定會有人提供解決方案,JOOQ就是這樣一個產(chǎn)物侧巨!

JOOQ簡介

JOOQ是基于Java訪問關(guān)系型數(shù)據(jù)庫的工具包舅锄,它具有輕量、簡單司忱、并且足夠靈活的特點皇忿,通過JOOQ我們可以輕松的使用Java面向?qū)ο蟮恼Z法來實現(xiàn)各種復(fù)雜的SQL。相比于傳統(tǒng)ORM框架坦仍,如Hibernate鳍烁、Mybatis來說,JOOQ汲取了即汲取了它們操作數(shù)據(jù)的簡單性和安全性繁扎、同時也保留了原生SQL的靈活性幔荒,從某種程度上說JOOQ更像是介于ORM和JDBC的中間層糊闽。

JOOQ目前在國內(nèi)相對來說還比較小眾,對于大部分從SSH或者SSM成長起來的碼農(nóng)朋友們來說爹梁,心里估計會質(zhì)疑“這玩意用的這么少右犹,到底靠不靠譜?”姚垃。在這里碼農(nóng)哥可以很負(fù)責(zé)任的說JOOQ是靠譜的念链!因為碼農(nóng)哥已經(jīng)在好幾個生產(chǎn)項目上實踐過了,而且是在比較核心的支付系統(tǒng)上完全使用了JOOQ來替代Mybatis作為持久層框架莉炉,并且這個支付系統(tǒng)的并發(fā)量也是非常高的钓账,所以JOOQ框架本身是能夠經(jīng)受住真實業(yè)務(wù)場景的考驗的!

SpringBoot項目集成JOOQ

接下來我們就來一起看看絮宁,如何在SpringBoot的項目中集成和使用JOOQ吧梆暮!首先,我們在項目中引入JOOQ的stater依賴包绍昂,如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jooq</artifactId>
</dependency>

因為JOOQ對Spring Boot有很好的支持啦粹,所以我們只需要引入相應(yīng)的starter依賴即可,而具體的版本則是與Spring Boot的版本關(guān)聯(lián)的窘游,這里并不需要我們?nèi)ブ付ā?/p>

其次唠椭,我們需要在項目中配置JOOQ的代碼生成插件,這樣JOOQ就可以自動在項目編譯的時候為我們生成所需要的數(shù)據(jù)庫以來對象了忍饰,在項目的pom.xml中配置Maven插件贪嫂,如下:

<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
    <execution>
        <id>default</id>
        <phase>generate-sources</phase>
        <goals>
            <goal>generate</goal>
        </goals>
        <configuration>
            <jdbc>
                <driver>com.mysql.jdbc.Driver</driver>
                <url>jdbc:mysql://127.0.0.1:3306</url>
                <user>root</user>
                <password><![CDATA[123456]]></password>
            </jdbc>
            <generator>
                <name>org.jooq.util.DefaultGenerator</name>
                <generate>
                    <instanceFields>true</instanceFields>
                    <pojos>true</pojos>
                    <daos>true</daos>
                </generate>
                <database>
                    <inputSchema>jets</inputSchema>
                    <name>org.jooq.util.mysql.MySQLDatabase</name>
                    <includes>.*</includes>
                    <excludes>schema_version</excludes>
                </database>
                <target>
                    <packageName>${app.package}</packageName>
                    <directory>target/generated-sources/jooq</directory>
                </target>
            </generator>
        </configuration>
    </execution>
</executions>
</plugin>

配置完成這個Maven插件后,基本上JOOQ就算差不多與SpringBoot集成完成了艾蓝,如果此時編譯項目JOOQ代碼插件就會在target/generated-sources/jooq目錄下根據(jù)數(shù)據(jù)庫中的表結(jié)構(gòu)生成相應(yīng)的數(shù)據(jù)庫操作對象力崇,而這個過程則完成對開發(fā)人員透明,我們并不需要做額外的事情赢织。

而在具體的業(yè)務(wù)邏輯中亮靴,需要操作數(shù)據(jù)庫時我們就可以很方便的使用這些自動生成的代碼來進(jìn)行操作,例如于置,我們需要在業(yè)務(wù)代碼中執(zhí)行insert操作茧吊,代碼如下:

@Slf4j
@Service
public class OpenServiceImpl implements OpenService {

    @Autowired
    protected DSLContext dslContext;

    @Override
    public BalanceChargeTradeResVo balanceChargeTrade(BalanceChargeTradeReqVo balanceChargeTradeReqVo)
            throws VerifyDataException, BalanceCreateOrderException {
        BalanceChargeTradeResVo balanceChargeTradeResVo;
        try {
            WalletUserBalanceOrderRecord walletUserBalanceOrderRecord = createBalanceChargeOrder(
                    balanceChargeTradeReqVo);
            dslContext.executeInsert(walletUserBalanceOrderRecord);
            balanceChargeTradeResVo = BalanceChargeTradeResVo.builder().userId(balanceChargeTradeReqVo.getUserId())
                    .amount(balanceChargeTradeReqVo.getAmount()).currency(balanceChargeTradeReqVo.getCurrency())
                    .orderId(walletUserBalanceOrderRecord.getOrderId()).businessType(BusinessType.TOP_UP.getCode())
                    .build();
            return balanceChargeTradeResVo;
        } catch (Exception e) {
            throw new BalanceCreateOrderException(ErrorCode.BALANCE_CHARGE_ORDER_ERROR.getCode(),
                    ErrorCode.BALANCE_CHARGE_ORDER_ERROR.getDesc());
        }
    }

在以上代碼中,我們只需要在service業(yè)務(wù)類中注入DSLContext對象八毯,并在組裝完自動生成的數(shù)據(jù)庫類的對象后執(zhí)行executeInsert方法就可以完成insert操作了搓侄。而如果我們要完成查詢操作,也可以很簡單的實現(xiàn)宪彩,代碼如下:

@Slf4j
@Service
public class OpenServiceImpl implements OpenService {

    @Autowired
    protected DSLContext dslContext;

    @Override
    public BalanceQueryResVo balanceQuery(long userId) throws AccountNoExistException {
        List<WalletUserBalanceRecord> walletUserBalanceRecordList = dslContext
                .selectFrom(WalletUserBalance.WALLET_USER_BALANCE)
                .where(WalletUserBalance.WALLET_USER_BALANCE.USER_ID
                        .eq(String.valueOf(userId))).fetchInto(WalletUserBalanceRecord.class);
        if (walletUserBalanceRecordList == null || walletUserBalanceRecordList.size() <= 0) {
            throw new AccountNoExistException(ErrorCode.ACCOUNT_NO_EXIST_ERROR.getCode(),
                    ErrorCode.ACCOUNT_NO_EXIST_ERROR.getDesc());
        }
        Optional<WalletUserBalanceRecord> walletUserBalanceRecord = walletUserBalanceRecordList.stream()
                .filter(o -> o.getAccType().equals(String.valueOf(AccType.CASH_ACCOUNT.getCode()))).findFirst();
        BalanceQueryResVo balanceQueryResVo = BalanceQueryResVo.builder().userId(userId)
                .balance(walletUserBalanceRecordList.stream().mapToInt(o -> o.getBalance().intValue()).sum())
                .currency(walletUserBalanceRecord.get().getCurrency()).build();
        return balanceQueryResVo;
    }

在如??代碼中休讳,我們需要通過自動代碼生成的類指定表名,并以面向?qū)ο蟮恼Z法方式組裝查詢條件后就可以完成查詢操作了尿孔!這里只是簡單介紹了兩種通過JOOQ實現(xiàn)常見數(shù)據(jù)庫操作的方法,更多的細(xì)節(jié),大家可以參考JOOQ用戶手冊活合!

這樣你會發(fā)現(xiàn)操作數(shù)據(jù)庫更加方便快捷了雏婶,而且因為自動代碼生成對開發(fā)者是透明的,所以整個工程的代碼整潔度也提高了白指!PS:大家可以在自己的項目中試試JOOQ留晚,相信你一定不會后悔!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末告嘲,一起剝皮案震驚了整個濱河市错维,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌橄唬,老刑警劉巖赋焕,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仰楚,居然都是意外死亡隆判,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門僧界,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侨嘀,“玉大人,你說我怎么就攤上這事捂襟∫螅” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵葬荷,是天一觀的道長涨共。 經(jīng)常有香客問我,道長闯狱,這世上最難降的妖魔是什么煞赢? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮哄孤,結(jié)果婚禮上锌订,老公的妹妹穿的比我還像新娘眨猎。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布些己。 她就那樣靜靜地躺著,像睡著了一般捧存。 火紅的嫁衣襯著肌膚如雪捷绒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天捉貌,我揣著相機與錄音支鸡,去河邊找鬼冬念。 笑死,一個胖子當(dāng)著我的面吹牛牧挣,可吹牛的內(nèi)容都是我干的急前。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼瀑构,長吁一口氣:“原來是場噩夢啊……” “哼裆针!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寺晌,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤世吨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后呻征,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耘婚,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年怕犁,在試婚紗的時候發(fā)現(xiàn)自己被綠了边篮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡奏甫,死狀恐怖戈轿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阵子,我是刑警寧澤思杯,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站挠进,受9級特大地震影響色乾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜领突,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一暖璧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧君旦,春花似錦澎办、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恕稠,卻和暖如春琅绅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鹅巍。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工千扶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留料祠,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓县貌,卻偏偏與公主長得像术陶,于是被迫代替她去往敵國和親凑懂。 傳聞我的和親對象是個殘疾皇子煤痕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL接谨、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,457評論 0 4
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,092評論 1 32
  • 使用Jooq和flywayDB改善代碼質(zhì)量 @(個人博客)[數(shù)據(jù)庫, mysql, 改進(jìn), jooq, kotli...
    asiazhang2002閱讀 3,875評論 0 4
  • mybatis中的sqlSession是線程安全的嗎摆碉? 鏈接:https://blog.csdn.net/qq_3...
    劉小刀tina閱讀 2,062評論 0 3
  • 油菜花謝了 剩綠油油的葉 香樟樹開花 小小的白色的 湖面柳絮飄 忽驚擾了路人 風(fēng)帶來夏意 天藍(lán)回憶好長
    蘇葉涼閱讀 249評論 2 6