zoukankan      html  css  js  c++  java
  • 封装JDBC:实现简单ORM框架lfdb

    一、简介

      框架就是一组可重用的构件,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。

    代码如下:

     1 public static void main(String[] args) {
     2         //生成配置对象
     3         Configuration configuration=new Configuration("dbtest/test/config.xml");
     4         //生成Session工厂
     5         SessionFactory sessionFactory=configuration.buildSessionFactory();
     6         //获取Session
     7         Session session=sessionFactory.getSession();
     8         Student student=new Student();
     9         student.setSex("男");
    10         student.setSname("德玛西亚");
    11         student.setCollege("超神学院");
    12         student.setSno("1212121");
    13         //执行事务
    14         session.add(student);
    15         //关闭Session
    16         session.colse();
    17     }

    四、实现

    1、  Configuration类实现

      1 /**
      2  * Configuration:参数配置类
      3  * 
      4  * @author ZWQ
      5  * @version 1.0
      6  *          <p>
      7  *          通过该类使用配置文件建立SessionFactory。
      8  *          </p>
      9  * **/
     10 public class Configuration {
     11     //数据库驱动
     12     private String driver = "";
     13     //连接url
     14     private String url = "";
     15     //用户名
     16     private String user = "";
     17     //密码
     18     private String password = "";
     19     //Session池初始大小
     20     private int initsize = 5;
     21     //Session池最大大小
     22     private int maxsize = 10;
     23 
     24     /**
     25      * 默认构造方法,使用项目根目录src下面的lfdb.config.xml文件
     26      */
     27     public Configuration() {
     28         initConfig("lfdb.config.xml");
     29     }
     30 
     31     /**
     32      * 带参构造方法,使用项目自定义的.xml文件
     33      * <p>
     34      * 根目录下使用为Configuration configuration=new Configuration("config.xml");
     35      * </p>
     36      * <p>
     37      * 具体包下面使用为Configuration configuration=new Configuration("demo/config.xml");
     38      * </p>
     39      * 
     40      * @param configFile
     41      *            :String 需要使用的lfdb配置文件
     42      */
     43     public Configuration(String configFile) {
     44         initConfig(configFile);
     45     }
     46 
     47     private void initConfig(String configFile) {
     48         try {
     49             // 获取配置文件输入流
     50             InputStream configInputStream = getClass().getClassLoader().getResourceAsStream(configFile);
     51             if (configInputStream == null) {
     52                 System.out.println(">>>>>>>配置文件未找到");
     53                 new FileNotFoundException();
     54             }
     55             // XML文件解析
     56             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     57             dbf.setIgnoringComments(true);
     58             dbf.setIgnoringElementContentWhitespace(true);
     59             DocumentBuilder db = dbf.newDocumentBuilder();
     60             System.out.println(">>>>>>>解析配置文件...");
     61             Document document = db.parse(configInputStream);
     62             Element root = document.getDocumentElement();
     63             NodeList config = root.getChildNodes();
     64             // 读取配置参数内容
     65             for (int i = 0; i < config.getLength(); i++) {
     66                 Node node = config.item(i);
     67                 String nodeName = node.getNodeName();
     68                 if (nodeName.equalsIgnoreCase("driver")) {
     69                     driver = node.getFirstChild().getNodeValue().trim();
     70                 } else if (nodeName.equalsIgnoreCase("url")) {
     71                     url = node.getFirstChild().getNodeValue().trim();
     72                 } else if (nodeName.equalsIgnoreCase("user")) {
     73                     user = node.getFirstChild().getNodeValue().trim();
     74                 } else if (nodeName.equalsIgnoreCase("password")) {
     75                     password = node.getFirstChild().getNodeValue().trim();
     76                 } else if (nodeName.equalsIgnoreCase("initsize")) {
     77                     initsize = Integer.parseInt(node.getFirstChild().getNodeValue().trim());
     78                 } else if (nodeName.equalsIgnoreCase("maxsize")) {
     79                     maxsize = Integer.parseInt(node.getFirstChild().getNodeValue().trim());
     80                 }
     81             }
     82             System.out.println(">>>>>>>配置文件解析完成");
     83         } catch (Exception e) {
     84             e.printStackTrace();
     85             new RuntimeException();
     86         }
     87     }
     88 
     89     /**
     90      * 建立一个SessionFactory
     91      * 
     92      * @return SessionFactory 返回一个SessionFactory的实例
     93      * **/
     94     public SessionFactory buildSessionFactory() {
     95         return new SessionFactoryImpl(this);
     96     }

    2、  SessionFactoryImpl类实现

     1 public class SessionFactoryImpl implements SessionFactory {
     2     // Session池
     3     LinkedList<Session> sessionPool = new LinkedList<Session>();
     4     // 与Configuration中参数相对应
     5     private String driver;
     6     private String url;
     7     private String user;
     8     private String password;
     9     private int initsize;
    10     private int maxsize;
    11     // 当前Session池最大大小
    12     private int currentsize;
    13 
    14     // 通过Configuration构造,并加载驱动,初始化Session池
    15     public SessionFactoryImpl(Configuration configuration) {
    16         driver = configuration.getDriver();
    17         url = configuration.getUrl();
    18         user = configuration.getUser();
    19         password = configuration.getPassword();
    20         initsize = configuration.getInitsize();
    21         maxsize = configuration.getMaxsize();
    22         loadDriver();
    23         for (int i = 0; i < initsize; i++) {
    24             createSession();
    25         }
    26     }
    27 
    28     // 创建Session,放入Session池
    29     private void createSession() {
    30         if (currentsize < maxsize) {
    31             try {
    32                 Connection connection = DriverManager.getConnection(url, user, password);
    33                 //当前只支持MySql语句的生成
    34                 SQLBuilder sqlBuilder = new MysqlSQLBuilder();
    35                 sessionPool.addLast(new SessionImpl(connection, sqlBuilder, sessionPool));
    36                 currentsize++;
    37             } catch (Exception e) {
    38                 System.out.println(">>>>>>>创建Session出错");
    39                 e.printStackTrace();
    40             }
    41 
    42         } else {
    43             System.out.println(">>>>>>>已超出Session配置最大容量");
    44         }
    45     }
    46 
    47     // 加载数据库驱动
    48     private void loadDriver() {
    49         System.out.println(">>>>>>>加载数据库驱动...");
    50         try {
    51             // 加载数据库驱动.
    52             Class.forName(driver);
    53             System.out.println(">>>>>>>加载数据库驱动成功...");
    54         } catch (ClassNotFoundException e) {
    55             System.out.println(">>>>>>>加载数据库驱动失败...");
    56             e.printStackTrace();
    57             new RuntimeException();
    58         }
    59     }
    60 
    61     @Override
    62     public Session getSession() {
    63         synchronized (sessionPool) {
    64             if (this.sessionPool.size() > 0) {
    65                 return this.sessionPool.removeFirst();
    66             } else {
    67                 createSession();
    68                 if (this.sessionPool.size() > 0) {
    69                     return this.sessionPool.removeFirst();
    70                 } else {
    71                     System.out.println(">>>>>>>>已经没有session");
    72                     return null;
    73                 }
    74             }
    75         }
    76     }
    77 
    78     @Override
    79     public void closeSession(Session session) {
    80         sessionPool.addLast(session);
    81         session=null;
    82     }
    83 }

    3、  SessionImpl类实现:部分代码

     1     @Override
     2     public void add(Object object) {
     3         try {
     4             String sql = sqlBuilder.createAddSQL(object);
     5             Statement statement = connection.createStatement();
     6             statement.executeUpdate(sql);
     7         } catch (Exception e) {
     8             System.out.println(">>>>>>>>添加对象失败");
     9             e.printStackTrace();
    10         }
    11     }
    12   @Override
    13     public <T> List<T> get(Class<T> clazz, String sql) {
    14         List<T> result = null;
    15         try {
    16             Statement statement = connection.createStatement();
    17             ResultSet rs = statement.executeQuery(sql);
    18             BasicRowProcessor basicRowProcessor = new BasicRowProcessor();
    19             result = basicRowProcessor.toBeanList(rs, clazz);
    20         } catch (SQLException e) {
    21             System.out.println(">>>>>>>获取结果出错");
    22             e.printStackTrace();
    23         }
    24         return result;
    25     }

    4、  MysqlSQLBuilder类实现:部分代码

     1 @Override
     2     public String createAddSQL(Object object) {
     3         StringBuilder sql = new StringBuilder();
     4         StringBuilder columns = new StringBuilder();
     5         StringBuilder values = new StringBuilder();
     6         sql.append("insert into ");
     7         sql.append(object.getClass().getSimpleName());
     8 
     9         try {
    10             Field[] fields = object.getClass().getDeclaredFields();
    11             boolean firststate = false;
    12             for (Field field : fields) {
    13                 field.setAccessible(true);
    14                 if (field.getName().toString().toLowerCase().equals("id")) {
    15                     continue;
    16                 }
    17                 if (firststate) {
    18                     columns.append(",");
    19                     values.append(",");
    20 
    21                 } else {
    22                     firststate = true;
    23                 }
    24                 String column = field.getName();
    25                 Object value = field.get(object);
    26                 columns.append(column);
    27                 if (field.getType() == String.class) {
    28                     values.append("'");
    29                     values.append(value);
    30                     values.append("'");
    31                 } else {
    32                     values.append(value);
    33                 }
    34             }
    35             sql.append("(");
    36             sql.append(columns);
    37             sql.append(") values(");
    38             sql.append(values);
    39             sql.append(")");
    40         } catch (IllegalArgumentException | IllegalAccessException e) {
    41             System.out.println(">>>>>>>创建插入sql语句失败");
    42             e.printStackTrace();
    43         }
    44         return sql.toString();
    45     }

    五、总结

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

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

     

     

     

     

  • 相关阅读:
    【ABAP系列】SAP 系统的消息类型分析 MESSAGE TYPE
    【FICO系列】SAP FICO-模块 关于固定资产年结和折旧的问题
    【ABAP系列】SAP ABAP 刷新SCREEN的方法
    【ABAP系列】SAP ABAP 控制ALV单元格编辑后获取新的数值
    【ABAP系列】SAP ABAP系统变量及注释
    【EWM系列】SAP EWM凭证对象表概览
    【EWM系列】SAP EWM中仓库任务WT创建的函数
    教你快速录制gif动图
    阿里巴巴的26款超神Java开源项目!
    HTTP和HTTPS协议,看一篇就够了
  • 原文地址:https://www.cnblogs.com/vikde/p/3741789.html
Copyright © 2011-2022 走看看