數據庫中間件-jdbi

文章來源: https://www.jianshu.com/p/1ee...

img

Java 的數據庫原生使用 jdbc,中間件有不少,例如說 hibernate、mybatis、jdbi,這幾種是最經常使用的中間件。java

怎麼選擇

  • 通常狀況下,若是始終只會使用到一種數據庫,jdbc 就是最好的選擇了,使用這種方式,就是直接使用最底層的東西,定位問題等都很是方便。
  • 數據庫中間件就是節省開發人力,用不多的代碼就能夠快速開發。可是也會引入一些複雜度,特別是若是對中間件不熟悉或者中間件存在 bug,會致使更高複雜度。
  • 若是使用數據庫中間件,各類中間件都有各自的優劣勢,對於相關的東西須要瞭解清楚,不然會致使不恰當的選擇。

jdbi

jdbi 是我比較喜歡的一個數據庫中間件,它是非 ORM 的,特別適合於數據庫固定不變的場景,即不會對應多種數據庫,之後也不會更換數據庫的場景。若是不是這種場景,那麼使用 jdbc 或者最好選擇 hibernate 等對多種數據庫兼容較好的中間件。
基於上述使用場景,jdbi 的優勢有:git

  • 和 jdbci 比較接近,使用和掌握很是簡單。
  • 與時俱進,例如說如今最新的 jdbi3,增長了流式編程函數式等編程風格。
  • 源代碼的實現思路很是清晰,有一種美感。使用 jdbi 封裝出的數據庫代碼也很是清晰。

jdbi 的兩種風格

Fluent Api

handle.createUpdate ("INSERT INTO user (id, name) VALUES (:id, :name)")
  .bind ("id", 2)
  .bind ("name", "Clarice")
  .execute ();

這裏就是 java8 的流式風格,用連貫式表達式將一個 sql 實現串在一塊兒sql

Declarative Api

// Define your own declarative interface
public interface UserDao {
    @SqlUpdate ("CREATE TABLE user (id INTEGER PRIMARY KEY, name VARCHAR)")
    void createTable ();

    @SqlUpdate ("INSERT INTO user (id, name) VALUES (?, ?)")
    void insertPositional (int id, String name);

    @SqlUpdate ("INSERT INTO user (id, name) VALUES (:id, :name)")
    void insertNamed (@Bind ("id") int id, @Bind ("name") String name);

    @SqlUpdate ("INSERT INTO user (id, name) VALUES (:id, :name)")
    void insertBean (@BindBean User user);

    @SqlQuery ("SELECT * FROM user ORDER BY name")
    @RegisterBeanMapper (User.class)
    List<User> listUsers ();
}

聲明式的主要是使用註解來實現,在實際的面向對象風格的代碼中,我我的以爲聲明式的比較簡潔,容易閱讀和維護。因此下面都按照 Declarative Api 的方式。數據庫

一些關鍵性的問題

對於 jdbi 的實現,須要本身去看 jdbi 的主頁,http://jdbi.org/,這裏講一些實際使用中遇到的須要注意到的問題編程

返回自動遞增的主鍵

jdbc 方式怎麼作的呢?mybatis

try {
  Connection conn = DBUtil2.getConnection ();
  //PreparedStatement ps = 
  //      conn.prepareStatement (SAVE_SQL, new String [] { "id" });
  // 應該返回生成的主鍵,上下兩種方式均可
  PreparedStatement ps = conn.prepareStatement (SAVE_SQL,PreparedStatement.RETURN_GENERATED_KEYS);
  ps.setString (1, user.getName ());
  ps.setFloat (2, user.getSalary ());
  ps.setInt (3, user.getAge ());
  if (ps.executeUpdate () > 0) {
    // 獲取主鍵
    ResultSet rs = ps.getGeneratedKeys ();
    rs.next ();
    int i = rs.getInt (1);
    user.setId (i);
    ps.close ();
    return true;
  }
  ps.close ();
} catch (SQLException e) {
  e.printStackTrace ();
} finally {
  DBUtil2.closeConnection ();
}

jdbi 提供的機制:app

public interface UserDao {
    @SqlBatch ("INSERT INTO users (name) VALUES (?)")
    @GetGeneratedKeys
    List<User> createUsers (String... names);
}

很是直觀簡潔函數

查詢

jdbc 方式,咱們在查詢大數據量時,通常使用數據庫遊標,逐條查詢。
jdbi 的查詢是什麼樣的呢?以下:大數據

public interface UserDao {
  @SqlQuery ("select name from users")
  List<String> listNames ();  
}

可是這個時候,若是遇到大數據量怎麼辦,jdbi 提供的解決方案:spa

public interface UserDao {
  @SqlQuery ("select name from users")
  ResultIterator<String> getNamesAsIterator ();
}

這裏使用了迭代器,依次去查詢,和 jdbi 遊標的做用是同樣的。

批量插入

jdbi 的插入,當一個列表插入,若是要提高效率,就是拆分插入,拆分插入 jdbi 提供了機制 SqlBatch

public interface UserDao {
  @SqlBatch ("insert into users (tenant_id, id, name)" + "values (:tenantId, :user.id, :user.name)")
  void bulkInsert (@Bind ("tenantId") long tenantId, 
                  @BindBean ("user") User... users);
}

小結

jdbi 是很是簡潔優美的數據庫中間件組件,當在數據庫惟一特別是 pg 數據庫,我的認爲是首選方式,有效的把 jdbc 封裝了一下,更加適合於開發。

img

資源後花園: https://gitee.com/alterem/pic...
相關文章
相關標籤/搜索