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

代碼地址以下:
http://www.demodashi.com/demo/12468.htmlhtml

mybatis.flying

Build Status Codecov Maven Central GitHub release License

衆所周知,mybatis 雖然易於上手,但放到互聯網環境下使用時,不可避免的要面對諸如‘’一級緩存存在髒數據‘’、‘’須要寫大量明文 SQL 語句‘’等問題。對於這些問題 mybatis 的開發團隊選擇了一種謙遜的方式,他們開放 mybatis 接口,容許用戶開發插件,按本身的方式來解決這些問題。因而,一切 ORM 領域相關的問題在 mybatis 上經過插件都有了解決方案。java

flying 主要特色:

之前咱們在 mapper.xml 中要寫很複雜的 sql 語句,但如今在 mapper.xml 中只需這樣:git

<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>

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

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 就徹底明白您的數據結構和您想作的事情了。 接下來您增刪改查這個實體就會變得很是簡單:web

/* 新增 */
    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 中進行查看。redis

flying 特色總結以下:算法

  • 數據操做入參和返回類型都是自定義的實體類,徹底 no sql 杜絕各類‘’手滑‘’,項目可隨意重構。sql

  • 支持跨表操做和跨數據源操做。apache

  • 非侵佔工做機制,能夠和您已有的 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.一、3.4.二、3.4.三、3.4.四、3.4.5 0.9.3

之因此採用分版本發佈的方式是由於咱們對 mybatis 每一個版本的用戶都認真負責,力求使您獲得 flying 最大的好處。

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

一、將代碼搭建成 maven 項目。

二、以 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 能夠看到效果:

查看購物車: http://localhost:8080/flying-demo2/getCart?id=${購物車cart的id}

查看商品: http://localhost:8080/flying-demo2/getCommodity?id=${商品commodity的id}

翻頁查看商品(全部條件均爲可選): http://localhost:8080/flying-demo2/getCommodityInPage?pageNum=${頁碼}&priceOrder=${按價格升序或降序輸入asc或desc}&priceFrom=${價格最小值}&priceTo=${價格最大值}

增長新商品: http://localhost:8080/flying-demo2/addCommodity?name=${新商品名稱}&price=${新商品價格}

編輯商品: http://localhost:8080/flying-demo2/updateCommodity?id=${商品的id}&name=${商品的名稱}&price=${商品的價格}

查看購物車中的商品: http://localhost:8080/flying-demo2/getCommodityByCart?id=${購物車的id}

對購物車進行結帳: http://localhost:8080/flying-demo2/dealCart?id=${購物車的id}

取消購物車的結帳: http://localhost:8080/flying-demo2/undealCart?id=${購物車的id}

查看用戶: http://localhost:8080/flying-demo2/getPerson?id=${用戶的id}

查看會員級別: http://localhost:8080/flying-demo2/getRole?id=${會員級別的id}

編輯會員級別: http://localhost:8080/flying-demo2/updateRoleDirectly?id=${會員級別的id}&name=${會員級別的名稱}

查詢匹配兩個級別值(如gold、silver、normal)的會員級別(使用或邏輯特性):
http://localhost:8080/flying-demo2/getRoleValue1OrValue2?value1=${級別值1}&value2=${級別值2}

查詢會員級別值(如gold、silver、normal)或用戶名稱匹配給定值的用戶(使用外鍵或邏輯特性)
http://localhost:8080/flying-demo2/getRoleValueOrPersonName?value=${級別值}&name=${用戶名稱}

向當前購物車加入/刪除商品(amount爲負數時爲刪除),並自動處理最終結果(用來展現雙向相關算法下處理業務模型的優雅)
http://localhost:8080/flying-demo2/addCommodityToCart?cartId=${購物車的id}&commId=${商品的id}&amount=${購買數量}

按兩個用戶id查詢購買的商品詳情(使用跨庫或邏輯特性)
http://localhost:8080/flying-demo2/getCartCommodityByPersonId1OrId2?id1=${用戶id1}&id2=${用戶id2}

不刷新緩存的編輯會員級別:http://localhost:8080/flying-demo2/updateRoleDirectlyWithoutCache?id=${會員級別的id}&name=${會員級別的名稱}

以上方法的實現代碼可見: https://github.com/limeng32/flying-demo2/blob/use-flying-0.9.3/src/main/java/indi/demo/flying/web/CommonController.java

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 插件而努力。

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

代碼地址以下:
http://www.demodashi.com/demo/12468.html

注:本文著做權歸做者,由demo大師代發,拒絕轉載,轉載須要做者受權

相關文章
相關標籤/搜索