由于最近使用jdbc使用的比较频繁,在使用的过程做了一些简单的封装。
在这里简单的记录一下,方便以后使用。迷路的大神请勿见笑。
数据库使用的Oracle。
使用时用dao层类extends类BaseDaoImpl.java
- 获取数据库连接的类
DBConn.java
package com.utils;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import org.apache.commons.dbcp.BasicDataSource;
/**
* @author yxln
* @function 获取数据库连接
* 获取方式 DBConn.getInstance.getConn();
*/
public class DBConn {
private DBConn() {
}
// 数据库连接
private static DBConn instance = null ;
// 数据库配置文件
private static Properties props = null ;
// 数据池
private static BasicDataSource ds = null ;
static {
try {
// 创建本类实例
instance = new DBConn() ;
props = new Properties() ;
// 加载数据库配置文件
props.load(DBConn.class.getResourceAsStream("/db.properties"));
// 加载驱动类
ds = new BasicDataSource() ;
ds.setDriverClassName(props.getProperty("driver"));
ds.setUsername(props.getProperty("username"));
ds.setPassword(props.getProperty("password"));
ds.setUrl(props.getProperty("url"));
// 设置数据库最大活动数
ds.setMaxActive(Integer.parseInt(props.getProperty("maxActive")));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
* @return
*/
public Connection getConn() {
Connection conn = null ;
try {
// 数据库连接
conn = ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn ;
}
/**
* @author yxln
* @function 关闭数据库操作先关的一些的
* @date 2018年9月29日
* @param conn 数据库连接Connection
* @param sm 执行sql的Statement
* @param rs 结果集REsultSet
*/
public static void closeConn(Connection conn, Statement sm,ResultSet rs ) {
try {
if(rs != null) {
rs.close();
}
} catch (SQLException e1) {
e1.printStackTrace();
}finally {
if(null != sm) {
try {
sm.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(null != conn) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
/**
* @author yxln
* @function 关闭数据库操作先关的一些的
* @date 2018年9月29日
* @param conn 数据库连接Connection
* @param sm 执行sql的PreparedStatement
* @param rs 结果集REsultSet
*/
public static void closeConn(Connection conn, PreparedStatement ps,ResultSet rs ) {
try {
if(rs != null) {
rs.close();
}
} catch (SQLException e1) {
e1.printStackTrace();
}finally {
if(null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(null != conn) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
public static DBConn getInstance() {
return instance;
}
}
- 数据库中查询的数据ResultSet映射到实体类
ObjectMapping.java
package com.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 将数据库中查询的数据ResultSet映射到实体类
* @author YinXilin
* @param <T> 要转换的实体类
*/
@SuppressWarnings("unchecked")
public class ObjectMapping<T> {
CommonUtils<T> common = new CommonUtils<>() ;
/**
* 将ResultSet类型的数据转换成实体类domain
* @param rs 从数据库中的查询到的结果集
* @param domain 结果数据的实体类
* @return
*/
public List<T> mapping(ResultSet rs,Class<?> domain) {
List<T> list = null ;
T t = null ;
if(null != rs) {
try {
// 实体类中的属性
Field[] fields = null ;
// 利用反射执行实行实体类中的方法
Method method = null ;
// 从结果集中的获取的值
String value = "" ;
// 遍历结果集
list = new ArrayList<T>() ;
while(rs.next()) {
// 实例化实体类
t = (T) domain.newInstance() ;
try {
// 获取实体类中的所有属性
fields = domain.getDeclaredFields() ;
// 循环遍历实体类中的属性
for(int i = 0 ; i < fields.length ; i++) {
// 获得属性名
String fieldName = fields[i].getName() ;
// 如果属性名为 serialVersionUID , 不行执行操作,跳过此次循环
if("serialVersionUID".equals(fieldName)) {
continue ;
}
// 获取属性的类型
Class<?> fieldType = fields[i].getType() ;
// 获取实体类中的方法
method = domain.getMethod(common.getMethodName(fieldName),fieldType) ;
// 从结果集中获取实体类的属性对应的字段的值
String str = common.attributeNameToFieldName(fieldName) ;
value = rs.getString(str) ;
if(value != null && value.length() > 0 && !"null".equals(value)) {
// 实体类的对象t 利用反射调用实体类中的方法(将结果集中的值value映射到实体类中)
// 如果这里报argument type mismatch异常,有可能是 convert方法没有对这种数据进行转换
method.invoke(t, convert(fieldType, value)) ;
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
list.add(t) ;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e2) {
e2.printStackTrace();
} catch (IllegalAccessException e2) {
e2.printStackTrace();
}
}
return list ;
}
/**
* 将源数据转换成制定的类型
* @param fieldType 需要转换成的制定的类型
* @param origin 需要转换的源数据
* @return 转换成目标类型后的数据
*/
public Object convert(Class<?> targetType,String origin){
// 转换的目标类型或元数据为空,则无法转换,直接返回源数据
if(null == targetType || null == origin) {
return origin ;
}
// 将源数据转换成Integer类型
if(targetType.equals(Integer.class)) {
return Integer.parseInt(origin) ;
// 将源数据转换成Date类型
}else if(targetType.equals(Date.class)) {
Date date = null ;
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(origin) ;
} catch (ParseException e) {
e.printStackTrace();
}
return date ;
}else if(targetType.equals(Double.class)) {
return Double.parseDouble(origin) ;
}
return origin ;
}
}
- CRUD基本操作接口
IBaseDao.java
package com.dao;
import java.util.List;
import java.util.Map;
/**
* @author yxln
* @function
* @date 2018年10月18日
*/
public interface IBaseDao<T> {
/*
* 插入单条数据
*/
public int insert(String sql,Object... args);
/*
* 通过po插入单条数据
*/
public int insertPo(T po);
/*
* 查询单条数据
*/
public T query(String sql ,Object... paras) ;
/*
* 分页查找数据
*/
public List<T> queryListByPage_Oralce(String sql ,Map<String,Object> map) ;
/*
* 多条件、单次数据删除
*/
public int delete(String sql , Object... args) ;
/*
* 批量删除
*/
public void deleteBatches(String sql,Object[]... args) ;
/*
* 修改数据
*/
public int update(String sql,Object... paras) ;
}
- CRUD实现类
BaseDaoImpl.java
package com.dao.impl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.dao.IBaseDao;
import com.utils.CommonUtils;
import com.utils.DBConn;
import com.utils.ObjectMapping;
/**
* @author yxln
* @param <T>
* @function
* @date 2018年10月18日
*/
public class BaseDaoImpl<T> implements IBaseDao<T>{
// 数据库连接
Connection conn = null ;
// sql预处理对象
PreparedStatement ps = null ;
// 结果集对象
ResultSet rs = null ;
// 工具类
CommonUtils<T> common = null ;
// 结果集映射对象
ObjectMapping<T> objMapping = new ObjectMapping<T>() ;
private Class clazz ;
/**
* @author yxln
* @function 添加数据
* @date 2018年10月18日
* @param sql
* @return
*/
public int insert(String sql,Object... args) {
// 获取数据库连接
conn = DBConn.getInstance().getConn() ;
int flag = 0 ;
try {
// 对sql语句进行预处理
ps = conn.prepareStatement(sql) ;
if(args != null) {
int paramIndex = 1 ;
for(Object obj:args) {
// 当前的值如果为java时间(java.util.Date())类型,需要转换成java.sql.Date()
if("java.util.Date".equals(obj.getClass().getName())) {
ps.setObject(paramIndex++, new java.sql.Date(((java.util.Date) obj).getTime()));
}else {
ps.setObject(paramIndex++, obj);
}
}
}
flag = ps.executeUpdate() ;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBConn.closeConn(conn, ps, null);
}
return flag;
}
/**
* @author yxln
* @function 将实体类中的数据插入到数据库中
* @date 2018年10月18日
* @param po 实体类对象(持久对象)
* -- 实体类名一定要和数据库表明一样,
* -- 实体类中的属性和数据库字段对应,属性必须采用驼峰命名法,数据库中_后面的字母大写
* @return
*/
public int insertPo(T po) {
common = new CommonUtils<>() ;
// 取出实体类中的属性名与对应的值
Map<String,Object> attrs = common.getObjectAttribute(po) ;
// 获取实体类的类名
String className = po.getClass().getSimpleName().toUpperCase() ;
// 错做数据数据库结果
int flag = 0 ;
// 将实体类中的数据插入数据库的sql语句 的前半段
StringBuffer sqlHalf1 = new StringBuffer("insert into "+ className + "(");
// sql 语句的后半段
StringBuffer sqlHalf2 = new StringBuffer("values(");
// 根据实体类中的属性拼接sql语句
for(String key:attrs.keySet()) {
sqlHalf1.append(common.attributeNameToFieldName(key).toUpperCase() + ",") ;
sqlHalf2.append("?,") ;
}
sqlHalf1.deleteCharAt(sqlHalf1.length()-1).append(") ") ;
sqlHalf2.deleteCharAt(sqlHalf2.length()-1).append(") ") ;
// 获取数据连接
conn = DBConn.getInstance().getConn() ;
try {
// 对sql语句进行预处理
ps = conn.prepareStatement(sqlHalf1.append(sqlHalf2).toString()) ;
int paramIndex = 1 ;
// 遍历attrs,将其中的值设置到预处理sql中对应的占位符上
for(Object obj:attrs.values()) {
// 当前的值如果为java时间(java.util.Date())类型,需要转换成java.sql.Date()
if("java.util.Date".equals(obj.getClass().getName())) {
ps.setObject(paramIndex++, new java.sql.Date(((java.util.Date) obj).getTime()));
}else {
ps.setObject(paramIndex++, obj);
}
}
// 执行查询的sql语句
flag = ps.executeUpdate() ;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBConn.closeConn(conn, ps, null);
}
return flag;
}
/**
* @author yxln
* @function 查询单条数数据并将结果映射到实体类
* @param sql
* @param paras
* @return
* @date 2018年10月31日
*/
public T query(String sql ,Object... paras) {
conn = DBConn.getInstance().getConn() ;
ResultSet rs = null ;
T t = null ;
try {
ps = conn.prepareStatement(sql) ;
if(paras != null && paras.length > 0) {
for(int i = 0 ; i < paras.length ; i++)
ps.setObject(i + 1, paras[i]);
}
rs = ps.executeQuery() ;
Type type = (ParameterizedType) this.getClass().getGenericSuperclass();
if(type instanceof ParameterizedType) {
this.clazz = (Class) ((ParameterizedType)type).getActualTypeArguments()[0];
}else {
System.out.println("【异常】没有给定泛型的类型");
}
t = (T) objMapping.mapping(rs, clazz).get(0) ;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBConn.closeConn(conn, ps, rs);
}
return t ;
}
/**
* @author yxln
* @function 分页查找数据
* @param sql
* @param pageNo
* @param pageSize
* @return
* @date 2018年10月23日
*/
public List<T> queryListByPage_Oralce(String sql ,Map<String,Object> map) {
// map、pageNo、pageSize 中任何一个为空,则不能完成分页查询,
if(map == null || map.get("pageNo") == null || map.get("pageSize") == null) {
System.out.println("map、pageNo、pageSize 中任何一个为空,则不能完成分页查询");
return null;
}
conn = DBConn.getInstance().getConn() ;
ResultSet rs = null ;
List<T> list = null ;
int pageNo = 1 ;
int pageSize = 5 ;
Type type = (ParameterizedType) this.getClass().getGenericSuperclass();
if(type instanceof ParameterizedType) {
this.clazz = (Class) ((ParameterizedType)type).getActualTypeArguments()[0];
}else {
System.out.println("【异常】没有给定泛型的类型");
}
if(map.get("pageNo") != null) {
pageNo = Integer.parseInt(map.get("pageNo") + "") ;
map.remove("pageNo") ;
}
if(map.get("pageSize") != null) {
pageSize = Integer.parseInt(map.get("pageSize") + "") ;
map.remove("pageSize") ;
}
sql = " select * from ( select all_data.*,rownum all_data_row from ("+sql+
") all_data where ROWNUM <= "+(pageNo * pageSize)+") where all_data_row > " +((pageNo - 1) * pageSize) ;
try {
ps = conn.prepareStatement(sql) ;
if(map != null) {
Set<String> keySet = map.keySet() ;
}
rs = ps.executeQuery() ;
list = new ArrayList<T>() ;
while(rs.next()) {
list = objMapping.mapping(rs, this.clazz) ;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBConn.closeConn(conn, ps, rs);
}
return list ;
}
/**
*
* @author yxln
* @function 多条件、单次数据删除(注意此方法传进多个参数并不是用于批量删除,批量删除使用本类中的方法deleteBatches())
* @param sql 删除的sql语句
* @param args 参数,与sql语句中占位符对应
* 例子1:deleteBatches("delete from employee where id = ? and name = ?",new String[] {"6","yxln4"})
* 例子1:deleteBatches("delete from employee where id = ? and name = ?","6","yxln4")
* @return
* @date 2018年10月30日
*/
public int delete(String sql , Object... args) {
//获取数据库连接
conn = DBConn.getInstance().getConn() ;
int flag = 0 ;
try {
// 获取sql预处理对象
ps = conn.prepareStatement(sql) ;
// 判断是否有参数
if(args != null && args.length > 0) {
for(int i = 0 ; i < args.length ; i++) {
// 将参数设置到对应的占位符
ps.setObject(i + 1, args[i]);
}
}
flag = ps.executeUpdate() ;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBConn.closeConn(conn, ps, rs);
}
return flag;
}
/**
*
* @author yxln
* @function 批量删除
* @param sql 执行批量删除的sql
* @param args 每一组参数(参数个数与占位符对应)
* 例子1:deleteBatches("delete from employee where id = ? ",
* new String[] {"4","6"})
* 例子2:deleteBatches("delete from employee where id = ? ","4","6")
* 例子3:deleteBatches("delete from employee where id = ? and name = ?",
* new String[] {"4","yxln3"},new String[] {"6","yxln4"})
* 例子4:deleteBatches("delete from employee where id = ? and name = ?",
* new String[][] {new String[] {"23","yxln9"},new String[] {"24","yxln9"}})
* @date 2018年10月31日
*/
public void deleteBatches(String sql,Object[]... args) {
conn = DBConn.getInstance().getConn() ;
int[] flag = new int[] {};
try {
//不自动提交
conn.setAutoCommit(false);
ps = conn.prepareStatement(sql) ;
// 判断是否有参数
if(args != null && args.length > 0) {
// 判断参数中的对象是否为数组
if(args[0].getClass().isArray() && ((Object[])args[0]).length > 0) {
Object[] obj = null ;
for(int i = 0 ; i < args.length ; i++) {
obj = (Object[]) args[i] ;
for(int j = 0 ; j < obj.length ; j++) {
ps.setObject(j + 1, obj[j]);
}
ps.addBatch();
}
flag = ps.executeBatch() ;
conn.commit();
// 只想sql语句传入一个参数
}else {
for(int i = 0 ; i < args.length ; i++) {
ps.setObject(1, args[i]);
ps.addBatch();
}
flag = ps.executeBatch() ;
conn.commit();
}
}
} catch (SQLException e) {
// 捕获到执行过程的中的异常,回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBConn.closeConn(conn, ps, rs);
}
}
}
/**
* @author yxln
* @function 修改单条数据
* @param sql 执行修改的sql语句
* @param paras 参数
* @return
* @date 2018年10月31日
*/
public int update(String sql,Object... paras) {
conn = DBConn.getInstance().getConn() ;
int flag = 0 ;
try {
ps = conn.prepareStatement(sql) ;
if(paras != null && paras.length > 0) {
for(int i = 0 ; i < paras.length ; i++) {
ps.setObject(i +1, paras[i]);
}
}
flag = ps.executeUpdate() ;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBConn.closeConn(conn, ps, rs);
}
return flag ;
}
}