1. 程式人生 > >使用 mybatis + flying + 雙向相關建模 的電商後端

使用 mybatis + flying + 雙向相關建模 的電商後端

程式碼下載地址:

mybatis.flying

Build Status Codecov Maven Central GitHub release License

眾所周知,mybatis 雖然易於上手,但放到網際網路環境下使用時,不可避免的要面對諸如‘’一級快取存在髒資料‘’、‘’需要寫大量明文 SQL 語句‘’等問題。對於這些問題 mybatis 的開發團隊選擇了一種謙遜的方式,他們開放 mybatis 介面,允許使用者開發外掛,按自己的方式來解決這些問題。於是,一切 ORM 領域相關的問題在 mybatis 上通過外掛都有了解決方案。

flying 主要特點:

以前我們在 mapper.xml 中要寫很複雜的 sql 語句,但現在在 mapper.xml 中只需這樣:

    <select
id="select" resultMap="result">
flying#{?}:select </select> <select id="selectOne" resultMap="result"> flying:selectOne </select> <insert id="insert"> flying:insert </insert> <update id="update"> flying:update </update
>
<delete id="delete"> flying:delete </delete>

再在您的實體類上加上這樣一些標註:

package myPackage;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "account")
public class Account {
    @Id
    @Column
    private Integer id;

    @Column
private java.lang.String name; @Column private Integer age; /* 省略 getter 和 setter */ }

flying 就完全明白您的資料結構和您想做的事情了。 接下來您增刪改查這個實體就會變得非常簡單:

    /* 新增 */
    Account newAccount = new Account();
    newAccount.setName("ann");
    newAccount.setAge(18);
    accountService.insert(newAccount);

    /* 按主鍵查詢 */
    Account account = accountService.select(newAccount.getId());

    /* 按姓名查詢,這裡忽略了年齡 */
    Account accountC1 = new Account();
    accountC1.setName("ann");
    Account account1 = accountService.selectOne(accountC1);
    /* account1 和 account 代表相同的業務資料 */

    /* 按年齡查詢,這裡忽略了姓名 */
    Account accountC2 = new Account();
    accountC2.setAge(18);
    Account account2 = accountService.selectOne(accountC2);
    /* account2 和 account 代表相同的業務資料 */

    /* 按姓名和年齡查詢 */
    Account accountC3 = new Account();
    accountC3.setName("ann");
    accountC3.setAge(18);
    Account account3 = accountService.selectOne(accountC3);
    /* account3 和 account 代表相同的業務資料 */

    /* 修改 */
    account.setName("bob");
    accountService.update(newAccount);

    /* 按主鍵刪除 */
    accountService.delete(newAccount);

由於 flying 掌握了您全部的資料結構和實體關係,所以操作資料變得非常簡單,您再也不需要定義 “getAccountById、getAccountByName、getAccountByAge” 這樣重複性強的方法了,由此帶來更大的好處是您的 service 層只需要關注事務方面的邏輯即可,它從低階程式碼中完全解放了出來。以上只是 flying 功能的冰山一角,其它的功能如多表聯查、分頁、樂觀鎖、跨資料來源查詢、二級快取等 flying 都有簡單的解決方案,您可以在 flying-doc.limeng32.com 中進行檢視。

flying 特點總結如下:

  • 資料操作入參和返回型別都是自定義的實體類,完全 no sql 杜絕各種‘’手滑‘’,專案可隨意重構。

  • 支援跨表操作和跨資料來源操作。

  • 非侵佔工作機制,可以和您已有的 mybatis 方法協同工作。

  • 加入了優化過的快取外掛,可以對多資料來源環境下 flying 方法和傳統 mybatis 方法同時進行快取管理。

  • 可以自定義主鍵生成器,全面支援或邏輯查詢。(初雪版新增特性)

flying 獲取方式:

flying 的 maven 座標為:

    <groupId>com.github.limeng32</groupId>
    <artifactId>mybatis.flying</artifactId>
    <version>0.9.3</version>

mybatis 版本與 flying 最新版本初雪的對應關係見下:

mybatis 版本 flying-初雪
3.3.0、3.3.1 0.8.3
3.4.0、3.4.1、3.4.2、3.4.3、3.4.4、3.4.5 0.9.3

之所以採用分版本釋出的方式是因為我們對 mybatis 每個版本的使用者都認真負責,力求使您得到 flying 最大的好處。

我們還為您提供了一個快速上手的示例,請按以下方式使用:

1、將程式碼搭建成 maven 專案。

2、以 maven 命令執行 tomcat7:run

以下是初始化時的新增的資料來源 dataSource 和 dataSource2,將商品業務資料和使用者資料分開存放是一種常見做法。dataSource 描述了兩個購物車和 12 種商品和商品裝入購物車的情況:

<dataset>
    <CART ID="1" DEAL="0" DEAL_TIME=null PERSON_ID="1"/>
    <CART ID="2" DEAL="0" DEAL_TIME=null PERSON_ID="2" />

    <COMMODITY ID="1" NAME="牙刷A" PRICE="1200" />
    <COMMODITY ID="2" NAME="牙刷B" PRICE="1850" />
    <COMMODITY ID="3" NAME="牙刷C" PRICE="2100" />
    <COMMODITY ID="4" NAME="佳潔士牙膏" PRICE="1499" />
    <COMMODITY ID="5" NAME="六必治牙膏" PRICE="1999" />
    <COMMODITY ID="6" NAME="雲南白藥牙膏" PRICE="2499" />
    <COMMODITY ID="7" NAME="潘婷洗髮露" PRICE="3500" />
    <COMMODITY ID="8" NAME="多芬洗髮露" PRICE="3900" />
    <COMMODITY ID="9" NAME="海飛絲洗髮露" PRICE="5100" />
    <COMMODITY ID="10" NAME="浴液-1500ML" PRICE="2800" />
    <COMMODITY ID="11" NAME="浴液-2000ML" PRICE="3200" />
    <COMMODITY ID="12" NAME="浴液-4000ML" PRICE="4900" />

    <CART_COMMODITY ID="1" CART_ID="1" COMM_ID="1" AMOUNT="3" />
    <CART_COMMODITY ID="2" CART_ID="1" COMM_ID="5" AMOUNT="4" />
    <CART_COMMODITY ID="3" CART_ID="1" COMM_ID="8" AMOUNT="1" />
    <CART_COMMODITY ID="4" CART_ID="1" COMM_ID="12" AMOUNT="1" />
    <CART_COMMODITY ID="5" CART_ID="2" COMM_ID="2" AMOUNT="2" />
    <CART_COMMODITY ID="6" CART_ID="2" COMM_ID="4" AMOUNT="1" />
    <CART_COMMODITY ID="7" CART_ID="2" COMM_ID="9" AMOUNT="2" />
    <CART_COMMODITY ID="8" CART_ID="2" COMM_ID="11" AMOUNT="1" />
</dataset>

dataSource2 描述了 3 種會員級別和 3 位使用者的情況:

<dataset>
    <ROLE ID="1" NAME="普通會員" VALUE="normal" />
    <ROLE ID="2" NAME="銀牌會員" VALUE="silver" />
    <ROLE ID="3" NAME="金牌會員" VALUE="gold" />

    <PERSON ID="1" NAME="張三" ROLE_ID="1" />
    <PERSON ID="2" NAME="李四" ROLE_ID="2" />
    <PERSON ID="3" NAME="王五" ROLE_ID="3" />
</dataset>

專案結構截圖

demo 程式碼結構圖

執行效果

執行起來後,具體的功能訪問頁面可以用如下方式訪問到,在瀏覽器中輸入以下 url 可以看到效果:

use-flying-0.9.3 分支開始我們採用雙向相關的方式構建 pojo,以求打造一個真實可用的電商前臺,關於雙向相關的詳細資訊請見: https://my.oschina.net/u/2280950/blog/1580056

以上API方法除最後一個外,其餘均支援了二級快取。您可以呼叫 updateRoleDirectlyWithoutCache 修改會員級別名稱,之後呼叫 getRole 能看到新的名稱,但呼叫 getCartgetCommodityByCart 則只能看到修改前的名稱,這是因為 updateRoleDirectlyWithoutCache 設計為不支援二級快取,從這裡可以看出快取確實發揮了作用;如果您呼叫 updateRoleDirectly 修改會員級別名稱,在呼叫 getRolegetCartgetCommodityByCart 都會顯示出新的名稱,因為 updateRoleDirectly 設計為支援二級快取。如果再使用 redis 託管 mybatis 的二級快取,就成為了可擴充套件的快取解決方案,不過這已超過本例的討論範圍。

updateRoleDirectlyupdateRoleDirectlyWithoutCache 都是普通 mybatis 方法而非 flying 自動對映方法,這個例子也說明改造 mybatis 二級快取的外掛可供 flying 自動對映方法和非 flying 自動對映方法同時工作。

最後,flying 專案介紹請見 flying-doc.limeng32.com ,我們為開發最好的 mybatis 外掛而努力。

注:本文著作權歸作者,由demo大師(http://www.demodashi.com)宣傳,拒絕轉載,轉載需要作者同意