1. 程式人生 > 程式設計 >簡單瞭解java ORM框架JOOQ

簡單瞭解java ORM框架JOOQ

這篇文章主要介紹了簡單瞭解java ORM框架JOOQ,文中通過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

前言

今天給大家介紹一個新的ORM框架->JOOQ,可能很多朋友還沒有聽說過這個框架,碼農哥之前也是一直在使用Mybatis框架作為Java工程中的持久層訪問框架,但是最近的一些專案採用JOOQ框架開發後,碼農哥表示再也不想用Mybatis了!

為什麼這麼說呢?因為JOOQ在程式碼層面要比Mybatis簡潔得多,而且效能也非常優異。相信大家都有過這樣的體會,我們在專案工程中使用Mybatis進行資料庫相關程式碼的編寫時,為了提高工程效率,一般會在資料庫模型設計完成後,一次性使用Mybatis程式碼外掛(如:mybatis-generator),來生成Mybatis資料庫訪問的實體類程式碼以及XML、Mapper等對映程式碼,從而儘量以面向物件的方式來操作和訪問資料庫。而通過這樣的方式,雖然在工程效率上提高了很多,但是從程式碼的簡潔和優雅性上來說就會讓人感覺特別的囉嗦,因為自動生成的程式碼並不完全都是你在專案中能夠用得到的。

所以,有些對程式碼有追求的同學就會以比較簡潔的方式來手寫SQL程式碼。如在@Mapper介面中編寫這樣的程式碼:

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

而雖然這種方式可以減少很多無用的程式碼量,但是在業務邏輯比較複雜的場景下這種方式顯然又會大大降低開發的效率,因為通過這樣的方式不僅SQL編寫的通用層度需要我們花費額外的時間去考慮,而且由於Java面向物件的程式設計方式,我們還需要花費很多的時間來將資料庫查詢結果對映成為實體物件,所以使用Mybatis進行持久層開發時有時候真的是讓人又愛又恨!

那麼有沒有一種新的ORM框架既能夠保持Mybatis的靈活性又不像Hibernate那樣重呢?畢竟大家也都是從Hibernate的魔爪中逃離出來後才選擇使用Mybatis直到今天的!在軟體工程領域就是這樣,有痛點的地方就一定會有人提供解決方案,JOOQ就是這樣一個產物!

JOOQ簡介

JOOQ是基於Java訪問關係型資料庫的工具包,它具有輕量、簡單、並且足夠靈活的特點,通過JOOQ我們可以輕鬆的使用Java面向物件的語法來實現各種複雜的SQL。相比於傳統ORM框架,如Hibernate、Mybatis來說,JOOQ汲取了即汲取了它們操作資料的簡單性和安全性、同時也保留了原生SQL的靈活性,從某種程度上說JOOQ更像是介於ORM和JDBC的中間層。

JOOQ目前在國內相對來說還比較小眾,對於大部分從SSH或者SSM成長起來的碼農朋友們來說,心裡估計會質疑“這玩意用的這麼少,到底靠不靠譜?”。在這裡碼農哥可以很負責任的說JOOQ是靠譜的!因為碼農哥已經在好幾個生產專案上實踐過了,而且是在比較核心的支付系統上完全使用了JOOQ來替代Mybatis作為持久層框架,並且這個支付系統的併發量也是非常高的,所以JOOQ框架本身是能夠經受住真實業務場景的考驗的!

SpringBoot專案整合JOOQ

接下來我們就來一起看看,如何在SpringBoot的專案中整合和使用JOOQ吧!首先,我們在專案中引入JOOQ的stater依賴包,如下:

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

因為JOOQ對Spring Boot有很好的支援,所以我們只需要引入相應的starter依賴即可,而具體的版本則是與Spring Boot的版本關聯的,這裡並不需要我們去指定。

其次,我們需要在專案中配置JOOQ的程式碼生成外掛,這樣JOOQ就可以自動在專案編譯的時候為我們生成所需要的資料庫以來物件了,在專案的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目錄下根據資料庫中的表結構生成相應的資料庫操作物件,而這個過程則完成對開發人員透明,我們並不需要做額外的事情。

而在具體的業務邏輯中,需要操作資料庫時我們就可以很方便的使用這些自動生成的程式碼來進行操作,例如,我們需要在業務程式碼中執行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業務類中注入DSLContext物件,並在組裝完自動生成的資料庫類的物件後執行executeInsert方法就可以完成insert操作了。而如果我們要完成查詢操作,也可以很簡單的實現,程式碼如下:

@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;
  }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。