源码地址:https://github.com/beijing-penguin/Myjdbc
MVC项目中的具体使用方式,https://github.com/beijing-penguin/ucenter-web-manage.git
我为什么要写这个Myjdbc?
毕业后的一段时间一直在用hibernate,和mybatis框架,后来感觉这种框架太繁琐,比如,现在要用java读取客户给的一个excel表格,读取里面的数据后插入到数据库,这样一个小的需求,我都需要配置hibernate文件、配置mybatis的文件,对我来说,太麻烦了,因为我是懒人,不喜欢太多的东西。
我记得有一次用hibernate框架管理多数据源的时候,出现一个问题,当第一个数据源的连接提交后,第二个提交就会报错,当时查过一些办法,但是任然很难快定位问题的根本原因。并且做开发以来,所用过第三方JDBC框架或多或少的会在某些业务上面变得有些很不灵活,或者说某个地方我需要去查很多资料才能用好这个框架,其次框架本身出现bug,也很难调试和改变源码。总之有关数据库的操作,已经不是一个框架能够很好地去解决的问题了,它需要的是一种思想,需要结合某种特定高度灵活的框架,作为底层基础,来适应不同的需求。于是基于要做好一个高度灵活可扩展易调试的框架或者是理顺一个开发这种变态业务的思想,也并非易事。。于是本人便开始了Myjdbc的研究之旅。
聊聊我的Myjdbc
我很高兴,我有一天在群里告知各位群友后,能够得到某些群友的反馈,说想研究一下(或者看看)我的框架。其实,如果说我的框架是需要"研究"后才能用的话,那么说明,我设计失败了。jdbc的框架,有那么多的人封装多,为什么我还要造轮子,我是个懒人,我更加不想造轮子,我想创新的是一个开发思想,或者说我只想快速开发,完成项目,然后喝着饮料,玩着手机坐在公司潇潇洒洒,即便出现bug,我也能秒秒钟定位问题的根本原因,并解决。那么为此MyJdbc诞生了,一个只属于自己框架,也是属于每个人自己的框架。。框架功能:数据库连接与数据库操作(增删改查),提供多数据源管理和多数据源下的弱事务操作(提交和回滚)。框架优点:轻量级高度灵活可扩展,可复用的组件,简单易用,可自行定义其他功能,非常方便的调试。框架缺点:1,不支持动态sql,2,暂时不支持分表分库,正在开发中......
Myjdbc如何使用及有哪些特点
建议,开发时,尽量拷贝源码到项目中使用。上线后稳定下来,可以考虑打包成Myjdbc.jar
要了解清楚怎么去调试和如何使用,首先请看我设计的目录结构
anno里是注解类,
config是全局的jdbc的配置,任何配置都可以在这里定义,比如是否在执行sql前打印sql日志?
core包,就是封装了原始的jdbc操作,且任何操作类的方法都只有3个参数,
JDBCProxy.java是一个动态代理类,使用方式可以如下面这段代码这么设计,当然,你可以改变代理类中的任何源码及设计来符合你的需求。
@Controller @RequestMapping("/user") public class LoginController {
private LoginService loginService = JDBCProxy.getInstance().getTarget(LoginService.class);
@RequestMapping("/login")
public String login(User user,HttpSession session,HttpServletRequest req) throws Exception{
User u = loginService.login(user);
}
}
package com.dc.module.system.service; import java.util.List; import java.util.Map; import org.dc.jdbc.anno.Transactional; import org.dc.jdbc.helper.DBHelper; import com.dc.commons.config.Configure; import com.dc.commons.entity.User; public class LoginService { private DBHelper accountDBHelper = new DBHelper(Configure.accSource); public User login(User user) throws Exception{ User u = accountDBHelper.selectOne("$login.getOneUser",User.class,user); return u; } }
比如下面这段DeleteOper.java的源码,
/**
* 删除操作
* @author dc
* @time 2015-8-17
*/
public class DeleteOper extends OperSuper{
private static DeleteOper deleteOper = new DeleteOper();
public static DeleteOper getInstance(){
return deleteOper;
}
public int delete(Connection conn,String sql,Object[] params) throws Exception{
return super.preparedAndExcuteSQL(conn, sql, params);
}
}
如果我封装的这段代码还不满足你的公司的项目需求,请自行写个方法,但是有且只有3个参数,如果3个参数不够,请及时给我反馈,并说明原因。
entity包,是作为sql元素相关信息的临时媒介。比如可以用来保存sql字符串和这个字符串所对象参数数组。
因为java语法并不支持执行一个方法,返回两个参数,就像这样的形式Object sql,param = getUser()这样的形式(lua语言支持)。
hepler包,就相当于最表面的应用级的工具,可以理解为view层。作为将底层方法透明可见的一种方式
init包。则为jdbc在前可以选择性执行init初始化的操作工具类在这个包下,比如需要加载xml文件中定义好的sql文件
utils包下面,目前主要定义的有反射获取方法名,java类型匹配及转化等工具。
使用案例如下面这段代码
package test;
import java.io.File;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dc.jdbc.config.JDBCConfig;
import org.dc.jdbc.core.ConnectionManager;
import org.dc.jdbc.helper.DBHelper;
import org.dc.jdbc.init.LoadSqlUtil;
import org.junit.Before;
import org.junit.Test;
import com.alibaba.druid.util.JdbcUtils;
public class JDBCTest {
private static DBHelper accDBHelper = new DBHelper(Configure.accSource);
private static DBHelper testDBHelper = new DBHelper(Configure.testSource);
@Before
public void initJdbc(){
try {
JDBCConfig.isPrintSqlLog = true;
LoadSqlUtil.loadSql("D:\\Git\\MyJdbc\\target\\classes\\test\\sql");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void select(){
try {
ConnectionManager.isTransaction.set(false);
/*start*/
Map<String,Object> map = testDBHelper.selectOne("select * from user limit 1");
List<Map<String,Object>> mapList = testDBHelper.selectList("select * from user");
/*end*/
Map<String,Object> map_WithParam1 = testDBHelper.selectOne("select * from user where name=? and age=? limit 1","dc",20);
User user = testDBHelper.selectOne("select name,age from user where name=? and age=? limit 1",User.class,"dc",20);
//只返回年龄,如数据的该字段没查到则返回的数据为null,那么用Integer类型接受即可,不然会报NullPointerException
//int age = testDBHelper.selectOne("select age from user where name=? and age=? limit 1",Integer.class,"dc",20);
Integer age = testDBHelper.selectOne("select age from user where name=? and age=? limit 1",Integer.class,"dc",20);
String name = testDBHelper.selectOne("select name from user where name=? and age=? limit 1",String.class,"dc",20);
Map<String,Object> map_WithParam1_1 = testDBHelper.selectOne("select * from user where name=? and age=? limit 1",new Object[]{"dc",20});
//传入Map
Map<String,Object> mapParams = new HashMap<String, Object>();
mapParams.put("name", "dc");
mapParams.put("age", 12);
Map<String,Object> map_WithParam1_2 = testDBHelper.selectOne("select * from user where name=#{name} and age=#{age} limit 1",mapParams);
Map<String,Object> map_WithParam1_2_1 = testDBHelper.selectOne("$user.getOneUser",mapParams);
//传入对象,也可以对象和Map一起作为参数传入方法
User userObj = new User();
userObj.setName("dc");
userObj.setAge(12);
Map<String,Object> map_WithParam1_3 = testDBHelper.selectOne("select * from user where name=#{name} and age=#{age} limit 1",userObj);
List<Map<String,Object>> mapList_withParam1 = testDBHelper.selectList("select * from user");
List<User> mapList_withParam1_1 = testDBHelper.selectList("select name,age from user",User.class);
List<String> mapList_withParam1_2 = testDBHelper.selectList("select name from user",String.class);
List<Integer> mapList_withParam1_3 = testDBHelper.selectList("select name from user",Integer.class);
} catch (Exception e) {
e.printStackTrace();
}finally{
ConnectionManager.closeConnection();
}
}
@Test
public void insert(){
//开启事务
ConnectionManager.isTransaction.set(true);
try {
testDBHelper.insert("insert into user(name,age) values(?,?)", "dc",12);
//提交
ConnectionManager.commit();
} catch (Exception e) {
e.printStackTrace();
ConnectionManager.rollback();
}finally{
ConnectionManager.closeConnection();
}
}
}