首页 > 代码库 > 封装JDBC:实现简单ORM框架lfdb

封装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 =http://www.mamicode.com/ 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也不少,性能就更加不要说了,写这个是为了学习,很多地方理解有误的,还望各路大神指出。

六、附件

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

文件说明:

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

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

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