封装JDBC:实现简单ORM框架lfdb
作者: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
三、使用
一个东西,要想明白他的原理,必须先要知道怎么使用:
- 创建Configuration对象:构造时加载配置文件。
- 使用Configuration对象创建一个SessionFactory对象:configuration.buildSessionFactory()。
- 获取Session。
- 使用session执行操作。
- 关闭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的更多相关文章
- JDBC 利用反射技术将查询结果封装为对象(简单ORM实现)
ORM(Object Relational Mapping)对象关系映射 public class ORMTest { public static void main(String[] args) t ...
- JAVA描述的简单ORM框架
抽了点时间自己写了个ORM,主要是为了复习JAVA泛型,映射,注解方面的知识.如需代码,可前往:https://github.com/m2492565210/java_orm自行下载 框架的类结构如下 ...
- 常见ORM框架及JDBC操作工具类
在Java 程序里面去连接数据库,最原始的办法是使用JDBC 的API.我们先来回顾一下使用JDBC 的方式,我们是怎么操作数据库的. // 注册JDBC 驱动 Class.forName(" ...
- mybatis(一)常见ORM框架及JDBC操作工具类
转载:https://www.cnblogs.com/wuzhenzhao/p/11075569.html 在Java 程序里面去连接数据库,最原始的办法是使用JDBC 的API.我们先来回顾一下 ...
- PHP ORM框架与简单代码实现(转)
对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据 ...
- 重学 Java 设计模式:实战中介者模式「按照Mybaits原理手写ORM框架,给JDBC方式操作数据库增加中介者场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同龄人的差距是从什么时候拉开的 同样的幼儿园.同样的小学.一样 ...
- 简单实用的Android ORM框架TigerDB
TigerDB是一个简单的Android ORM框架,它能让你一句话实现数据库的增删改查,同时支持实体对象的持久化和自动映射,同时你也不必关心表结构的变化,因为它会自动检测新增字段来更新你的表结构. ...
- 【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)
文件夹 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器開始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入 ...
- .Net Core 简单定时任务框架封装
有段日子没有更新,写点东西冒个泡 .这篇文章过来讲个小东西,也是大家在日常开发中也经常需要面临的问题:后台定时任务处理.估计大家看到这句就已经联想到 QuartZ 等类似第三方类库了,不好意思,后边的 ...
随机推荐
- 【转】 log4cpp 的使用
[转自] http://sogo6.iteye.com/blog/1154315 Log4cpp配置文件格式说明 log4cpp有3个主要的组件:categories(类别).append ...
- Java Executor 框架学习总结
大多数并发都是通过任务执行的方式来实现的.一般有两种方式执行任务:串行和并行. class SingleThreadWebServer { public static void main(String ...
- VirtualBox的usb支持
解决usb支持: 0. 下载Oracle_VM_VirtualBox_Extension_Pack-4.0.4-70112.vbox-extpack后双击即可采用VB安装,若还是用ark打开可人为设置 ...
- Java中的一些常见错误
1.空指针错误 在java数组的使用中,有时候需要对字符串数组中的元素进行对比.那么当元素不为null时,程序会正常运行:然而,一旦对比的元素为null,那么程序就会出现空指针错误. 解决方法:加入保 ...
- bzoj4448 SCOI2015 情报传递 message
传送门bzoj4448 题解 离线之后构建树上主席树,每个点的线段树维护到根路径的信息,不用链剖(我的链剖只是拿来求\(\mathrm{lca}\)的),时空复杂度\(O(n\log{n})\). c ...
- 一个可视化的retrospective网站
IdeaBoardz - Brainstorm, Retrospect, Collaborate是一个可视化的retrospective,brainstorm的网站,比较简单易用,可以导出pdf和ex ...
- js事件的方法
事件的方法:onclick 鼠标单击ondblclick 鼠标双击onkeyup 按下并释放键盘上的一个键时触发 onchange 文本内容或 ...
- poj1673
所谓Exocenter就是垂心.不难证明. #include <iostream> #include <math.h> #include <stdio.h> str ...
- Delphi TWebBrowser
Delphi WebBrowser控件的使用 WebBrowser控件属性:1.Application 如果该对象有效,则返回掌管WebBrowser控件的应用程序实现的自动化对象(IDis ...
- Node.js小Httpserver
须要说明两点: 1 程序文件hello.js需用记事本另存为utf-8格式的hello.js watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamVhcGVk ...