使用jdbc访问数据库,每次建立连接,连接完成进行相应的操作后就对其进行关闭操作。每次访问都需建立对数据库的连接,很耗资源。就像刚建好一栋房子,进去住了几天,就把它拆了重新建立,虽然可以建立,但耗很大资源。为了防止这样的事情发生,于是数据库连接池产生了。
建立数据库连接池是由第三方提供的jar包,C3P0或者DBCP的jar包都可以。
本人使用C3P0jar包自己做了一个C3P0Utils工具类,代码如下:
package com.itheima.utils; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Utils { private static DataSource ds=new ComboPooledDataSource(); /** * 获取数据库连接 * @return 返回Connection * @throws SQLException */ public static Connection getConnection() throws SQLException{ return ds.getConnection(); } /** * 获取数据源 * @return */ public static DataSource getDataSource(){ return ds; } /** * 关闭数据库 */ public static void close(ResultSet rs,Statement ps,Connection con){ if(rs!=null){ try { rs.close(); rs=null; } catch (SQLException e) { e.printStackTrace(); } } if(ps!=null){ try { ps.close(); ps=null; } catch (SQLException e) { e.printStackTrace(); } } if(con!=null){ try { con.close(); con=null; } catch (SQLException e) { e.printStackTrace(); } } } }
有了C3P0Utls工具类,自定义自己的dbutils就方便多了。
首先,在对数据库进行操作时,主要有增删改查,其中,增删改用一个方法update封装就搞定,查询涉及到把数据封装到bean中,也可以用一个方法query搞定。
具体代码如下:
package com.itheima.utils; import java.sql.Connection; import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import javax.sql.DataSource; import com.itheima.dao.ResultSetHandler; public class DbUtils { private static DataSource ds=null; public DbUtils(DataSource ds) { super(); this.ds = ds; } /** * 对数据库进行增删改操作 * @param sql SQL语句 * @param params 传入的问号对应的参数 */ public static void executeUpdate(String sql,Object...params){ Connection con=null; PreparedStatement ps=null; try { con=ds.getConnection(); ps=con.prepareStatement(sql); ParameterMetaData pmd=ps.getParameterMetaData(); int count=pmd.getParameterCount(); if(count>0){ if(params==null||params.length==0){ //参数为空或者为null,都不能匹配需要传入的问号个数,则抛出异常 throw new IllegalArgumentException("参数不能为null或者空"); }else if(params.length!=count){ System.out.println(count+"=="+params.length); //参数的长度不匹配问号个数,也要抛出异常 throw new IllegalArgumentException("参数不匹配"); } for(int i=0;i<count;i++){ //参数个数等于问号个数,则将问号设置为参数 ps.setObject(i+1, params[i]); } } ps.executeUpdate(); } catch (Exception e) { throw new RuntimeException("操作失败"); }finally{ C3P0Utils.close(null, ps, con); } } /** * 查询单条记录并封装成对象 * @param sql 要执行的语句 * @param rsh 要封装的BeanHeadler类,封装的对象为传入的类字节码 * @param params 查询参数 * @return */ public static Object executeQuery(String sql,ResultSetHandler rsh,Object...params){ Connection con=null; PreparedStatement ps=null; ResultSet rs=null; try { con=ds.getConnection(); ps=con.prepareStatement(sql); ParameterMetaData pmd=ps.getParameterMetaData(); int count=pmd.getParameterCount(); if(count>0){ if(params==null||params.length==0){ //参数为空或者为null,都不能匹配需要传入的问号个数,则抛出异常 throw new IllegalArgumentException("参数不能为null或者空"); }else if(params.length!=count){ System.out.println(count+"=="+params.length); //参数的长度不匹配问号个数,也要抛出异常 throw new IllegalArgumentException("参数个数不匹配"); } for(int i=0;i<count;i++){ //参数个数等于问号个数,则将问号设置为参数 ps.setObject(i+1, params[i]); } } rs=ps.executeQuery(); return rsh.handler(rs); } catch (Exception e) { throw new RuntimeException("操作失败"); }finally{ C3P0Utils.close(rs, ps, con); } } }
3.写一个接口
package com.itheima.dao; import java.sql.ResultSet; public interface ResultSetHandler { Object handler(ResultSet rs); }
4.写几个实现类
1.
package com.itheima.dao.impl; import java.lang.reflect.Field; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import com.itheima.dao.ResultSetHandler; /** * 自定义封装数据库查询的结果集 * @author Administrator * */ public class BeanHeadler implements ResultSetHandler { private Class clazz; public BeanHeadler(Class clazz){ this.clazz=clazz; } public Object handler(ResultSet rs) { //定义Object对象 Object obj=null; //分而治之,将rs中的结果集封装到obj对象中 try { if(rs.next()){ obj=clazz.newInstance(); //获取结果集元数据 ResultSetMetaData rsmd=rs.getMetaData(); int count=rsmd.getColumnCount(); for(int i=0;i<count;i++){ //通过元数据获取到每列的名字 String columnName=rsmd.getColumnName(i+1); //通过列名获取到列值 Object columnValue=rs.getObject(columnName); //有了列名再通过反射获取到类obj的属性值 Field f=clazz.getDeclaredField(columnName); f.setAccessible(true); f.set(obj, columnValue); } } return obj; } catch (Exception e) { throw new RuntimeException("查询失败"); } } }
2.
package com.itheima.dao.impl; import java.lang.reflect.Field; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.util.ArrayList; import java.util.List; import com.itheima.dao.ResultSetHandler; public class BeanListHeadler implements ResultSetHandler { private Class clazz; public BeanListHeadler(Class clazz){ this.clazz=clazz; } @Override public Object handler(ResultSet rs) { List list=new ArrayList(); try { ResultSetMetaData rsmd=rs.getMetaData(); int count=rsmd.getColumnCount(); while(rs.next()){ Object obj=clazz.newInstance(); //获取结果集元数据 for(int i=0;i<count;i++){ //通过元数据获取到每列的名字 String columnName=rsmd.getColumnName(i+1); //通过列名获取到列值 Object columnValue=rs.getObject(columnName); //有了列名再通过反射获取到类obj的属性值 Field f=clazz.getDeclaredField(columnName); f.setAccessible(true); f.set(obj, columnValue); } list.add(obj); } return list; } catch (Exception e) { throw new RuntimeException("查询失败"); } } }
通过以上几个步骤,一个简单的mydbutils大功告成,可以使用其灵活的对数据库进行增删改查了