封装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 等类似第三方类库了,不好意思,后边的 ...
随机推荐
- JavaScript高级程序设计12.pdf
第六章 面向对象的程序设计 ECMA中有两种属性:数据属性和访问器属性 数据属性的特性 [[Configurable]] 表示是否通过delete删除属性,是否重新定义属性,是否能把属性修改为访问器属 ...
- Android定义的路径全局变量
Android定义的路径全局变量 ifeq (,$(strip $(OUT_DIR))) OUT_DIR := $(TOPDIR)out endif DEBUG_OUT_DIR := $(OUT_DI ...
- 爬虫技术浅析 | z7y Blog
爬虫技术浅析 | z7y Blog 爬虫技术浅析
- z
360导航_新一代安全上网导航 http://www.codeproject.com/Articles/636730/Distributed-caching-using-Redis-server-wi ...
- 12个强大的Web服务测试工具
在过去的几年中,web服务或API的普及和使用有所增加. web服务或API是程序或软件组件的集合,可以帮助应用程序进行交互或通过形成其他应用程序或服务器之间的连接执行一些进程/事务处理.基本上有两种 ...
- js中return、return true、return false的区别
一.返回控制与函数结果, 语法为:return 表达式; 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果 二.返回控制, 无函数结果,语法为:return; 在大多数情况下,为事件 ...
- java读取图片的(尺寸、拍摄日期、标记)等EXIF信息
1.metadata-extractor是 处理图片EXIF信息的开源项目,最新代码及下载地址:https://github.com/drewnoakes/metadata-extractor 2.本 ...
- Android 下用 Pull 解析和生成 XML
Java 中是可以用 SAX 和 DOM 解析 XML 的,虽然在 Android 下也可以用这2中方式,但是还是推荐用 Pull.Pull 使用简单,效率相对高,Android 下是集成了 Pul ...
- 初次接触GWT,知识点总括
初次接触GWT,知识点概括 前言 本人最近开始研究 GWT(Google Web Toolkit) ,现将个人的一点心得贴出来,希望对刚开始接触 GWT的程序员们有所帮助,也欢迎讨论,共同进步. 先说 ...
- [Javascript] Using JSHint for Linting with Gulp
gulpfile.js var gulp = require('gulp'); var jshint = require('gulp-jshint'); var stylish = require(' ...