关闭

[置顶] 众里寻他千百度-- 轻量级持久化框架

标签: 框架DbHelper
20877人阅读 评论(52) 收藏 举报
分类:

起了一个比较文艺的标题,但是仍然感觉不能 表达出接下来这个工具的文雅。 虽然这个库是前几个月写的了,但是经过了近期小项目的考验,愈发觉得这款轻量级的库应该被更多的开发者所知晓,于是“臭不要脸”地写了这篇介绍性的文章。


最新版本:衣带渐宽终不悔,为伊消得人憔悴–DbHelper增强版

初衷

对于如日中天的编程语言老大哥Java而言,其拥趸者数目定然不少。

纯JDBC

基本上而言,到达一定的阶段之后,就一定会接触到数据库了。一开始写纯正的JDBC的时候,不知道别人是怎么想的,但是对我个人而言,简直是 如坐针毡。

先不论使用Statement还是使用PreparedStatement来拼凑SQL语句,单单是处理ResultSet就是个不折不扣的烦心事。

持久化框架

其实这并不是特例,大部分人都会有这么个感受。不然Hibernate等这些持久化框架也不会诞生了不是。但这也带来了一些弊端。

  • 首先对于新手而言,使用这些框架需要一定的学习成本,学习曲线不够平缓,这就有可能磨灭其学习的兴趣。

  • 其次,对于小项目而言,动用重量级的框架,就显得“大材小用”了。虽然这并不是说部可以,却显得有点不合时宜。

轻量级持久化框架

相信大家都了解Apache的dbutils吧。大大地简化了JDBC的处理,封装了很多必须的操作。但是我个人认为它并不能称之为一个框架。 充其量是一个JDBC的Wrap版,也就是对JDBC进行了简单的封装的一个工具。

于是,在研究了其工作原理之后,结合Apache的另一个BeanUtils库,我制作了一个比较轻量级的数据库持久化框架。(姑且称之为框架吧,(^__^) 嘻嘻……)

设计思路

以我个人,不长的开发经验来看。“过犹不及,过满则亏”。所以对于框架的设计原则也应该如此。

不能什么都做,要适时的将权限放开,增加拓展。

仔细思考了,到底要拿它来做什么? 如何添加拓展?这些问题之后,我就开始着手编码了。

期间运用了 蹩脚的泛型和反射操作,自动化的解剖Bean,来解决与数据库之间的持久化和反序列化处理等等。

大体的“架构” 可用下图表示:

架构图

怎么使用?

介绍到如何使用,我觉得还是以实际的使用案例来介绍比较好,这样更有说服力。

依赖

因为这个框架依赖于apache的一些jar,所以我们需要将下列依赖添加到自己的项目中。(我个人建议在项目中新建一个lib包来放置jar文件)
jar依赖

数据库配置

因为JDBC是跨数据库的,所以我们只要提供针对不同的数据库厂商的jar,那么这个框架也可以跨数据库。

如上图可以看到 src目录下有一个db.cfg.xml的文件。这里面就放置了之前要手动处理的数据库配置信息了。比葫芦画瓢,按照下面的代码配置自己的环境即可。

<?xml version="1.0" encoding="UTF-8" ?>
<project>
    <database name="mysql">
        <driver>com.mysql.jdbc.Driver</driver>
        <url>jdbc:mysql://localhost:3306/mydb</url>
        <user>root</user>
        <password>mysql</password>
    </database>

</project>

基本上来说,大家都会有专门的BaseDAO类,那么在这个类里面进行数据库配置的注册事件是最合适不过了。

import dbhelper.DbHelper;

/**
 * @author 郭 璞
 *
 */
public class BaseDAO {

    /**
     * 使用静态代码块的方式,在程序的DAO层运行之前就注册好 DbHelper ,做好对数据源的注册
     */
    static {
        try {
            DbHelper.register();
        } catch (Exception e) {
            throw new RuntimeException(e + "\n 数据源未注册成功");
        }
    }

}

这样,其他的DAO只需要继承这个类就可以了,我们就不用关心数据源的问题了,底层框架会自动的帮我们搞定。

正式使用

有一点需要强调的是,数据库中的字段要和Java Bean中的属性名保持高度的一致,否则框架不能正确的找到其隶属的字段信息。毕竟框架不是万能的嘛。

数据库表结构

数据库表字段

Java Bean结构

JavaBean字段

如图所示, 按照这样来设计就可以了。

从数据库获取一条记录,并转为对象


    /**
     * 根据用户名查找其个人的详细的信息
     * 
     * @param user_name
     * @return
     */
    public User selectUser(String user_name) {
        // 声明数据库连接对象
        Connection conn = null;
        try {
            // 初始化 数据库连接对象,避免出现空指针调用异常问题
            conn = DbHelper.getConn();
            // 组装 SQL 查询语句
            String sql = "select * from java_user where user_name= ?";
            // 实例化数据库查询对象
            QueryRunner queryRunner = new QueryRunner();
            // 采用 泛型编程技术 ,从底层开始直接获取数据库行记录到对象的自动转化流程
            User user = queryRunner.query(conn, sql, new BeanHandler<User>(User.class), user_name);
            // 释放数据库链接资源
            DbHelper.release(conn);
            return user != null ? user : null;
        } catch (Exception e) {
            throw new RuntimeException(" :\n" + e);
        }
    }

与此同时,数据库中的记录如下图:
数据库中记录信息

下面使用JUnit来测试一下,
Junit测试结果

可见,确实可以自动的帮助我们反序列化数据库中的数据。


高级版

上面的小案例简单的测试了一下,单个Bean对象的获取,那么如果说ResultSet内包含多条记录呢? 这时候你可能会想,要是能自动的转换成List,然后List里面包裹着这些反序列化好的数据对象,该多好。

确实是这样的,DbHelper也做到了。(^__^) 嘻嘻……

数据库内记录

闲言少叙,咱们直接开始吧。

数据库内字段信息

JavaBean结构

按照约定,java Bean 内字段保持和数据库内表结构字段一致即可。

public class Site {
    private String site_name;
    private String site_username;
    private String site_password;
    private Integer java_user_id;
    private Integer java_tag_tag_id;

    public String getsite_name() {
        return site_name;
    }
    ··· ···

然后就是 DAO层内的业务代码了,还是那简单的几步。需要注意的是,接口回调的时候new的不再是BeanHandler了,而是BeanListHandler。这和返回的结果集直接相关。

public List<Site> selectAllSites(String user_name) {
        Connection conn = null;
        try {
            // 实例化 数据库连接对象
            conn = DbHelper.getConn();
            // 拼接sql语句
            String sql = "select * from java_site where java_site.java_user_id=(select java_user.id from java_user where java_user.user_name='"
                    + user_name + "')";
            // 实例化查询器
            QueryRunner queryRunner = new QueryRunner();
            // 获取接口回调处理后的结果
            List<Site> sites = queryRunner.query(conn, sql, new BeanListHandler<Site>(Site.class));
            // 释放数据库链接资源
            DbHelper.release(conn);

            return sites != null ? sites : null;
        } catch (Exception e) {
            throw new RuntimeException(" :\n" + e);
        }
    }

然后再来看看JUnit的测试结果:
JUnit List 测试结果

果不其然,还是获取到了正确的数据。这一点可以和数据库中原始的信息进行对比。

拓展

为了使得这个框架更加的灵活, 满足大部分的定制性的需求,这里给QueryRunner 额外进行了拓展。可以灵活的处理自己的业务需求。

/**
     * 根据给定的参数实现向数据库中给定SQL语句的update,delete,insert 操作
     * 
     * @param conn
     *            数据库连接对象,用户不必关心其释放问题,这里自动将其释放
     * @param sql
     *            数据库查询语句
     * @param params
     *            对应于SQL语句占位符的参数列表
     * @throws Exception
     */
    public void update(Connection conn, String sql, Object... params) throws Exception {
        PreparedStatement ps = conn.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            ps.setObject((i + 1), params[i]);
        }
        ps.executeUpdate();
        DbHelper.release(conn, ps);
    }

使用的时候只需要将组装好的sql语句传给query方法即可。如:

/**
     * 更新 网站对应的标签信息
     * 
     * @param site_name
     *            网站名称
     * @param new_java_tag_tag_id
     *            新的标签信息
     * @return
     */
    public boolean updateSiteTagID(String site_name, Integer new_java_tag_tag_id) {
        Connection conn = null;
        try {
            conn = DbHelper.getConn();
            String sql = "update java_site set java_tag_tag_id=? where site_name=?";
            QueryRunner queryRunner = new QueryRunner();
            Object[] params = { new_java_tag_tag_id, site_name };
            // 在完成更新操作后,底层会自动的断开与数据库的链接
            queryRunner.update(conn, sql, params);
            return true;
        } catch (Exception e) {
            throw new RuntimeException(" :\n" + e);
        }

    }

如此,基本上可以满足JDBC编程时遇到的情况了。

总结

其实博主本人真的是一个爱分享,热心肠的有志青年。今天写这篇文章的一个很重要的原因就是想帮助那些饱受JDBC之苦的开发人员,今早的以一种优雅的方式脱离苦海。

这篇文章从应用性的角度而言,应该算是比较详细的了。但是基本上没有讨论底层的实现。

如果您对这个轻量级的框架感兴趣的话,不妨点点左侧的友情链接。

友情链接

  • 想要源码: 点击蓝色的“GitHub”
  • 一起讨论: 点击红色的“点我聊天”(我有可能会不在线)
  • 联系方式: 发私信或者从GitHub上找到我的邮箱。

最后,衷心希望需要的人 能从中获得帮助。

18
5
查看评论

java的持久化(JDBC ,mybatis, Hibernate, SpringJDBC)之间的区别

JDBC, Ibtais ,Hibernate ,SpringJDBC  是我们平时大家开发的过程中使用的比较多的几种持久化技术,具体在开发的过程中该怎么选择呢?            先来说说各...
  • qq_35703954
  • qq_35703954
  • 2017-01-11 21:46
  • 3149

采用 Java 持久化框架:选择、时机和优缺点?

对于开发新软件系统来说,面向对象编程无疑是当今使用最为广泛的编程模式。由于商业数据的持久性需求,关系数据库管理系统(RDBMS)取得了最为 广泛的应用。RDBMS 使用的是关系模型,它与软件系统中的域对象模型有所不同。使用面向对象编程语言开发软件系统并使用 RDBMS 来持久存储数据时,数据持久化框...
  • DL88250
  • DL88250
  • 2008-01-14 05:42
  • 5441

采用Java持久化框架:选择、时机和优缺点

对于开发新软件系统来说,面向对象编程无疑是当今使用最为广泛的编程模式。由于商业数据的持久性需求,关系数据库管理系统(RDBMS)取得了最为 广泛的应用。RDBMS 使用的是关系模型,它与软件系统中的域对象模型有所不同。使用面向对象编程语言开发软件系统并使用 RDBMS 来持久存储数据时,数据持久化框...
  • hshhack
  • hshhack
  • 2009-07-28 20:34
  • 624

【持久化框架】Mybatis与Hibernate的详细对比

这篇博文我们重点分析一下Mybatis与Hibernate的区别
  • jiuqiyuliang
  • jiuqiyuliang
  • 2015-05-01 14:20
  • 76995

【持久化框架】Mybatis简介与原理

mybatis简单小巧易于上手,方便浏览修改sql语句
  • jiuqiyuliang
  • jiuqiyuliang
  • 2015-04-28 08:08
  • 219377

什么叫持久层框架

学框架,为的是什么? 不就是为了更方便的,更容易的干事么?【坏笑】 我刚开始是通过 * Hibernate* 这个框架 听说的这个概念。下面就对 持久层这个令我懵逼了好久的名词进行解释什么是持久层?持久是相对于瞬时来说的,* 持久层,可以理解成数据 保存在 数据库或者 硬盘一类可以保存很长时间的...
  • qq_33530388
  • qq_33530388
  • 2017-03-14 20:19
  • 2174

Spring框架:Spring与持久化

Spring的持久化用于简化数据的操作。 数据源 数据源有多种类型:JNDI、连接池、JDBC。 JNDI的配置方法。例子中使用Tomcat作为Web容器。首先要在context.xml中加上下面这段代码。 <Resource name="jdbc/TestD...
  • caipeichao2
  • caipeichao2
  • 2014-10-08 22:53
  • 2160

UAP的持久化框架

持久化框架 简述: 为了简化对数据库访问时的连接、参数、结果处理等工作,同时为了将对数据库的SQL脚本执行转换为对数据对象的操作,UAP提出了JDBC框架。 UAP的JBBC框架分为三层,JDBC框架层负责处理数据库连接、会话、参数设置、查询结果处理等功能,并负责将对数据对象的操作转换为相应的SQ...
  • C1248770189
  • C1248770189
  • 2016-12-28 09:19
  • 504

饿了么开源项目:便捷高效的Android数据持久化存储框架

Android应用开发时经常要对许多数据进行持久化存储,便于以后访问。对于int、double、boolean这些基本数据,可以使用SharedPreference。对于一些对象,往SharedPreference里存储的时候需要使用序列化技术。如果对象很大,或者碰到列表、数组等结构,就必须使用数据...
  • u012077163
  • u012077163
  • 2016-05-17 16:29
  • 6200

python数据持久化

Python的数据持久化操作主要是六类:普通文件、DBM文件、Pickled对象存储、shelve对象存储、对象数据库存储、关系数据库存储。         普通文件不解释了,DBM就是把字符串的键值对存储在文件里:   ...
  • pete_lin
  • pete_lin
  • 2015-08-06 14:46
  • 1263
    个人资料
    • 访问:3240679次
    • 积分:34887
    • 等级:
    • 排名:第148名
    • 原创:357篇
    • 转载:35篇
    • 译文:9篇
    • 评论:734条
    友情链接
    我的偶像
    个人主页
      GitHub
    放松一下
    博客专栏
    最新评论
    版权信息
    去除本页广告
    图片炸弹装填中...

        
    [img=赞一个]http://bpic.588ku.com/element_origin_min_pic/16/12/12/0d96da96cf36505736c09d63832eaac8.jpg[/img]