作者:Vinkn 来自http://www.cnblogs.com/Vinkn/

一、简介

  框架就是一组可重用的构件,LZ自己写的姑且就叫微型小框架:lfdb。LZ也对其他的ORM框架没有什么了解,现在只会一个Hibernate,还是勉强会,什么懒加载,什么二级缓存这些太高级了,平时也没用到,但是用了就要明白个所以然,自己揣摩着模仿写个小框架,但是没有研究过Hibernate是怎么写的,也不清楚系统的架构,凭借自己的感觉写的,很多地方理解上有错,很多代码写得也很垃圾,还没很多东西没有考虑到,比如当个表的映射关系,数据库外键的关联等等。希望各位大神给与一点点指点。

二、结构

1、Configuration:配置文件类,加载并解析配置文件,生成实例化的SessionFactory。

2、SessionFactory:接口,加载数据库驱动,生成Session放入SessionPool(池)中,提供Session。

  >>具体实现:SessionFactoryImpl

3、Session:接口,提供事务管理,包含对象的增删改查,以及sql执行。

  >>具体实现:SessionImpl

4、SQLBuilder:接口,创建增删改差的sql语句。可以针对不同的数据库设计不同的实现。

  >>具体实现:Mysql SQLBuilder

三、使用

一个东西,要想明白他的原理,必须先要知道怎么使用:

  1. 创建Configuration对象:构造时加载配置文件。
  2. 使用Configuration对象创建一个SessionFactory对象:configuration.buildSessionFactory()。
  3. 获取Session。
  4. 使用session执行操作。
  5. 关闭session。

代码如下:

 public static void main(String[] args) {
         //生成配置对象
         Configuration configuration=new Configuration("dbtest/test/config.xml");
         //生成Session工厂
         SessionFactory sessionFactory=configuration.buildSessionFactory();
         //获取Session
         Session session=sessionFactory.getSession();
         Student student=new Student();
         student.setSex("男");
         student.setSname("德玛西亚");
         student.setCollege("超神学院");
         student.setSno("1212121");
         //执行事务
         session.add(student);
         //关闭Session
         session.colse();
     }

四、实现

1、  Configuration类实现

 /**
  * Configuration:参数配置类
  *
  * @author ZWQ
  * @version 1.0
  *          <p>
  *          通过该类使用配置文件建立SessionFactory。
  *          </p>
  * **/
 public class Configuration {
     //数据库驱动
     private String driver = "";
     //连接url
     private String url = "";
     //用户名
     private String user = "";
     //密码
     private String password = "";
     //Session池初始大小
     private int initsize = 5;
     //Session池最大大小
     private int maxsize = 10;

     /**
      * 默认构造方法,使用项目根目录src下面的lfdb.config.xml文件
      */
     public Configuration() {
         initConfig("lfdb.config.xml");
     }

     /**
      * 带参构造方法,使用项目自定义的.xml文件
      * <p>
      * 根目录下使用为Configuration configuration=new Configuration("config.xml");
      * </p>
      * <p>
      * 具体包下面使用为Configuration configuration=new Configuration("demo/config.xml");
      * </p>
      *
      * @param configFile
      *            :String 需要使用的lfdb配置文件
      */
     public Configuration(String configFile) {
         initConfig(configFile);
     }

     private void initConfig(String configFile) {
         try {
             // 获取配置文件输入流
             InputStream configInputStream = getClass().getClassLoader().getResourceAsStream(configFile);
             if (configInputStream == null) {
                 System.out.println(">>>>>>>配置文件未找到");
                 new FileNotFoundException();
             }
             // XML文件解析
             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
             dbf.setIgnoringComments(true);
             dbf.setIgnoringElementContentWhitespace(true);
             DocumentBuilder db = dbf.newDocumentBuilder();
             System.out.println(">>>>>>>解析配置文件...");
             Document document = db.parse(configInputStream);
             Element root = document.getDocumentElement();
             NodeList config = root.getChildNodes();
             // 读取配置参数内容
             for (int i = 0; i < config.getLength(); i++) {
                 Node node = config.item(i);
                 String nodeName = node.getNodeName();
                 if (nodeName.equalsIgnoreCase("driver")) {
                     driver = node.getFirstChild().getNodeValue().trim();
                 } else if (nodeName.equalsIgnoreCase("url")) {
                     url = node.getFirstChild().getNodeValue().trim();
                 } else if (nodeName.equalsIgnoreCase("user")) {
                     user = node.getFirstChild().getNodeValue().trim();
                 } else if (nodeName.equalsIgnoreCase("password")) {
                     password = node.getFirstChild().getNodeValue().trim();
                 } else if (nodeName.equalsIgnoreCase("initsize")) {
                     initsize = Integer.parseInt(node.getFirstChild().getNodeValue().trim());
                 } else if (nodeName.equalsIgnoreCase("maxsize")) {
                     maxsize = Integer.parseInt(node.getFirstChild().getNodeValue().trim());
                 }
             }
             System.out.println(">>>>>>>配置文件解析完成");
         } catch (Exception e) {
             e.printStackTrace();
             new RuntimeException();
         }
     }

     /**
      * 建立一个SessionFactory
      *
      * @return SessionFactory 返回一个SessionFactory的实例
      * **/
     public SessionFactory buildSessionFactory() {
         return new SessionFactoryImpl(this);
     }

2、  SessionFactoryImpl类实现

 public class SessionFactoryImpl implements SessionFactory {
     // Session池
     LinkedList<Session> sessionPool = new LinkedList<Session>();
     // 与Configuration中参数相对应
     private String driver;
     private String url;
     private String user;
     private String password;
     private int initsize;
     private int maxsize;
     // 当前Session池最大大小
     private int currentsize;

     // 通过Configuration构造,并加载驱动,初始化Session池
     public SessionFactoryImpl(Configuration configuration) {
         driver = configuration.getDriver();
         url = configuration.getUrl();
         user = configuration.getUser();
         password = configuration.getPassword();
         initsize = configuration.getInitsize();
         maxsize = configuration.getMaxsize();
         loadDriver();
         for (int i = 0; i < initsize; i++) {
             createSession();
         }
     }

     // 创建Session,放入Session池
     private void createSession() {
         if (currentsize < maxsize) {
             try {
                 Connection connection = DriverManager.getConnection(url, user, password);
                 //当前只支持MySql语句的生成
                 SQLBuilder sqlBuilder = new MysqlSQLBuilder();
                 sessionPool.addLast(new SessionImpl(connection, sqlBuilder, sessionPool));
                 currentsize++;
             } catch (Exception e) {
                 System.out.println(">>>>>>>创建Session出错");
                 e.printStackTrace();
             }

         } else {
             System.out.println(">>>>>>>已超出Session配置最大容量");
         }
     }

     // 加载数据库驱动
     private void loadDriver() {
         System.out.println(">>>>>>>加载数据库驱动...");
         try {
             // 加载数据库驱动.
             Class.forName(driver);
             System.out.println(">>>>>>>加载数据库驱动成功...");
         } catch (ClassNotFoundException e) {
             System.out.println(">>>>>>>加载数据库驱动失败...");
             e.printStackTrace();
             new RuntimeException();
         }
     }

     @Override
     public Session getSession() {
         synchronized (sessionPool) {
             if (this.sessionPool.size() > 0) {
                 return this.sessionPool.removeFirst();
             } else {
                 createSession();
                 if (this.sessionPool.size() > 0) {
                     return this.sessionPool.removeFirst();
                 } else {
                     System.out.println(">>>>>>>>已经没有session");
                     return null;
                 }
             }
         }
     }

     @Override
     public void closeSession(Session session) {
         sessionPool.addLast(session);
         session=null;
     }
 }

3、  SessionImpl类实现:部分代码

     @Override
     public void add(Object object) {
         try {
             String sql = sqlBuilder.createAddSQL(object);
             Statement statement = connection.createStatement();
             statement.executeUpdate(sql);
         } catch (Exception e) {
             System.out.println(">>>>>>>>添加对象失败");
             e.printStackTrace();
         }
     }
   @Override
     public <T> List<T> get(Class<T> clazz, String sql) {
         List<T> result = null;
         try {
             Statement statement = connection.createStatement();
             ResultSet rs = statement.executeQuery(sql);
             BasicRowProcessor basicRowProcessor = new BasicRowProcessor();
             result = basicRowProcessor.toBeanList(rs, clazz);
         } catch (SQLException e) {
             System.out.println(">>>>>>>获取结果出错");
             e.printStackTrace();
         }
         return result;
     }

4、  MysqlSQLBuilder类实现:部分代码

 @Override
     public String createAddSQL(Object object) {
         StringBuilder sql = new StringBuilder();
         StringBuilder columns = new StringBuilder();
         StringBuilder values = new StringBuilder();
         sql.append("insert into ");
         sql.append(object.getClass().getSimpleName());

         try {
             Field[] fields = object.getClass().getDeclaredFields();
             boolean firststate = false;
             for (Field field : fields) {
                 field.setAccessible(true);
                 if (field.getName().toString().toLowerCase().equals("id")) {
                     continue;
                 }
                 if (firststate) {
                     columns.append(",");
                     values.append(",");

                 } else {
                     firststate = true;
                 }
                 String column = field.getName();
                 Object value = field.get(object);
                 columns.append(column);
                 if (field.getType() == String.class) {
                     values.append("'");
                     values.append(value);
                     values.append("'");
                 } else {
                     values.append(value);
                 }
             }
             sql.append("(");
             sql.append(columns);
             sql.append(") values(");
             sql.append(values);
             sql.append(")");
         } catch (IllegalArgumentException | IllegalAccessException e) {
             System.out.println(">>>>>>>创建插入sql语句失败");
             e.printStackTrace();
         }
         return sql.toString();
     }

五、总结

  写一个框架是需要用心的事情,需要考虑到使用者的方便性,以及功能的完整性与健壮性。

  这个只是一个半成品,很多地方还没有实现,bug也不少,性能就更加不要说了,写这个是为了学习,很多地方理解有误的,还望各路大神指出。

六、附件

项目文件夹:lfdb

下载地址:http://pan.baidu.com/s/1bn1Y6BX

如果有什么疑问或者建议,请联系我

文件说明:

1、lfdb源码.zip  :lfdb的源代码

2、lfdb_1.2.jar  :可以直接使用的jar包

3、lfdbdemo源码.zip  :lfdb示例的源代码

封装JDBC:实现简单ORM框架lfdb的更多相关文章

  1. JDBC 利用反射技术将查询结果封装为对象(简单ORM实现)

    ORM(Object Relational Mapping)对象关系映射 public class ORMTest { public static void main(String[] args) t ...

  2. JAVA描述的简单ORM框架

    抽了点时间自己写了个ORM,主要是为了复习JAVA泛型,映射,注解方面的知识.如需代码,可前往:https://github.com/m2492565210/java_orm自行下载 框架的类结构如下 ...

  3. 常见ORM框架及JDBC操作工具类

    在Java 程序里面去连接数据库,最原始的办法是使用JDBC 的API.我们先来回顾一下使用JDBC 的方式,我们是怎么操作数据库的. // 注册JDBC 驱动 Class.forName(" ...

  4. mybatis(一)常见ORM框架及JDBC操作工具类

      转载:https://www.cnblogs.com/wuzhenzhao/p/11075569.html 在Java 程序里面去连接数据库,最原始的办法是使用JDBC 的API.我们先来回顾一下 ...

  5. PHP ORM框架与简单代码实现(转)

    对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据 ...

  6. 重学 Java 设计模式:实战中介者模式「按照Mybaits原理手写ORM框架,给JDBC方式操作数据库增加中介者场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同龄人的差距是从什么时候拉开的 同样的幼儿园.同样的小学.一样 ...

  7. 简单实用的Android ORM框架TigerDB

    TigerDB是一个简单的Android ORM框架,它能让你一句话实现数据库的增删改查,同时支持实体对象的持久化和自动映射,同时你也不必关心表结构的变化,因为它会自动检测新增字段来更新你的表结构. ...

  8. 【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)

    文件夹      [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器開始(八)      [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入 ...

  9. .Net Core 简单定时任务框架封装

    有段日子没有更新,写点东西冒个泡 .这篇文章过来讲个小东西,也是大家在日常开发中也经常需要面临的问题:后台定时任务处理.估计大家看到这句就已经联想到 QuartZ 等类似第三方类库了,不好意思,后边的 ...

随机推荐

  1. bzoj 1923 [Sdoi2010]外星千足虫(高斯消元+bitset)

    1923: [Sdoi2010]外星千足虫 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 634  Solved: 397[Submit][Status ...

  2. bzoj3065: 带插入区间K小值

    无聊来写了下 一开始发现树高是O(n)的,然后就MLE了,进去看了下发现没有重构! 看了半天发现调用错了函数 然后进去又发现不满足sz = ch[0]->sz + ch[1]->sz + ...

  3. 「S-A-L-T-A」项目失败总结!

    前言: 从2013年8月20日进入这个项目开始,到现在12月12日. 从项目详细设计开始,到现在连SI2阶段的疏通测试都没有完成! (现在,这个项目好像已经不需要我们再做下去了...) 项目失败原因总 ...

  4. 解决apache服务器本地可以访问,同局域网内他人不能访问的问题(转)

    问题提出:发现这个问题时,我同学让我做好的网页小案例给他看看,我是用wamp搭建的本地服务器,本地访问地址例如为: http://localhost/Dedecms/index.php 对于其他人要访 ...

  5. 设计模式(4) -- 单例模式(Singleton)

    设计模式(4)  -- 单例模式(Singleton) 试想一个读取配置文件的需求,创建完读取类后通过New一个类的实例来读取配置文件的内容,在系统运行期间,系统中会存在很多个该类的实例对象,也就是说 ...

  6. dreamvc框架(一)ioc容器的集成

    我的dreamvc框架最终写得差点儿相同了,借鉴了非常多开源框架,SpringMVC.Struts2等,眼下放在github上面.地址请猛戳我 写得差点儿相同了,是要写一个总结,把自己当时的思路记录下 ...

  7. Objective-C--Runtime机制

    个人理解: 简单来说,Objective-C runtime是一个实现Objective-C语言的C库.对象可以用C语言中的结构体表示,而方法(methods)可以用C函数实现.事实上,他们 差不多也 ...

  8. cocoaPods下载使用记录

    cocoaPods下载使用记录 参考地址: 如何在Mac OS 上安装运行Ruby运行环境 http://www.cnblogs.com/daguo/p/4097263.html cocoaPods安 ...

  9. Red Hat Enterprise Linux 6安装步骤

    首先,准备安装环境,此次实验是在VMware Workstation虚拟机环境下来实现的,下面就开始安装: 点击Create a New Vitrual Machine来新建一个虚拟机,选择自定义安装 ...

  10. mvc4+jquerymobile页面加载时无法绑定事件

    问题:在view里写js,在页面第一次加载完成后,无法触发事件, 如:按钮click事件,已经在$(function(){  添加了click });但就是无法触发,必须刷新下才可以. 原因分析: 主 ...