数据库中间件-jdbi

文章来源:www.jianshu.com/p/1ee34c858…java

img

Java 的数据库原生使用 jdbc,中间件有不少,例如说 hibernate、mybatis、jdbi,这几种是最经常使用的中间件。git

怎么选择

  • 通常状况下,若是始终只会使用到一种数据库,jdbc 就是最好的选择了,使用这种方式,就是直接使用最底层的东西,定位问题等都很是方便。
  • 数据库中间件就是节省开发人力,用不多的代码就能够快速开发。可是也会引入一些复杂度,特别是若是对中间件不熟悉或者中间件存在 bug,会致使更高复杂度。
  • 若是使用数据库中间件,各类中间件都有各自的优劣势,对于相关的东西须要了解清楚,不然会致使不恰当的选择。

jdbi

jdbi 是我比较喜欢的一个数据库中间件,它是非 ORM 的,特别适合于数据库固定不变的场景,即不会对应多种数据库,之后也不会更换数据库的场景。若是不是这种场景,那么使用 jdbc 或者最好选择 hibernate 等对多种数据库兼容较好的中间件。 基于上述使用场景,jdbi 的优势有:sql

  • 和 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 实现串在一块儿数据库

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 的主页,jdbi.org/,这里讲一些实际使用中…markdown

返回自动递增的主键

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 的查询是什么样的呢?以下:oop

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

可是这个时候,若是遇到大数据量怎么办,jdbi 提供的解决方案:

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

资源后花园:gitee.com/alterem/pic…

相关文章
相关标签/搜索