封装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 等类似第三方类库了,不好意思,后边的 ...
随机推荐
- 使用VisualStudio进行单元测试之四 顺序测试
前文中所提到的测试都是针对一个方法进行的独立测试,即使是同事测试多个方法,他们之间也没有影响.但是在实际的生产过程中,更多的情况是方法与方法之间是存在相互的逻辑关系的,所以也就有了今天要介绍的顺序测试 ...
- typedef用法小结
typedef用法小结- - 注意:本文转自网络,版权归原作者所有. typedef typedef用法小结- - 这两天在看程序的时候,发现很多地方都用到typedef,在结构体定义,还有一些数组等 ...
- 阿里云如何添加多个网站 for Linux(绑定域名)
我们可以通过.htaccess文件来达到一个空间帮顶多个域名的效果,即域名1访问空间上webroot下的目录1(即二级目录),域名2访问空间上webroot下的目录2,等等.二级目录名为fuli,需要 ...
- Java Struts2 的请求处理流程详解
一.Struts2的处理流程: 客户端产生一个HttpServletRequest的请求,该请求被提交到一系列的标准过滤器(Filter)组建链中(如ActionContextCleanUp:它主要是 ...
- iOS获取经纬度
在ios8.0以上获取经纬度时,需要申请授权,否则不能定位 第一步: 在 HomeViewController.m @interfaceHomeViewController ()<CLLoc ...
- Java宝典
本人最近参加了几家公司的面试,在其中发现了不少笔试题,虽然是平常再简单不过的,但一不小心还是会出错.今天特意找时间写下来和大家分享. 1.访问控制符权限问题. 同一个包中 同一个类中 不同包的子类 ...
- 通过代码来执行testng.xml
大多数时候,我们都是通过Eclipse IDE上的操作命令来执行testng 框架下的case 运行.那如果我们不想通过这种方式,而是想通过代码调用来实现执行该怎么办?下面是我搜集的两种方式供大家参考 ...
- c#基础语言编程-正则表达式应用
引言 在不同语言中虽正则表达式一样,但应用函数还是有所区别,在c#语言中使用Regex. 可以通过以下两种方式之一使用正则表达式引擎: 通过调用 Regex 类的静态方法. 方法参数包含输入字符串和正 ...
- Android color(颜色) 在XML文件和java代码中
Android color(颜色) 在XML文件和java代码中,有需要的朋友可以参考下. 1.使用Color类的常量,如: int color = Color.BLUE;//创建一个蓝色 是使用An ...
- Nubia Z5S(高通公司MSM8974) QHSUSB_BULK砖的方法节省模式(随着win7在恢复recovery分区案例)
Nubia Z5S在某些异常情况或按组合键进入QHSUSB_BULK状态, 这种模式的现象, 猜想windows(实例win7)即使在数据线, 它会出现在计算机n载,甚至会提示要格式化某些分区(这里要 ...