Java持久化基础—基于JDBC轻量级分页工具集
?
一、工具集包含了以下内容:
1、封装了C3P0连接池,提取数据源获取,不用修改Java源代码,只需配置c3p0-config.xml和dataSource.properties两个文件轻松实现各种常用数据库连接;
2、优化了查询结果集,直接返回一个包含查询对象的集合,方便使用;
3、封装SQL生成器,即使不会SQL语句也能轻松实现基本查询包括分页查询;
4、主要针对分页进行了封装优化,以对象的方式实现分页;
class="MsoNormal" style="margin: 0cm 0cm 0pt;">com.ran.db包下:
JDBCUtil.java //JDBC数据库连接、增删改查操作类 DBManager.java //C3P0连接池类,管理连接 PageDBManager.java //分页管理类,对数据求和和分页查询 PageBean.java?? //分页信息对象类com.ran.generic包下:
ResultSetToObject.java //通过反射封装结果集对象的工具类 SimpleSQLGenerator.java //SQL生成器工具类com.ran.po包下:
AddressBookPO.java?? //与数据表ADDRESS对应的实体类com.ran.dao包下:
? MyDAO.java //分页测试类 ?配置文件:? ?c3p0-config.xml 、dataSource.properties ?配置数据源和连接池等信息?
?
二、简单实现分页
实现分页很简单其实就只需关注三个单词:what、how、use
1、what:我需要一个什么样结果的分页,使用SimpleSQLGenerator.java类定义我的查询规则,包括查询目标、查询条件和排序方式等;
2、how:定义了一个查询规则,我就得去执行,使用PageDBManager.java类来执行我定义的规则最终得到我想要的结果;
3、use:通过执行规定好的查询得到一个分页对象PageBean,可以直接使用PageBean获取分页的所有信息,包括总页数、当前页、总记录,还有最重要的结果集LIST;
实现分页只需调用上面三个类即可,其它类已封装好不用调用,欢迎大家对上面类进行修改优化。
?
三、代码实例
(因代码较多,建议大家将代码拷至项目中查看,后面我会上传整个项目“JavaJDBC” )
JDBCUtil.java
package com.ran.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.ran.generic.ResultSetToObject;
public class JDBCUtil {
public Connection conn = null;
public PreparedStatement ps = null;
public ResultSet rs = null;
private List entityList = null;
public JDBCUtil(){}
/**
* 获取一个连接对象
*/
public Connection getConnection(){
try {
conn = DBManager.getInstance().getConnection(); //C3P0连接池控制Connection
} catch (Exception e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
return conn;
}
/**
* 优化后的query,只需传递sql命令和需要返回的对象类型就可获得一个对象集合,
* 在展示层只需变量集合直接操作对象获取属性值,完全面向对象的方式
* @param sql —— 查询SQL命令
* @param parms —— 查询条件
* @param classPo —— 需要返回结果集合的类型
* @return —— 返回一个LIST容器装PO对象,前台可直接遍历操作对象
*/
public List query( String sql , List parms,Class classPo ){
conn = this.getConnection();
entityList = new ArrayList();
//Map结构:key:表字段名 value:表字段值
//LIST结果:获取每一行数据,
//如:[{PHONE=13441231244, ADDRESS=成都市, SEX=男, YNAME=张三}, {PHONE=13551234123, ADDRESS=成都市, SEX=男, YNAME=李大}]
List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>();
try {
ps = conn.prepareStatement(sql); //预编译SQL
if( 0!=parms.size() ){
for( int i = 0; i<parms.size(); i++ ){
ps.setObject(i+1, parms.get(i)); //循环设置参数
}
}
rs = ps.executeQuery(); //执行查询操作
//下面开始封装每一行数据放入MAP,并将每行数据放入LIST
if( rs != null ){
ResultSetMetaData rsm = rs.getMetaData(); //用于获取结果集中列的类型和属性信息对象
while( rs.next() ){
Map<String,Object> map = new HashMap<String,Object>();
for( int i = 1; i<=rsm.getColumnCount();i++ ){
map.put(rsm.getColumnName(i), rs.getObject(i)); //字段名称——字段值
}
resultList.add(map); //将一行的数据放入LIST
}
}
//利用反射来封住数据返回一个指定对象类型的数据集
//LIST结构:[AddressBookPO@9446e4, AddressBookPO@ba5c7a, AddressBookPO@10d593e]
entityList = ResultSetToObject.ToObjectList(classPo, resultList);
} catch (Exception e) {
e.printStackTrace();
}
try {
this.close(); //关闭所有对象
} catch (Exception e) {
e.printStackTrace();
}
return entityList;
}
/**
* 查询记录总数
* @param sql
* @param parms
* @return
*/
public int countQuery( String sql,List parms){
conn = this.getConnection();
int count = 0;
try {
ps = conn.prepareStatement(sql); //预编译SQL
if( null!= parms && 0!= parms.size() ){
for( int i = 0; i<parms.size(); i++ ){
ps.setObject(i+1, parms.get(i)); //循环设置参数
}
}
rs = ps.executeQuery(); //执行查询操作
if( rs.next() ){
count = rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
}
return count;
}
/**
* 增删改操作
* @param sql SQL查询语句
* @param pares 判断条件
* @return
*/
public int edit( String sql, List pares ){
conn = this.getConnection();
int hasEffect = 0;
try {
ps = conn.prepareStatement(sql); //预编译SQL
if( 0 != pares.size() ){
for( int i = 0; i<pares.size(); i++ ){
System.out.println(pares.get(i).getClass().getName());
ps.setObject(i+1, pares.get(i)); //循环设置参数
}
}
hasEffect = ps.executeUpdate(); //执行增删改返回影响行数
} catch (SQLException e) {
e.printStackTrace();
}
try {
this.close(); //关闭所有对象
} catch (Exception e) {
e.printStackTrace();
}
return hasEffect;
}
/**
* 关闭所有对象
* @throws Exception
*/
public void close() throws Exception{
if( rs != null ){
rs.close();
}
if( ps != null ){
ps.close();
}
if( conn != null ){
conn.close();
}
}
}
?DBManager.java
package com.ran.db;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* C3P0连接池类
* @author Administrator
*
*/
public class DBManager {
private static final Properties pro = new Properties(); //属性文件对象
private static final String FILEDIR = "src/dataSource.properties"; //指定属性文件地址
public static String DBSOURCE; //数据源
private static final DBManager dbm = new DBManager();
static ComboPooledDataSource cpds = null;
private Connection conn = null;
private DBManager(){}
public static DBManager getInstance(){
return dbm;
}
//通过静态代码块读取数据源,保证只执行一次
static{
try {
FileInputStream connFileStream =new FileInputStream(new File(FILEDIR));
pro.load(connFileStream); //读取属性文件
} catch (Exception e) {
e.printStackTrace();
}
DBSOURCE = pro.getProperty("DATASOURCE");
cpds = new ComboPooledDataSource(DBSOURCE);
}
/**
* 获取连接
* @return
*/
public synchronized Connection getConnection(){
try {
conn = cpds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
?PageDBManager.java
package com.ran.db;
import java.util.ArrayList;
import java.util.List;
import com.ran.generic.SimpleSQLGenerator;
/**
* 分页管理类
* @author Administrator
*/
public class PageDBManager {
private static final JDBCUtil jdbc = new JDBCUtil(); //数据库JDBC操作类
private PageBean pageBean = null;
private List fieldsValue = null;
public PageBean getPageBean() {
return pageBean;
}
public void setPageBean(PageBean pageBean) {
this.pageBean = pageBean;
}
public PageDBManager(){}
public PageDBManager( int pageRecord,int currentPage,SimpleSQLGenerator sqlGen ){
pageBean = new PageBean(pageRecord); //构建一个PageBean对象并初始化每页记录数
pageBean.setCurrentPage(currentPage); //设置当前页
this.searchAllRecord(sqlGen); //查询总记录数
pageBean.initTotalPage(); //初始化总页数
}
/**
* 初始化总页数
* @param sqlGen SQL构造器
*/
public void searchAllRecord( SimpleSQLGenerator sqlGen ){
if( null != sqlGen.getFields() ){
fieldsValue = new ArrayList( sqlGen.getFields().values() );
}
pageBean.setAllRecord(jdbc.countQuery(sqlGen.countSQL(), fieldsValue));
}
/**
* 条件分页查询
* @param sqlGen SQL构造器
* @param classPo 结果集类型
* @return
*/
public List queryRecordList( SimpleSQLGenerator sqlGen,Class classPo ){
List recordList = new ArrayList();
if( null != sqlGen.getFields() ){
fieldsValue = new ArrayList( sqlGen.getFields().values() );
}
//判断数据源
if( "mysql".equals(DBManager.DBSOURCE) ){
recordList = jdbc.query(sqlGen.pageSQLForMySQL(pageBean.getPageRecord(), pageBean.getCurrentPage()), fieldsValue, classPo);
}else if( "oracle".equals(DBManager.DBSOURCE) ){
recordList = jdbc.query(sqlGen.pageSQLForOracle(pageBean.getPageRecord(), pageBean.getCurrentPage()), fieldsValue, classPo);
}
return recordList;
}
}
?PageBean.java
package com.ran.db;
import java.util.List;
public class PageBean {
private int currentPage; //当前页
private int totalPage; //总页数
private int pageRecord; //每页记录数
private int allRecord; //总记录数
private List resultList = null; //结果集
public PageBean(){}
public PageBean( int pageRecord ){
this.pageRecord = pageRecord;
if( this.currentPage == 0 ){
this.currentPage = 1;
}
}
public List getResultList() {
return resultList;
}
public void setResultList(List resultList) {
this.resultList = resultList;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getPageRecord() {
return pageRecord;
}
public void setPageRecord(int pageRecord) {
this.pageRecord = pageRecord;
}
public int getAllRecord() {
return allRecord;
}
public void setAllRecord(int allRecord) {
this.allRecord = allRecord;
}
/**
* 初始化总页数
* @return 返回总页数
*/
public void initTotalPage(){
if( this.allRecord % this.pageRecord == 0 ){
this.totalPage = allRecord / pageRecord;
}else{
this.totalPage = allRecord / pageRecord + 1;
}
}
}
?ResultSetToObject.java
package com.ran.generic;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 封装实体类-将制定对象类型数据通过反射赋值初始化对象
* @author Administrator
*/
public class ResultSetToObject {
private static List resultList = null;
private static Object o = null;
/**
* 下面这个方法有个弊端:实体对象的属性必须和数据库对应表的字段名称一样,如USER对象有一个name属性
* 那么其对于数据表TUSER的字段名称也必须是NAME。
* 如果属性名称和字段名称不一致怎么办?
* 解决办法:可以将对象的属性和对应数据表的字段名做一个映射,最简单的就是创建一个属性文件以键值对方式存放
* 如:name:USERNAME,age:USERAGE。通过读取属性文件来匹配属性和字段的映射。
* @param c
* @param resultSetList
* @return
* @throws Exception
*/
public static List ToObjectList( Class c, List<Map<String,Object>> resultSetList ) throws Exception{
resultList = new ArrayList();
Field[] fields = c.getDeclaredFields();
for( Map<String,Object> map : resultSetList ){
o = c.newInstance();
for( Field f:fields ){
String fieldName = f.getName();
String methodName = "set"+fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
Method method = c.getMethod(methodName, new Class[]{f.getType()});
method.invoke(o, map.get(f.getName().toUpperCase()));
}
resultList.add(o);
}
return resultList;
}
}
?SimpleSQLGenerator.java
package com.ran.generic;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class SimpleSQLGenerator {
private String tableName; //目标表
private int editFlag; //1=insert,2=update,3=delete
private String[] queryFields; //查询字段组: select String[0],String[1],String[2] from table
private Map<String,Object> updateFields = null; //UPDATE字段-字段值 :SET name="zhangsan",sex="男"
private Map<String,Object> insertFields = null; //INSERT字段-字段值 :INSERT INTO TABLE(KEYSET) VALUES(VALUES);
private Map<String,Object> fields = null; //WHERE条件字段-字段值 :WHERE name="zhangsan"
private boolean isOrder; //是否排序
private String orderField; //排序字段名 order by orderField
private String sort; //升序或降序
public static final String ASC = "ASC"; //升序
public static final String DESC = "DESC"; //降序
private String sql; //生成SQLxxssss
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public int getEditFlag() {
return editFlag;
}
public void setEditFlag(int editFlag) {
this.editFlag = editFlag;
}
public String[] getQueryFields() {
return queryFields;
}
public void setQueryFields(String[] queryFields) {
this.queryFields = queryFields;
}
public Map<String, Object> getUpdateFields() {
return updateFields;
}
public void setUpdateFields(Map<String, Object> updateFields) {
this.updateFields = updateFields;
}
public Map<String, Object> getInsertFields() {
return insertFields;
}
public void setInsertFields(Map<String, Object> insertFields) {
this.insertFields = insertFields;
}
public Map<String, Object> getFields() {
return fields;
}
public void setFields(Map<String, Object> fields) {
this.fields = fields;
}
public boolean isOrder() {
return isOrder;
}
public void setOrder(boolean isOrder) {
this.isOrder = isOrder;
}
public String getOrderField() {
return orderField;
}
public void setOrderField(String orderField) {
this.orderField = orderField;
}
public String getSort() {
return sort;
}
public void setSort(String sort) {
this.sort = sort;
}
public SimpleSQLGenerator(){}
public SimpleSQLGenerator( String tableName,String[] queryFields,Map<String,Object> updateFields,Map<String,Object> insertFields,Map<String,Object> fields,
boolean isOrder,String orderField,String sort){
this.tableName = tableName;
this.queryFields = queryFields;
this.updateFields = updateFields;
this.insertFields = insertFields;
this.fields = fields;
this.isOrder = isOrder;
this.orderField = orderField;
this.sort = sort;
}
public boolean isNULLForMap( Map map ){
if( null != map && map.keySet().size() > 0 ){
return true;
}else{
return false;
}
}
//拼接WHERE后的条件字段 : WHERE NAME=?,SEX=?,ADDRESS=?......
public void spiltWHERE(){
if( this.isNULLForMap(fields) ){
Set<String> fieldSet = fields.keySet();
sql += "where ";
for(String field:fieldSet ){
sql += " "+field+" =? and";
}
sql = sql.substring(0,sql.lastIndexOf("and"));
}
}
//生成聚合countSQL用于查询结果集总记录数
public String countSQL(){
sql = "select count(*) from "+tableName+" t ";
this.spiltWHERE();
return sql;
}
//增删改SQL生成器,参数editFlag:0=insert,1=update,2=delete
public String editSQL( int editFlag ){
if( editFlag == 0 ){
if( this.isNULLForMap(insertFields) ){
Set<String> insertFieldSet = insertFields.keySet();
int filedsSize = insertFieldSet.size();
//构建INSERT语句
if( filedsSize != 0 ){
sql = "insert into "+tableName+" ( ";
for( String field : insertFieldSet ){
sql += field+",";
}
sql = sql.substring(0, sql.length()-1)+" ) values( ";
for( String field : insertFieldSet ){
sql += "?,";
}
sql = sql.substring(0, sql.length()-1)+" )";
}
}
//构建UPDATE语句
}else if( editFlag == 1 ){
sql = "UPDATE "+tableName+" SET ";
Set<String> updateFieldSet = updateFields.keySet();
for( String field : updateFieldSet ){
sql += field+"=? ,";
}
sql = sql.substring(0,sql.length()-1);
this.spiltWHERE();
//构建DELETE语句
}else if( editFlag == 2 ){
sql = "DELETE FROM "+tableName+" ";
this.spiltWHERE();
}
return sql;
}
//条件查询SQL
public String querySQL(){
sql = "SELECT ";
if( queryFields.length > 0 ){
for( String queryField:queryFields ){
sql += queryField+" , ";
}
sql = sql.substring(0,sql.lastIndexOf(","))+" FROM "+tableName+" ";
}else{
sql = "SELECT * FROM "+tableName+" ";
}
this.spiltWHERE();
if( this.isOrder ){
sql += " ORDER BY "+orderField+" "+sort;
}
return sql;
}
//Oracle分页SQL:基本满足大部分功能性分页,如有性能瑕疵欢迎帮忙改进
public String pageSQLForOracle( int pageRecord , int currentPage ){
//排序分页:select * from ( select rownum rn, t.* from ( select * from ADDDRESSBOOK order by SEX ) t where rownum <= 5) where rn > 0
//无排序分页:select * from ( select rownum rn, t.* from ADDDRESSBOOK t where rownum <= 5) where rn > 0
if( this.isOrder ){
sql = "select * from ( select rownum rn, t.* from ( select * from "+tableName+" ";
this.spiltWHERE();
sql += " ORDER BY "+orderField+" "+sort+" ) t where rownum <= "+currentPage*pageRecord+" ) where rn > "+(currentPage-1)*pageRecord;
}else{
sql = "select * from ( select rownum rn,* from "+tableName+" where ";
this.spiltWHERE();
sql += " and rownum <= "+currentPage*pageRecord+" ) where rn > "+(currentPage-1)*pageRecord;
}
return sql;
}
//MySQL分页SQL:基本满足大部分功能性分页,如有性能瑕疵欢迎帮忙改进
public String pageSQLForMySQL( int pageRecord , int currentPage ){
//排序分页:select * from ADDRESSBOOK order by createtime limit 0,5
//无排序分页:select * from ADDRESSBOOK order limit 0,5
sql = "select * from "+tableName+" t ";
this.spiltWHERE();
if( this.isOrder ){
sql += " ORDER BY "+orderField+" "+sort;
}
sql += " limit "+(currentPage-1)*pageRecord + ","+pageRecord;
return sql;
}
}
