哎,最近很好久没在博客园写点东西了,由于工作的原因,接触公司自己研发的底层orm框架,偶然发现该框架在调用jdbc操作的时候参考的是hibernate 里面的SimpleJdbcTemplate,这里我想到了在大学的时候自己用过的一个简单的jdbc封装,现在我将代码贴出来,和大家一起分享:

Config类:读取同一包下的数据库连接配置文件,这样是为了更好的通用性考虑

package com.tly.dbutil;

import java.io.IOException;
import java.util.Properties; public class Config {
private static Properties prop = new Properties();
static{
try {
//加载dbconfig.properties配置文件
prop.load(Config.class.getResourceAsStream("dbconfig.properties"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} //设置常量
public static final String CLASS_NAME = prop.getProperty("CLASS_NAME");
public static final String DATABASE_URL = prop.getProperty("DATABASE_URL");
public static final String SERVER_IP = prop.getProperty("SERVER_IP");
public static final String SERVER_PORT = prop.getProperty("SERVER_PORT");
public static final String DATABASE_SID = prop.getProperty("DATABASE_SID");
public static final String USERNAME = prop.getProperty("USERNAME");
public static final String PASSWORD = prop.getProperty("PASSWORD"); }

dbconfig.properties:数据库配置文件,你也可以用xml格式等,注意Config类里面该文件的调用位置

CLASS_NAME=com.mysql.jdbc.Driver
DATABASE_URL=jdbc:mysql
SERVER_IP=localhost
SERVER_PORT=3306
DATABASE_SID=employees
USERNAME=root
PASSWORD=1

接下来就是数据库连接辅助类DBConn了

package com.employees.dbutil;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class DBConn {
//三属性、四方法 //三大核心接口
private Connection conn = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null; //四个方法
//method1: 创建数据库的连接
public Connection getConntion(){
try {
//1: 加载连接驱动,Java反射原理
Class.forName(Config.CLASS_NAME);
//2:创建Connection接口对象,用于获取MySQL数据库的连接对象。三个参数:url连接字符串 账号 密码
String url = Config.DATABASE_URL+"://"+Config.SERVER_IP+":"+Config.SERVER_PORT+"/"+Config.DATABASE_SID;
conn = DriverManager.getConnection(url,Config.USERNAME,Config.PASSWORD);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
} //method2:关闭数据库的方法
public void closeConn(){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt!=null){
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} //method3: 专门用于发送增删改语句的方法
public int execOther(PreparedStatement pstmt){
try {
//1、使用Statement对象发送SQL语句
int affectedRows = pstmt.executeUpdate();
//2、返回结果
return affectedRows;
} catch (SQLException e) {
e.printStackTrace();
return -;
}
} //method4: 专门用于发送查询语句
public ResultSet execQuery(PreparedStatement pstmt){
try {
//1、使用Statement对象发送SQL语句
rs = pstmt.executeQuery();
//2、返回结果
return rs;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
} }

平时的用上面的代码能够解决一些简单的CRUD的应用了,但是还有很多限制,比如每次程序拿连接都要new,这样就给系统加大了负担,没有事务,没有dataSource等等,今天看见一哥们在园里面写的一篇用反射解决直接以对象参数的方式CRUD,这个我以前也写过,没写完,主要是自己想写一个通用的DButil,最后研究来研究去,发现越来越和hibernate里面的simpleJdbcTemplate接近了,所以就直接去看hibernate的源码了,加上那段时间有些事,没有时间,就将这件事闲置起来了,现在把这个东西补上,也给自己回顾一下下

BaseDao类

package com.employees.dao;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import com.employees.dbutil.DBConn; public class BaseDAO<T> { DBConn conn = new DBConn();
private Connection connection = null; @SuppressWarnings("unused")
private Class<T> persistentClass; @SuppressWarnings("unchecked")
public BaseDAO() {
initConnection();
//获得参数化类型
ParameterizedType type = (ParameterizedType)getClass().getGenericSuperclass();
persistentClass = (Class<T>)type.getActualTypeArguments()[];
} /**
* 获得数据库连接
*/
public void initConnection() {
connection = conn.getConntion();
} /**
* 保存
*/
public void save(T entity) throws Exception{
//SQL语句,insert into table name (
String sql = "insert into " + entity.getClass().getSimpleName().toLowerCase() + "("; //获得带有字符串get的所有方法的对象
List<Method> list = this.matchPojoMethods(entity,"get"); Iterator<Method> iter = list.iterator(); //拼接字段顺序 insert into table name(id,name,email,
while(iter.hasNext()) {
Method method = iter.next();
sql += method.getName().substring().toLowerCase() + ",";
} //去掉最后一个,符号insert insert into table name(id,name,email) values(
sql = sql.substring(, sql.lastIndexOf(",")) + ") values("; //拼装预编译SQL语句insert insert into table name(id,name,email) values(?,?,?,
for(int j = ; j < list.size(); j++) {
sql += "?,";
} //去掉SQL语句最后一个,符号insert insert into table name(id,name,email) values(?,?,?);
sql = sql.substring(, sql.lastIndexOf(",")) + ")"; //到此SQL语句拼接完成,打印SQL语句
System.out.println(sql); //获得预编译对象的引用
PreparedStatement statement = connection.prepareStatement(sql); int i = ;
//把指向迭代器最后一行的指针移到第一行.
iter = list.iterator();
while(iter.hasNext()) {
Method method = iter.next();
//此初判断返回值的类型,因为存入数据库时有的字段值格式需要改变,比如String,SQL语句是'"+abc+"'
if(method.getReturnType().getSimpleName().indexOf("String") != -) {
statement.setString(++i, this.getString(method, entity));
} else if(method.getReturnType().getSimpleName().indexOf("Date") != -){
statement.setDate(++i, this.getDate(method, entity));
} else if(method.getReturnType().getSimpleName().indexOf("InputStream") != -) {
statement.setAsciiStream(++i, this.getBlob(method, entity),);
} else {
statement.setInt(++i, this.getInt(method, entity));
}
}
//执行
conn.execOther(statement);
//关闭连接
conn.closeConn();
} /**
* 修改
*/
public void update(T entity) throws Exception{
String sql = "update " + entity.getClass().getSimpleName().toLowerCase() + " set "; //获得该类所有get方法对象集合
List<Method> list = this.matchPojoMethods(entity,"get"); //临时Method对象,负责迭代时装method对象.
Method tempMethod = null; //由于修改时不需要修改ID,所以按顺序加参数则应该把Id移到最后.
Method idMethod = null;
Iterator<Method> iter = list.iterator();
while(iter.hasNext()) {
tempMethod = iter.next();
//如果方法名中带有ID字符串并且长度为2,则视为ID.
if(tempMethod.getName().lastIndexOf("Id") != - && tempMethod.getName().substring().length() == ) {
//把ID字段的对象存放到一个变量中,然后在集合中删掉.
idMethod = tempMethod;
iter.remove();
//如果方法名去掉set/get字符串以后与pojo + "id"想符合(大小写不敏感),则视为ID
} else if((entity.getClass().getSimpleName() + "Id").equalsIgnoreCase(tempMethod.getName().substring())) {
idMethod = tempMethod;
iter.remove();
}
} //把迭代指针移到第一位
iter = list.iterator();
while(iter.hasNext()) {
tempMethod = iter.next();
sql += tempMethod.getName().substring().toLowerCase() + "= ?,";
} //去掉最后一个,符号
sql = sql.substring(,sql.lastIndexOf(",")); //添加条件
sql += " where " + idMethod.getName().substring().toLowerCase() + " = ?"; //SQL拼接完成,打印SQL语句
System.out.println(sql); PreparedStatement statement = this.connection.prepareStatement(sql); int i = ;
iter = list.iterator();
while(iter.hasNext()) {
Method method = iter.next();
//此初判断返回值的类型,因为存入数据库时有的字段值格式需要改变,比如String,SQL语句是'"+abc+"'
if(method.getReturnType().getSimpleName().indexOf("String") != -) {
statement.setString(++i, this.getString(method, entity));
} else if(method.getReturnType().getSimpleName().indexOf("Date") != -){
statement.setDate(++i, this.getDate(method, entity));
} else if(method.getReturnType().getSimpleName().indexOf("InputStream") != -) {
statement.setAsciiStream(++i, this.getBlob(method, entity),);
} else {
statement.setInt(++i, this.getInt(method, entity));
}
} //为Id字段添加值
if(idMethod.getReturnType().getSimpleName().indexOf("String") != -) {
statement.setString(++i, this.getString(idMethod, entity));
} else {
statement.setInt(++i, this.getInt(idMethod, entity));
} //执行SQL语句
statement.executeUpdate(); //关闭预编译对象
statement.close(); //关闭连接
connection.close();
} /**
* 删除
*/
public void delete(T entity) throws Exception{
String sql = "delete from " + entity.getClass().getSimpleName().toLowerCase() + " where "; //存放字符串为"id"的字段对象
Method idMethod = null; //取得字符串为"id"的字段对象
List<Method> list = this.matchPojoMethods(entity, "get");
Iterator<Method> iter = list.iterator();
while(iter.hasNext()) {
Method tempMethod = iter.next();
//如果方法名中带有ID字符串并且长度为2,则视为ID.
if(tempMethod.getName().lastIndexOf("Id") != - && tempMethod.getName().substring().length() == ) {
//把ID字段的对象存放到一个变量中,然后在集合中删掉.
idMethod = tempMethod;
iter.remove();
//如果方法名去掉set/get字符串以后与pojo + "id"想符合(大小写不敏感),则视为ID
} else if((entity.getClass().getSimpleName() + "Id").equalsIgnoreCase(tempMethod.getName().substring())) {
idMethod = tempMethod;
iter.remove();
}
} sql += idMethod.getName().substring().toLowerCase() + " = ?"; PreparedStatement statement = this.connection.prepareStatement(sql); //为Id字段添加值
int i = ;
if(idMethod.getReturnType().getSimpleName().indexOf("String") != -) {
statement.setString(++i, this.getString(idMethod, entity));
} else {
statement.setInt(++i, this.getInt(idMethod, entity));
} //执行
conn.execOther(statement);
//关闭连接
conn.closeConn();
} /**
* 通过ID查询
*/
public T findById(Object object) throws Exception{
String sql = "select * from " + persistentClass.getSimpleName().toLowerCase() + " where "; //通过子类的构造函数,获得参数化类型的具体类型.比如BaseDAO<T>也就是获得T的具体类型
T entity = persistentClass.newInstance(); //存放Pojo(或被操作表)主键的方法对象
Method idMethod = null; List<Method> list = this.matchPojoMethods(entity, "set");
Iterator<Method> iter = list.iterator(); //过滤取得Method对象
while(iter.hasNext()) {
Method tempMethod = iter.next();
if(tempMethod.getName().indexOf("Id") != - && tempMethod.getName().substring().length() == ) {
idMethod = tempMethod;
} else if((entity.getClass().getSimpleName() + "Id").equalsIgnoreCase(tempMethod.getName().substring())){
idMethod = tempMethod;
}
}
//第一个字母转为小写
sql += idMethod.getName().substring(,).toLowerCase()+idMethod.getName().substring() + " = ?"; //封装语句完毕,打印sql语句
System.out.println(sql); //获得连接
PreparedStatement statement = this.connection.prepareStatement(sql); //判断id的类型
if(object instanceof Integer) {
statement.setInt(, (Integer)object);
} else if(object instanceof String){
statement.setString(, (String)object);
} //执行sql,取得查询结果集.
ResultSet rs = conn.execQuery(statement); //记数器,记录循环到第几个字段
int i = ; //把指针指向迭代器第一行
iter = list.iterator(); //封装
while(rs.next()) {
while(iter.hasNext()) {
Method method = iter.next();
if(method.getParameterTypes()[].getSimpleName().indexOf("String") != -) {
//由于list集合中,method对象取出的方法顺序与数据库字段顺序不一致(比如:list的第一个方法是setDate,而数据库按顺序取的是"123"值)
//所以数据库字段采用名字对应的方式取.
this.setString(method, entity, rs.getString(method.getName().substring().toLowerCase()));
} else if(method.getParameterTypes()[].getSimpleName().indexOf("Date") != -){
this.setDate(method, entity, rs.getDate(method.getName().substring().toLowerCase()));
} else if(method.getParameterTypes()[].getSimpleName().indexOf("InputStream") != -) {
this.setBlob(method, entity, rs.getBlob(method.getName().substring().toLowerCase()).getBinaryStream());
} else {
this.setInt(method, entity, rs.getInt(method.getName().substring().toLowerCase()));
}
}
} //关闭结果集
rs.close(); //关闭预编译对象
statement.close(); return entity;
} /**
* 过滤当前Pojo类所有带传入字符串的Method对象,返回List集合.
*/
private List<Method> matchPojoMethods(T entity,String methodName) {
//获得当前Pojo所有方法对象
Method[] methods = entity.getClass().getDeclaredMethods(); //List容器存放所有带get字符串的Method对象
List<Method> list = new ArrayList<Method>(); //过滤当前Pojo类所有带get字符串的Method对象,存入List容器
for(int index = ; index < methods.length; index++) {
if(methods[index].getName().indexOf(methodName) != -) {
list.add(methods[index]);
}
}
return list;
} /**
* 方法返回类型为int或Integer类型时,返回的SQL语句值.对应get
*/
public Integer getInt(Method method, T entity) throws Exception{
return (Integer)method.invoke(entity, new Object[]{});
} /**
* 方法返回类型为String时,返回的SQL语句拼装值.比如'abc',对应get
*/
public String getString(Method method, T entity) throws Exception{
return (String)method.invoke(entity, new Object[]{});
} /**
* 方法返回类型为Blob时,返回的SQL语句拼装值.对应get
*/
public InputStream getBlob(Method method, T entity) throws Exception{
return (InputStream)method.invoke(entity, new Object[]{});
} /**
* 方法返回类型为Date时,返回的SQL语句拼装值,对应get
*/
public Date getDate(Method method, T entity) throws Exception{
return (Date)method.invoke(entity, new Object[]{});
} /**
* 参数类型为Integer或int时,为entity字段设置参数,对应set
*/
public Integer setInt(Method method, T entity, Integer arg) throws Exception{
return (Integer)method.invoke(entity, new Object[]{arg});
} /**
* 参数类型为String时,为entity字段设置参数,对应set
*/
public String setString(Method method, T entity, String arg) throws Exception{
return (String)method.invoke(entity, new Object[]{arg});
} /**
* 参数类型为InputStream时,为entity字段设置参数,对应set
*/
public InputStream setBlob(Method method, T entity, InputStream arg) throws Exception{
return (InputStream)method.invoke(entity, new Object[]{arg});
} /**
* 参数类型为Date时,为entity字段设置参数,对应set
*/
public Date setDate(Method method, T entity, Date arg) throws Exception{
return (Date)method.invoke(entity, new Object[]{arg});
}
}

EmployeesDao继承BaseDAO,可以直接使用父类的方法,增加了代码的复用

package com.employees.dao;

import java.util.ArrayList;
import java.util.List;
import com.employees.po.Employees; public class EmployeesDao extends BaseDAO<Employees> { // 添加员工信息的操作
public boolean addEmployees(final Employees employees) throws Exception {
save(employees);
return true;
} // 将员工信息添加到表格中
public List<Employees> addEmployees(int id) throws Exception {
List<Employees> lstEmployees = new ArrayList<Employees>();
Employees employees = findById(id);
// 将当前封转好的数据装入对象中
lstEmployees.add(employees);
return lstEmployees;
} public void deleteEmp(final Employees entity) throws Exception {
this.delete(entity);
} public void updateEmp(final Employees entity) throws Exception {
this.update(entity);
} }

po层的代码就不贴了,现在用junit4做一下测试

package com.employees.dao;

import org.junit.Test;

import com.employees.po.Employees;

public class EmployeesDaoTest {

    @Test
public void testAdd() throws Exception {
Employees emp = new Employees();
emp.setPname("tly");
emp.setPsex("男");
emp.setPbeliefs("xxxxx");
emp.setPaddr("天河");
emp.setPhobby("打篮球");
emp.setPsubject("计算机");
emp.setPtel("");
EmployeesDao dao = new EmployeesDao();
dao.addEmployees(emp);
}
@Test
public void testUpdate() throws Exception {
EmployeesDao dao = new EmployeesDao();
Employees emp = dao.findById();
emp.setPtel("");
dao.updateEmp(emp);
}
@Test
public void testdelete() throws Exception {
EmployeesDao dao = new EmployeesDao();
Employees emp = dao.findById();
dao.deleteEmp(emp);
} }

经过测试,这三个方法都能正常运行,时间仓促,有些代码是参考其他哥们的,有些地方可能考虑的不是很全面或者有些代码会有冗余,BaseDAO中做通用crud操作没有写全,要是哪位小伙伴有兴趣,可以接下去写写,比如查询,批量化操作等等,如果测试通过的话,记得给我发一份啊,呵呵,邮箱1170382650@qq.com,要现在的源码下载,包括数据库

简单通用JDBC辅助类封装的更多相关文章

  1. JDBC辅助类封装 及应用

    一:代码图解: 二:配置文件: driverClassName=com.mysql.jdbc.Driver url=jdbc\:mysql\://127.0.0.1\:3306/xlzj_sh_new ...

  2. JDBC的一些简单通用代码

    JDBC的一些简单通用代码 功能包括 连接数据库 查询操作 执行sql语句 jdbc相关类的加载 关闭连接 获取数据库格式的当前时间 代码 package dao; import java.sql.C ...

  3. 一颗简单的JDBC栗子

    前言:安装好数据库之后,我们编写的java程序是不能直接使用数据库的,而JDBC(Java Database Connectivity,即java数据库连接)是java语言里用来规范客户端程序访问数据 ...

  4. 简单的JDBC编程步骤

    1.加载数据库驱动(com.mysql.jdbc.Driver) 2.创建并获取数据库链接(Connection) 3.创建jdbc statement对象(PreparedStatement) 4. ...

  5. 一步一步写一个简单通用的makefile(三)

    上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化. 优化后的makefile: #Hel ...

  6. JDBC操作封装

    这两天学习了一下jdbc的封装,依据的是下面这篇 http://wenku.baidu.com/link?url=FaFDmQouYkKO24ApATHYmA5QzUcj-UE-7RSSZaBWPqk ...

  7. struts神马的不过是对servlet、filter的封装而已,hibernate神马的也不过是对jdbc的封装而已,他们只是把一些常见的操作流程化了,如果不懂servlet、filter,不懂jdbc,使用struts和hibernate出问题了都不知道是怎么回事。

    struts神马的不过是对servlet.filter的封装而已,hibernate神马的也不过是对jdbc的封装而已,他们只是把一些常见的操作流程化了,如果不懂servlet.filter,不懂jd ...

  8. 转:简单通用的一则makefile .

    在linux下面下写程序少不了写makefile,如果每个文件都按部就班的详细的写编译脚本,效率势必低下:makefile提供了自动化变量.模式规则等,稍加利用可以提高写makefile的效率.下面列 ...

  9. jquery提示消息,简单通用

    jquery提示消息.简单通用 function showTips(txt,time,status) { var htmlCon = ''; if(txt != ''){ if(status != 0 ...

随机推荐

  1. iOS设计模式 - 命令模式

    前言: 命令对象封装了如何对目标执行指令的信息,因此客户端或调用者不必了解目标的任何细节,却仍可以对他执行任何已有的操作.通过把请求封装成对象,客 户端可 以把它参数化并置入队列或日志中,也能够支持可 ...

  2. UVa 105 - The Skyline Problem(利用判断,在于想法)

    题目来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&pa ...

  3. 远离腰痛的好方法——如何锻炼腰背部肌肉?

    在我们的骨科门诊中最常见到的就是腰痛患者:引起腰痛的原因很多,也比较复杂,所以就有俗语"病人腰痛.医生头痛"一说.其实,相当大部分的腰痛症状都是跟腰背部后方的肌肉筋膜劳损或者无菌性 ...

  4. Linux线程学习(二)

    线程基础 进程 系统中程序执行和资源分配的基本单位 每个进程有自己的数据段.代码段和堆栈段 在进行切换时需要有比较复杂的上下文切换   线程 减少处理机的空转时间,支持多处理器以及减少上下文切换开销, ...

  5. Windows下查看端口占用

    最近在重新安装Mysql的时候,发现3306默认端口被占用了.类似的情况常常遇到,想查看到底是哪个程序把这个端口占用了. 下面是我google找到的方法,和大家分享. 1. 首先,使用netstat ...

  6. C#调用C++ DLL 文件

    说来惭愧,都注册一年多了,却没有发表过一篇正式的博文,中间很多学习的过程也没有记录下来.如今到了一个新的环境,也有了学习的机会,一定要把每天的收获记录一下. 要做的东西需要引用C++编写的DLL,刚开 ...

  7. PL/SQL之--流程控制语句

    一.简介 像编程语言一样,oracle PL/SQL也有自己的流程控制语句.通过流程控制语句,我们可以在PL/SQL中实现一下比较复杂的业务逻辑操作.而无需到程序中去控制,在一定程度上提高了效率,这也 ...

  8. dom4j操作xml

    dom4j是一个Java的XML API,类似于jdom,用来读写XML文件.是一个非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点,同时它也是一个开放源工具.可以在这个 ...

  9. Eclipse 快捷键 篇

    1. Ctrl+Shift+R:打开资源这可能是所有快捷键组合中最省时间的了.这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask名中的前几个字母,比如applic*.xml ...

  10. Gradle深入与实战(转)

    转自:NO END FOR LEARNINGhttp://benweizhu.github.io/blog/2015/01/31/deep-into-gradle-in-action-1/ 什么是构建 ...