二、Java持久化基础-优化封装JDBC工具类_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 二、Java持久化基础-优化封装JDBC工具类

二、Java持久化基础-优化封装JDBC工具类

 2016/5/12 5:33:34  ranji13  程序员俱乐部  我要评论(0)
  • 摘要:Java持久化基础-优化封装JDBC工具类今天对昨天的JDBC连接进行了优化和封装,优化如下:1、将数据库驱动等连接参数放入属性文件,通过读取属性文件来获取,这样在不更改源码的前提下即可实现对各种关系型数据库的连接,只需修改配置文件即可;2、将驱动的加载、属性文件的读取等一系列一次性操作放进静态域,这样保证程序只执行一次,提高运行效率;3、优化封装了查询方法query(),只需传递sql命令和需要返回的对象类型就可获得一个对象集合,在展示层只需遍历集合直接操作对象获取属性值,完全面向对象的方式
  • 标签:工具 Java 优化

Java持久化基础-优化封装JDBC工具类

?

今天对昨天的JDBC连接进行了优化和封装,优化如下:

1、将数据库驱动等连接参数放入属性文件,通过读取属性文件来获取,这样在不更改源码的前提下即可实现对各种关系型数据库的连接,只需修改配置文件即可;

2、将驱动的加载、属性文件的读取等一系列一次性操作放进静态域,这样保证程序只执行一次,提高运行效率;

3、优化封装了查询方法query(),只需传递sql命令和需要返回的对象类型就可获得一个对象集合,在展示层只需遍历集合直接操作对象获取属性值,完全面向对象的方式;

注:对query()的优化和封装大量使用了Java反射,虽然在效率上有损失,但是对于面向对象和前台的操作习惯而言无异于利大于弊。

?

1、JDBCUtil工具类

class="java" name="code">import java.io.File;
import java.io.FileInputStream;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;


public class JDBCUtil {
	
	private static String CLASSNAME;  //驱动类
	
	private static String DRIVER;  //驱动,填写数据库IP、端口和数据库名
	
	private static String DBUNAME;  //数据库用户名
	
	private static String DBPWD;  //数据库密码
	
	private static final Properties pro = new Properties();     //属性文件对象
	private static final String FILEDIR = "src/conn.properties";   //指定属性文件地址
	public static Connection conn = null;
	public static PreparedStatement ps = null;
	public static ResultSet rs = null;
	private List entityList = null;
	
	public JDBCUtil(){
		this.getConnection();   //初始化连接
	}
	
	//通过静态代码块读取属性文件和注册数据库驱动,保证只执行一次
	static{
		try {
			FileInputStream connFileStream =new FileInputStream(new File(FILEDIR));
			pro.load(connFileStream);   //读取属性文件
		} catch (Exception e) {
			e.printStackTrace();
		}
		//获取对应值
		CLASSNAME = pro.getProperty("CLASSNAME");
		DRIVER = pro.getProperty("DRIVER");
		DBUNAME = pro.getProperty("DBUNAME");
		DBPWD = pro.getProperty("DBUPWD");
		try {
			Class.forName(CLASSNAME);   //加载驱动
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取一个连接对象
	 */
	public void getConnection(){
		try {
			conn = DriverManager.getConnection(DRIVER,DBUNAME,DBPWD);
		} catch (Exception e) {
			System.out.println("数据库连接失败!");
			e.printStackTrace();
		}
	}
	
	/**
	 * 优化后的query,只需传递sql命令和需要返回的对象类型就可获得一个对象集合,
	 * 在展示层只需变量集合直接操作对象获取属性值,完全面向对象的方式
	 * @param sql —— 查询SQL命令
	 * @param parms —— 查询条件
	 * @param classPo —— 需要返回结果集合的类型
	 * @return —— 返回一个LIST容器装PO对象,前台可直接遍历操作对象
	 */
	public List query( String sql , Object[] parms,Class classPo ){
		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.length ){
				for( int i = 0; i<parms.length; i++ ){
					ps.setObject(i+1, parms[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  SQL查询语句
	 * @param pares  判断条件
	 * @return
	 */
	public int edit( String sql, Object[] pares ){
		int hasEffect = 0;
		try {
			ps = conn.prepareStatement(sql);  //预编译SQL
			
			if( 0 != pares.length ){
				for( int i = 0; i<pares.length; i++ ){
					ps.setObject(i+1, pares[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();
		}
	}
	

}

?

2、conn.properties属性文件格式

?

CLASSNAME=oracle.jdbc.driver.OracleDriver
DRIVER=jdbc\:oracle\:thin\:@127.0.0.1\:1521\:ORCL
DBUNAME=scott
DBUPWD=tiger

?3、封装实体类——ResultSetToObject

?

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;
	}
	
}

?4、实体对象——AddressBookPO.java

public class AddressBookPO {
	
	public String yname;
	
	public String sex;
	
	public String phone;
	
	public String address;

	public String getYname() {
		return yname;
	}

	public void setYname(String yname) {
		this.yname = yname;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

}

5、测试类

import java.util.ArrayList;


public class MyDAO {
	
	public static void main(String[] args) {
		JDBCUtil jdbc = new JDBCUtil();
		String sql = "select * from addressbook t where t.address = '成都市'";
		ArrayList<AddressBookPO> addressBookList = (ArrayList<AddressBookPO>) jdbc.query(sql, new Object[]{}, AddressBookPO.class);
		for(AddressBookPO addressBook:addressBookList ){
			System.out.println(addressBook.getYname());  //输出满足居住地在成都市的姓名
		}
	}
}

运行结果:
张三
李大

?

?6、数据表结构

数据表ADDRESSBOOK

?

prompt PL/SQL Developer import file
prompt Created on 2016年5月4日 by Administrator
set feedback off
set define off
prompt Creating ADDRESSBOOK...
create table ADDRESSBOOK
(
  YNAME   VARCHAR2(50),
  SEX     VARCHAR2(50),
  PHONE   VARCHAR2(50),
  ADDRESS VARCHAR2(50)
)
tablespace USERS
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );

prompt Disabling triggers for ADDRESSBOOK...
alter table ADDRESSBOOK disable all triggers;
prompt Loading ADDRESSBOOK...
insert into ADDRESSBOOK (YNAME, SEX, PHONE, ADDRESS)
values ('张三', '男', '13441231244', '成都市');
insert into ADDRESSBOOK (YNAME, SEX, PHONE, ADDRESS)
values ('李大', '男', '13551234123', '成都市');
insert into ADDRESSBOOK (YNAME, SEX, PHONE, ADDRESS)
values ('王黎', '女', '13441234211', '广元市');
insert into ADDRESSBOOK (YNAME, SEX, PHONE, ADDRESS)
values ('周提奥', '男', '13665423212', '德阳市');
insert into ADDRESSBOOK (YNAME, SEX, PHONE, ADDRESS)
values ('张凯', '男', '13651234287', '南充市');
insert into ADDRESSBOOK (YNAME, SEX, PHONE, ADDRESS)
values ('孟麥', '男', '13654355433', '西昌市');
insert into ADDRESSBOOK (YNAME, SEX, PHONE, ADDRESS)
values ('凤荏熙', '女', '13554345642', '遂宁市');
commit;
prompt 7 records loaded
prompt Enabling triggers for ADDRESSBOOK...
alter table ADDRESSBOOK enable all triggers;
set feedback on
set define on
prompt Done.

?
?

?

  • 大小: 100.3 KB
  • 查看图片附件
发表评论
用户名: 匿名