1. 程式人生 > >NutzDao學習筆記-基本概念知識

NutzDao學習筆記-基本概念知識

 

一 環境搭建

  1. 首先,你必須安裝 JDK 1.6,推薦JDK 8u112
  2. 其次,為了執行 Nutz.Dao,你必須要有一個數據庫軟體:
    1. Mysql,Postgresql, SQLServer, Oracle, DB2 , H2都可以。
  3. 建立一個 Java 專案:
    1. 推薦使用EclipseIdeaIDE工具
    2. 你要將資料庫的 JDBC Driver 和你喜歡的連線池加入專案的 classpath
  4. NutDao並不依賴MVC環境及Ioc.
  5. Mvc環境下,通常使用Ioc管理NutDao
    的例項.
  6. NutDao是執行緒安全的,無需重複建立其例項.
    建立POJO
    建立NutzDao例項,定義dataSource (重點)
    二 Dao介面的基本操作

插入

Insert

一條 SQL 插入一條記錄或者多條記錄

插入

FastInsert

一條 SQL ,通過batch插入多條記錄

刪除

Delete

一條 SQL 刪除一條記錄

更新

Update

一條

SQL 更新一條或者多條記錄

獲取

Fetch

一條 SQL 獲取一條記錄

查詢

Query

一條 SQL 根據條件獲取多條記錄

清除

Clear

一條 SQL 根據條件刪除多條記錄

建表

Create

根據實體建表

刪表

Drop

根據實體/表名稱進行刪表

聚合

Func

執行sum,count等操作

傳統關係型資料庫定義了資料庫的四種操作,增刪改查,但是nutz.dao從使用者角度,又擴充套件了好幾種操作,而且都支援條件增刪改查,專門為條件封裝了介面,但是也有它的侷限性

1 不生成外來鍵,也不推薦用外來鍵

2 只能解決一般建表需求,複雜的表結構需通過自定義sql完成

三 注意事項

主鍵

對於一個 POJO,你可以同時為其宣告 @Id @Name,它們都能正常工作。你只需要保證 @Name 對應的欄位 在資料庫裡有唯一性約束即可。 但是通常, Nutz.Dao 並沒有假設你同時在一個 POJO 裡應用 @Id, @Name @PK,如果你 這麼做了,可能會引發一些奇怪的問題。事實上,你也不可能這麼做,不是嗎?

TIPS:註解 @Id 與註解 @Name 宣告的欄位不需要另外加上註解 @Column 在註解 @PK 裡面宣告的對應複合主鍵的欄位不需要另外加上註解 @Column

預設的,nutz.dao認為一個整數型的主鍵是自增的。所以它會在執行

Dao.insert(pet);

之後,為你插入的物件執行

SELECT MAX(id) from t_pet;(如果你使用的資料庫如mysql,支援主鍵返回,那這個操作不會出現)

不同的資料庫獲得自增值得方式是不一樣的,通過@Next註解,宣告資料庫本地方言,來獲取自增值,注意這裡的自增是由資料庫來實現的,而非nutzDao的內部自增機制

複雜的sql條件

  • 對於 Nutz.Dao 來說,它本質上就是將你的 Java 物件轉化成 SQL,然後交給 JDBC 去執行。
  • SQL 中,當執行資料刪除和查詢操作時,最常用的就是 WHERE 關鍵字。
  • WHERE 關鍵字後面的就是所謂的複雜查詢條件

有些情況,資料庫中的欄位同 Java 物件中的欄位並不同名, 所以就需要給 Java 欄位上的資料庫欄位註解加上引數 @Column("資料庫欄位名") 如果你通過 Cnd.wrap() 硬編碼某個欄位,那麼當這個欄位資料庫欄位名發生改變時,你就需要改動很多。 因此你希望僅僅將對於資料庫的變動限制在 Java 物件的原始檔裡 所以 Nutz 提供了 Cnd.where() 方法

提供Criteria介面(繼承Condition介面)

  1. 讓程式設計師更容易的拼裝複雜邏輯的條件
  2. 讓生成的 SQL 可以被引數化,更好的支援 PreparedStatement

 

// 建立一個 Criteria 介面例項


Criteria cri = Cnd.cri();




// 組裝條件

if(...){

    cri.where().andIn("id", 3,4,5).andIn("name", "Peter", "Wendal", "Juqkai");

}else if(...){

    cri.where().andLT("id", 9);

}




if(...){

    cri.where().andLike("name", "%A%");

}




cri.getOrderBy().asc("name").desc("id");




// 執行查詢

List<MyObj> list = dao.query(MyObj.class, cri, null);

 

分頁

使用資料庫的應用程式,多數情況下都需要使用 分頁 這個功能。尤其是在 Web 應用程式中,後端的分頁查詢尤其的普遍。 在以往的使用經驗中,一個分頁查詢,除了能獲取到一個列表外,我們通常需要如下幾個資訊才能在客戶端顯示出一個完整的翻頁條。

  • 當前頁數 -- 第幾頁
  • 頁大小 -- 每頁有多少條記錄
  • 總頁數 -- 一共多少頁
  • 總記錄數 -- 如果不分頁,一共有多少條記錄
    當我們獲得了這四條資訊後,對於維護一個翻頁查詢就足夠。
    Nutz.Dao 的查詢介面天然就支援分頁查詢。
<T> List<T> query(Class<T> classOfT, Condition condition, Pager pager);

 

這個介面有三個引數

  • classOfT 告訴 Nutz.Dao 需要查詢的實體型別
  • condition 告訴 Nutz.Dao 查詢出的列表需要符合的條件。詳細請看 複雜條件
  • 最後一個引數,就是告訴 Nutz.Dao 將結果如何分頁的了。
    Pager 物件有如下幾個注意事項:
  • 如果 pager 被傳入了 null,則不分頁
  • 生成 Pager 物件的時候需要傳入 當前頁數 頁大小
  • Pager 雖然有 getRecordCount() getPageCount() 方法,但是它不會自動被設值 -- 因為考慮到效率
  • 通過 Pager.setRecordCount() 可以為 Pager 設定結果集的總數,Pager 會通過 getPageCount() 返回總頁數
  • 分頁頁數從1開始算,如果頁數是0,代表不分頁,請特別注意
     

支援一對一,一對多,多對多對映,支援自定義sql

事務

對於事務安全,nutz提供了事務模板

  • org.nutz.trans.Trans 類提供了兩個函式 exec
    • 一個接受數目可變的 Atom 物件
    • 一個接受一個整型值用以界定本事務的級別,以及一個數目可變的 Atom 物件
  • Atom 類就是 java.lang.Runnable 的一個別名
  • 在一個 Atom 裡,無論同時操作多少 DataSource,都是事務安全的(由於不是使用XADataSource,無法100%保證)
  • 你可以通過實現自己的 Transaction 實現類,擴充套件 Nutz.Dao 對於事務的支援

 

示例

final Pet pet1 = dao.fetch(Pet.class,"XiaoBai");


final Pet pet2 = dao.fetch(Pet.class,"XiaoHei");




pet1.setNickname("BaiBai");

pet2.setNickname("HeiHei");

// Begin transaction        

Trans.exec(new Atom(){

    public void run() {

        dao.update(pet1);

        dao.update(pet2);

    }

});

提供一個org.nutz.trans.Atom介面的匿名類來實現,在裡面的所有的dao操作都是原子性的,以為他們在同一個原子裡面“Atom”

設定事務的隔離級別

public static void exec(int level, Atom... atoms);

這裡的第一個引數 level java.sql.Connection 介面中的 setTransactionIsolation 規定的 level 是一樣的。下面 是在 java.sql.Connection 裡面關於 level 引數的 JDoc 說明:

它可以是下列常量中的任意一個值:

  • Connection.TRANSACTION_READ_UNCOMMITTED
  • Connection.TRANSACTION_READ_COMMITTED
  • Connection.TRANSACTION_REPEATABLE_READ
  • Connection.TRANSACTION_SERIALIZABLE
    實體解析
     

Class<?>  --->  Entity<?> ---> PojoMaker ---> DaoStatement ---> DaoExecutor ---> JDBC

           |               |              |                 |                |

           \------------------------ NutDao 的實現流程 -----------------------/

  • PojoMaker 介面負責語句的生成
  • DaoExecutor 介面負責語句的執行
    內建服務類
    單獨的呼叫一行介面,多傳入一個引數到沒什麼,但是如果頻繁的被使用,每次都要多寫一個引數畢竟很是麻煩,nutzdao提供了服務類來簡化這些操作
  • 如果 POJO 即聲明瞭 @Id 又聲明瞭 @Name,那麼適合採用 IdNameEntityService
  • 如果 POJO 僅聲明瞭 @Id,那麼適合採用 IdEntityService
  • 如果 POJO 僅聲明瞭 @Name,那麼適合採用 NameEntityService
  • 如果 POJO 即沒聲明瞭 @Id 又沒聲明瞭 @Name,那麼適合採用 EntityService
     
  • 這四個內建的服務類,僅僅提供了一些基本的操作。
  • 這些服務類都是支援泛型。
  • 你可以直接使用,或者你可以從這四個服務類繼承你自己的實現。
  • 如果你繼承這些服務類,請務必宣告泛型

Dao攔截器

var ioc = {


        dao : {

            type : "org.nutz.dao.impl.NutDao",

            args : [{refer:"dataSource"}],

            fields : {

                interceptors : [

                            "log", //輸入sql語句到日誌,這是nutdao預設情況下唯一啟用的攔截器

                            "time", // 列印sql時耗

                            "net.demo.MyDaoInterceptor", // 自定義攔截器,需要實現DaoInterceptor

                            {refer:"superI"} // 引用另外一個bean作為攔截器

                            ]

            }

        }

}

 參考資料:http://www.nutzam.com/index.html