美文网首页
数据库中间件-jdbi

数据库中间件-jdbi

作者: Wu杰语 | 来源:发表于2019-02-23 21:40 被阅读0次

    java的数据库原生使用jdbc,中间件有很多,例如说hibernate、mybatis、jdbi,这几种是最常用的中间件。

    怎么选择

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

    jdbi

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

    • 和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的主页,http://jdbi.org/,这里讲一些实际使用中遇到的需要注意到的问题

    返回自动递增的主键

    jdbc方式怎么做的呢?

    
            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提供的机制:

    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提供的解决方案:

    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封装了一下,更加适合于开发。

    相关文章

      网友评论

          本文标题:数据库中间件-jdbi

          本文链接:https://www.haomeiwen.com/subject/jkxmyqtx.html