优化数据库访问代码:一、使用数据库连接池。二、编写jdbc框架。
一、使用jdbc编写查询框架
除SQL语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中
在DBManager类中-------------------此类是一个数据库连接池和框架类
public class DBManager {
private static DataSource ds=null;
//加载配置文件
static{
InputStream in=DBManager.class.getClassLoader().getResourceAsStream("config/dbcp.properties");
//映射类型的集合,用来存放读取出来的键值对
Properties p=new Properties();
try {
p.load(in);
//通过配置文件构建数据库连接池
ds=BasicDataSourceFactory.createDataSource(p);
} catch (Exception e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
public static Connection getconnConnection() throws SQLException{
return ds.getConnection();
}
//归还到数据库连接池中
public static void release(Connection con,Statement st,ResultSet rs){
if (rs != null)
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (st != null)
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (con != null)
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//进行代码优化
public static void update(String sql,Object []params ){
Connection con=null;
PreparedStatement st=null;
ResultSet rs=null;
try {
con=DBManager.getconnConnection();
st=con.prepareStatement(sql);
for(int i=0;i<params.length;i++){
st.setObject(i+1,params[i]);
}
st.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}finally{
DBManager.release(con, st, rs);
}
}
public static Object find(String sql,Object []params,ResultSetHandlerrsh) throws SQLException{
Connection con=null;
PreparedStatement st=null;
ResultSet rs=null;
try {
con=DBManager.getconnConnection();
st=con.prepareStatement(sql);
for(int i=0;i<params.length;i++){
st.setObject(i+1,params[i]);
}
rs=st.executeQuery();
return rsh.handler(rs);
}finally{
DBManager.release(con, st, rs);
}
}
}
由于不知道程序员是怎么处理结果集的,所以将结果集的操作封装到一个接口中
如下:
public interface ResultSetHandler {
public Object handler(ResultSet rs);
}
实现接口的类处理结果集
public class BeanListHandler implements ResultSetHandler {
private Class clazz;
public BeanListHandler(Class clazz){
this.clazz=clazz;
}
@Override
public Object handler(ResultSet rs) {
List list=new ArrayList();
try {
while(rs.next()){
//读取一行
//将其封装到bean对象中
Object bean=clazz.newInstance();
ResultSetMetaData meta=rs.getMetaData();
int count=meta.getColumnCount();
for(int i=1;i<=count;i++){
String name=meta.getColumnName(i);
Object value=rs.getObject(name);
Field f=clazz.getDeclaredField(name);
f.setAccessible(true);
f.set(bean, value);
}
//把bean对象加入到list集合中
list.add(bean);
}
return list;
} catch (Exception e) {
// TODO Auto-generatedcatch block
throw new RuntimeException(e);
}
}
}
在userDaoImpl中调用此方法:
public void insert(){
QueryRunner runner=new QueryRunner(DBManagaer_c3p0.datasource());
String sql="insert into users(name,password) values('pp','1111')";
try {
runner.update(sql);
} catch (SQLException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
二、Apache——DBUtils框架
·commons-dutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性 能。一次dbutils称为很多不喜欢hibernate的公司的首选。
·api介绍:
·org.apache.commons.dbutils.QueryRunner
·org.apache.commons.dbutils.ResultSetHandler
·工具类
·org.apache.commons.dbutils.DbUtils
2-1、工具类-----------Dbutils类
DbUtils:提供如关闭连接、装载Jdbc驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
·public static void close(。。。)throws java..sql.SQLException:
DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是null,如果不是的话,他们就关闭Connection。Statement和ResultSet。
·public static void closeQuietly(。。。):这一类方法不仅能在Connection。Statement和ResultSet为null情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
·public static void commitAndCloseQuietly(Connection conn):用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
·public static Boolean loadDriver(java.lang.String driverClassName):这一方法装载并注册JDBC驱动程序如果成功就返回true。使用该方法,你不需要捕捉这个异常------ClassNotFoundException、
2-2、封装了增删改查的方法---------------QueryRunner类
·该类简单化了SQL查询,他与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
·QueryRunner类提供了两个构造方法:
·默认的构造方法
·需要一个javax.sql.DataSource来做参数的构造方法。
·QueryRunner类的主要方法:
·`public Object query(Connection conn, String sql, Object[] params,ResultSetHandler rsh) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
·public Object query(String sql, Object[] params, ResultSetHandlerrsh) throws SQLException: 几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource) 或使用的setDataSource 方法中重新获得 Connection。
·public Object query(Connection conn, String sql, ResultSetHandlerrsh) throws SQLException : 执行一个不需要置换参数的查询操作。
·public int update(Connection conn, String sql, Object[] params)throws SQLException:用来执行一个更新(插入、更新或删除)操作。
·public int update(Connection conn, String sql) throws SQLException:用来执行一个不需要置换参数的更新操作。
2-3、封装了查询方法中结果集处理的类--------------ResultSetHander接口
·该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式。
·ResultSetHandler接口提供了一个单独的方法:Object handle(java.sql.ResultSet rs)
·ResultSetHander接口的实现类:
·ArrayHandler:把结果集中的第一行数据转成对象数组。
·ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
·BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
·BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
·ColumnListHandler:将结果集中某一列的数据存放到List中。
·KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
·MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
·MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List