通过传统的JDBC进行数据操作比较繁琐,但是无论hibernate也好,Mybatis也好底层都是对JDBC的调用,那么我们可不可以对JDBC(包括存储过程的操作)进行封装(并且打包为jar)从而简化我们的开发呢?答案是肯定的。
首先封装分页工具类:
package bw.song.jdbc.util;
import java.util.List;
/**
* 分页工具类
* @author 宋伟宁
*
* @param
*/
public class Pager {
private int offset;//起始位置:limit offset,pagesize
private int currentPage;//当前页面
private int nextPage;//下一页
private int prevPage;//上一页
private int pageCount;//总页数
private int total;//总记录数
private int pagesize;//每页的记录数
private List datas;//分页显示的数据集
private String url; // 请求url
private String keyword; // 要模糊查询的内容
private String select; // 要模糊查询的字段名
private String items; //分页导航
//生成导航条
public String getItems() {
int index = url.indexOf("?");
if(index > 0){
url = url + "&";
}else{
url = url + "?";
}
StringBuffer buffer = new StringBuffer();
buffer.append("找到 "+this.total+" 条记录 ");
if(this.currentPage > 1){
buffer.append("[首页]");
buffer.append("[上一页]");
}
buffer.append("当前第 "+this.currentPage+"/"+pageCount+" 页");
if(this.currentPage < this.pageCount){
buffer.append("[下一页]");
buffer.append("[末页]");
}
buffer.append(" 每页 "+this.pagesize+" 条");
buffer.append("");
this.items=buffer.toString();
return this.items;
}
public Pager(int total,String currentPage,int pagesize){//带参构造
this.total=total;
this.pagesize=pagesize;
if(currentPage==null || currentPage.isEmpty()){
currentPage="1";
}
//计算起始位置:
this.currentPage=Integer.parseInt(currentPage);
this.offset = (this.currentPage-1)*this.pagesize;
//计算上一页
this.prevPage= this.currentPage==1 ? 1 : this.currentPage-1;
//计算总页数
this.pageCount = this.total% this.pagesize > 0 ? this.total/this.pagesize+1 : this.total/this.pagesize;
//计算下一页
this.nextPage = this.currentPage== this.pageCount ? this.pageCount : this.currentPage+1;
}
public Pager() {
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getNextPage() {
return nextPage;
}
public void setNextPage(int nextPage) {
this.nextPage = nextPage;
}
public int getPrevPage() {
return prevPage;
}
public void setPrevPage(int prevPage) {
this.prevPage = prevPage;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getPagesize() {
return pagesize;
}
public void setPagesize(int pagesize) {
this.pagesize = pagesize;
}
public List getDatas() {
return datas;
}
public void setDatas(List datas) {
this.datas = datas;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getSelect() {
return select;
}
public void setSelect(String select) {
this.select = select;
}
}
泛型DAO接口:
package bw.song.jdbc.dao;
import java.util.List;
import bw.song.jdbc.util.Pager;
public interface GenericDao {
/**
* 执行聚合函数
* @param sql
* @return
*/
int executeScalre(String sql);
int executeScalre(String sql,Object object);
int executeScalre(String sql,Object[] args);
/**
* 列表
* @param select
* @param args
* @return
*/
List findAll(String select,Object[] args);
List findAll(String select,Object obj);
List findAll(String select);
/**
* 查询对象
* @param select
* @param args
* @return
*/
T findObject(String select,Object[] args);
T findObject(String select,Object obj);
T findObject(String select);
int save(String insert,Object...args);
int delete(String delete,Integer id);
int update(String update,Object...args);
int getTotal(String sql,Object[] args);
int getTotal(String sql,Object object);
int getTotal(String sql);
/**
* 分页
* @param sql
* @param currentPage
* @param pagesize
* @return
*/
Pager pagelist(String sql,String currentPage, int pagesize);
Pager pagelist(String sql,String currentPage, int pagesize,Object obj);
Pager pagelist(String sql,String currentPage, int pagesize,Object[] args);
}
数据库通用操作类:
package bw.song.jdbc.dao;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.log4j.Logger;
import bw.song.jdbc.util.Pager;
/**
* 通用数据库操作类
* @author 宋伟宁
*
* 2019年10月3日下午10:40:55
*/
public class BaseDao{
private static ThreadLocal threadLocal=new ThreadLocal();
private static Connection connection;//连接
private static PreparedStatement pst;//预编译
private static ResultSet rs;//结果集
private static CallableStatement cstmt;//执行存储过程对象
private static Properties properties = new Properties();
private static String URL, DRIVER, USER, PWD;
private static int m;
private static Logger logger = Logger.getLogger(BaseDao.class);
/**
* 静态块读取配置文件(获取数据库连接属性)
* 获取数据库驱动
*/
static {
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties");
try {
properties.load(input);
DRIVER = properties.getProperty("jdbc.driver");
USER = properties.getProperty("jdbc.username");
PWD = properties.getProperty("jdbc.password");
URL = properties.getProperty("jdbc.url");
Class.forName(DRIVER);
} catch (Exception e) {
logger.debug("加载驱动失败。。。");
e.printStackTrace();
}
}
/**
* 通用的列表
* @param sql
* @param clazz
* @param args
* @return 泛型集合
*/
public static List findAll(String sql,Class clazz,Object...args){
logger.debug("BaseDao..sql:"+sql);
List list=new ArrayList(20);
T t=null;
try {
pst=createPreparedStatement(sql, args);
rs=pst.executeQuery();
while(rs.next()){
t=convert(clazz, rs);
list.add(t);
}
} catch (SQLException e) {
logger.debug("BaseDao...findAll 错误。。。。"+e.getMessage());
}finally{
closeAll(rs,pst);
closeConnection();
}
return list;
}
/**
* 通用的分页
* @param sql
* @param clazz
* @param currentPage
* @param pagesize
* @param args
* @return
*/
public static Pager pageAll(String sql,Class clazz,String currentPage,int pagesize,Object...args){
String total_sql= sql.replace("*", "count(*)").replace("limit ?,?", "").replace("LIMIT ?,?", "");
logger.debug("total_sql: "+total_sql);
List list=new ArrayList(20);
T t=null;
Pager pager=null;
try {
int total=executeScalare(total_sql, args);
pager=new Pager<>(total, currentPage, pagesize);
String sql_page=sql.replace("?,?", String.valueOf(pager.getOffset())+","+String.valueOf(pager.getPagesize()) );
logger.debug("BaseDao..sql:"+sql_page);
pst=createPreparedStatement(sql_page, args);
rs=pst.executeQuery();
while(rs.next()){
t=convert(clazz, rs);
list.add(t);
}
pager.setDatas(list);
} catch (SQLException e) {
logger.debug("BaseDao...分页查询 错误。。。。"+e.getMessage());
}finally{
closeAll(rs,pst);
closeConnection();
}
return pager;
}
/**
* 根据id或条件查询单个对象
* @param sql
* @param clazz
* @param args
* @return
*/
public static T findByObject(String sql,Class clazz,Object...args){
T t=null;
try {
pst=createPreparedStatement(sql, args);
rs=pst.executeQuery();
if(rs.next()){
t=convert(clazz, rs);
}
} catch (Exception e) {
logger.debug("BaseDao findById。。。。错误!"+e.getMessage());
}finally{
closeAll(rs,pst);
closeConnection();
}
return t;
}
public static int executeScalare(String sql,Object...args){
try {
pst= getConnection().prepareStatement(sql);
rs=pst.executeQuery();
if(rs.next()){
m=rs.getInt(1);
}
} catch (Exception e) {
logger.debug("执行聚合函数错误。。。。");
}finally{
closeAll(rs,pst);
closeConnection();
}
return m;
}
private static T convert(Class clazz,ResultSet rs) throws SQLException{
ResultSetMetaData metaData=rs.getMetaData();
int count=metaData.getColumnCount();
T t=null;
try {
t=clazz.newInstance();
for(int i=1;i<=count;i++){
String str= metaData.getColumnLabel(i);
Field field=clazz.getDeclaredField(str);
field.setAccessible(true);
field.set(t, rs.getObject(str));
}
} catch (InstantiationException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
logger.debug("类型转换,注入属性值错误:"+e.getMessage());
}
return t;
}
/**
* ThreadLocal模式的获取数据库连接
* @return
*/
public static Connection getConnection(){
try {
connection= threadLocal.get();
if(connection==null || connection.isClosed()){
connection=DriverManager.getConnection(URL, USER,PWD);
threadLocal.set(connection);
}
} catch (SQLException e) {
logger.debug("创建connection 错误:"+e.getMessage());
}
return connection;
}
/**
* 释放数据库连接
*/
public static void closeConnection(){
connection = threadLocal.get();
try {
if(connection!=null && !connection.isClosed()){
connection.close();
threadLocal.remove();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
*释放所有数据库连接资源
* @param closeables
*/
public static void closeAll(AutoCloseable...closeables){
for(AutoCloseable closeable : closeables){
if(closeable!=null){
try {
closeable.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 获取预编译执行对象
* @param sql
* @param args
* @return
*/
public static PreparedStatement createPreparedStatement(String sql,Object...args){
try {
pst=getConnection().prepareStatement(sql);
if(args!=null){
for(int i=0;i List procedureQuery(String pname,Class clazz,Object...args){
List list = new ArrayList(20);
T t = null;
try {
cstmt=createCallableStatement(pname, args);
rs = cstmt.executeQuery();
while (rs.next()) {
t=convert(clazz, rs);
list.add(t);
}
} catch (Exception e) {
System.out.println("执行查询错误。。。。。");
e.printStackTrace();
}finally{
closeAll(rs,cstmt);
closeConnection();
}
return list;
}
/**
* 根据条件查询单个对象的存储过程
* @param pname
* @param clazz
* @param args
* @return
*/
public static T procedureFindByObject(String pname,Class clazz,Object...args){
T t = null;
try {
cstmt=createCallableStatement(pname, args);
rs = cstmt.executeQuery();
if (rs.next()) {
t =convert(clazz, rs);
}
} catch (Exception e) {
System.out.println("执行查询错误。。。。。");
e.printStackTrace();
}finally{
closeAll(rs,cstmt);
closeConnection();
}
return t;
}
}
泛型实现类:
package bw.song.jdbc.dao;
import java.util.List;
import bw.song.jdbc.util.Pager;
public class GenericDaoImpl implements GenericDao {
private Class clazz;
protected GenericDaoImpl() {
this.clazz=(Class)((java.lang.reflect.ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
@Override
public int save(String insert,Object...args) {
return BaseDao.executeCommand(insert, args);
}
@Override
public int delete(String delete,Integer id) {
return BaseDao.executeCommand(delete, id);
}
@Override
public int update(String udpate,Object...args) {
return BaseDao.executeCommand(udpate, args);
}
@Override
public List findAll(String select, Object[] args) {
return BaseDao.findAll(select, clazz, args);
}
@Override
public List findAll(String select, Object obj) {
return this.findAll(select, new Object[]{obj});
}
@Override
public List findAll(String sql) {
return this.findAll(sql, null);
}
@Override
public T findObject(String select, Object[] args) {
// TODO Auto-generated method stub
return BaseDao.findByObject(select, clazz, args);
}
@Override
public T findObject(String select, Object obj) {
// TODO Auto-generated method stub
return this.findObject(select, new Object[]{obj});
}
@Override
public T findObject(String select) {
// TODO Auto-generated method stub
return this.findObject(select, null);
}
@Override
public Pager pagelist(String sql,String currentPage, int pagesize,Object[] args) {
return BaseDao.pageAll(sql, clazz, currentPage, pagesize, args);
}
@Override
public Pager pagelist(String sql,String currentPage,int pagesize) {
return this.pagelist(sql, currentPage,pagesize, null);
}
@Override
public Pager pagelist(String sql, String currentPage,int pagesize, Object obj) {
return this.pagelist(sql, currentPage, pagesize, new Object[]{obj});
}
@Override
public int getTotal(String sql, Object[] args) {
return BaseDao.executeScalare(sql, args);
}
@Override
public int getTotal(String sql, Object object) {
// TODO Auto-generated method stub
return this.getTotal(sql, new Object[]{object});
}
@Override
public int getTotal(String sql) {
return this.getTotal(sql, null);
}
@Override
public int executeScalre(String sql) {
return this.executeScalre(sql, null);
}
@Override
public int executeScalre(String sql, Object object) {
return this.executeScalre(sql, new Object[]{object});
}
@Override
public int executeScalre(String sql, Object[] args) {
return BaseDao.executeScalare(sql, args);
}
}