c3p0连接池(C3p0连接池,只有当用户获取连接时,才会包装Connection。)
第一步:导入c3p0
第二步:在classpath目录下,创建一个c3p0-config.xml
第三步:创建工厂类获取这个连接
package cn.itcast.utils; import java.sql.Connection; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class DataSourceUtils { private static DataSource ds; static{ ds = //默认的读取c3p0-config.xml中默认配置 new ComboPooledDataSource(); } public static DataSource getDatasSource(){ return ds; } public static Connection getConn(){ Connection con = null; try{ con = ds.getConnection();//每一次从ds中获取一个新的连接 }catch(Exception e){ e.printStackTrace(); } return con; } }
ComboPooledDataSource有三个构造:
没有参数的.
接收一个boolean
默认的情况下,为true,即所有connection.autoCommit属性为true.
在一个c3p0-config.xml文件中中,可以配置多种连接。 除了默认连接,其他都叫命名的连接。通过<named-config name=”xxxx”/>
ds = new ComboPooledDataSource("db909");
元(神)数据分析
元数据,是指仅拥有Connection一个对象的情况下,分析得出数据库的所有信息。
DataBaseMetadate - 说明数据库的信息。
ResultSetMetadate - 说明数据结果的类型信息的。核心。
如果要进行元数据分析,就必须要使用statement,preparedstatement.
1、用databasemetadate分析数据库的数据
package cn.mata; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.Test; import cn.utils.DataSourceUtils; public class Mata { @Test public void dbm() throws Exception { Connection con=DataSourceUtils.getConn(); DatabaseMetaData dm=con.getMetaData(); ResultSet rs=dm.getCatalogs(); while(rs.next()){ String name=rs.getString("TABLE_CAT"); System.err.println(name); } System.err.println("=========================="); String dbName=dm.getDatabaseProductName(); System.err.println(dbName);//.... System.err.println("有多少表。。"); ResultSet rs2=dm.getTables("contacts", "contacts", null, new String[]{"TABLE"}); while(rs2.next()){ String name=rs2.getString("TABLE_NAME"); System.err.println(name); } } }
2、用ResultSetMetadate分析结果集
此类是用来分析查询的结果集:分析有几个列,列名,列的类型是什么?
@Test public void rsDataMata() throws Exception { Connection con = DataSourceUtils.getConn(); Statement st = con.createStatement(); st.execute("use sakila"); String sql = "select * from actor"; ResultSet rs = st.executeQuery(sql); ResultSetMetaData rsmd = rs.getMetaData(); int cols = rsmd.getColumnCount(); System.err.println(cols); List<String> colsName = new ArrayList<String>(); for (int i = 0; i < cols; i++) { String colName = rsmd.getColumnName(i + 1); System.err.println(colName); colsName.add(colName); } // 获取数据 while (rs.next()) { for (String col : colsName) { String val = rs.getString(col); System.err.println(val); } System.err.println("----"); } con.close(); }
3、将某个数据库的表全部导出到excel中.
第一步:如何用POI操作Excel
1:某个数数据库有多少表,表名是什么?
DataBaseMetadate.getMetadate().getTables(null,null,null,new String[]{Table})--excel的文件名称。
2:对每一个表进行select * 操作--每一个sheet的名称。
3:分析表结构,rs.getMetadate();ResultSetMedated
4:多个列,列名是什么--字段名就是sheet的第一行信息。
5:获取每一行的数据--放到sheet第一行以后。
package cn.excel; import java.io.FileOutputStream; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.junit.Test; import cn.utils.DataSourceUtils; public class ExcelDemo { @Test public void createXls() throws Exception{ //声明一个工作薄 HSSFWorkbook wb = new HSSFWorkbook(); //声明表 HSSFSheet sheet = wb.createSheet("第一个表"); //声明行 HSSFRow row = sheet.createRow(7); //声明列 HSSFCell cel = row.createCell(3); //写入数据 cel.setCellValue("你也好"); FileOutputStream fileOut = new FileOutputStream("d:/b.xls"); wb.write(fileOut); fileOut.close(); } @Test public void export() throws Exception { // 声明需要导出的数据库 String dbName = "contacts"; // 声明book HSSFWorkbook book = new HSSFWorkbook(); // 获取Connection,获取db的元数据 Connection con = DataSourceUtils.getConn(); // 声明statemen Statement st = con.createStatement(); // st.execute("use "+dbName); DatabaseMetaData dmd = con.getMetaData(); // 获取数据库有多少表 ResultSet rs = dmd.getTables(dbName, dbName, null, new String[] { "TABLE" }); // 获取所有表名 - 就是一个sheet List<String> tables = new ArrayList<String>(); while (rs.next()) { String tableName = rs.getString("TABLE_NAME"); tables.add(tableName); } for (String tableName : tables) { HSSFSheet sheet = book.createSheet(tableName); // 声明sql String sql = "select * from " + dbName + "." + tableName; // 查询数据 rs = st.executeQuery(sql); // 根据查询的结果,分析结果集的元数据 ResultSetMetaData rsmd = rs.getMetaData(); // 获取这个查询有多少行 int cols = rsmd.getColumnCount(); // 获取所有列名 // 创建第一行 HSSFRow row = sheet.createRow(0); for (int i = 0; i < cols; i++) { String colName = rsmd.getColumnName(i + 1); // 创建一个新的列 HSSFCell cell = row.createCell(i); // 写入列名 cell.setCellValue(colName); } // 遍历数据 int index = 1; while (rs.next()) { row = sheet.createRow(index++); // 声明列 for (int i = 0; i < cols; i++) { String val = rs.getString(i + 1); // 声明列 HSSFCell cel = row.createCell(i); // 放数据 cel.setCellValue(val); } } } con.close(); book.write(new FileOutputStream("d:/" + dbName + ".xls")); } }
4.将查询的结果封装成List<Map>
package cn.utils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.sql.DataSource; public class ListMap { DataSource ds; public ListMap() { } public ListMap(DataSource ds) { this.ds = ds; } public List<Map<String, Object>> queryList(String sql) { // 封装数据 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); Connection con = null; try { con = ds.getConnection(); Statement st = con.createStatement(); ResultSet rs = st.executeQuery(sql); // 分析数据集 ResultSetMetaData rsmd = rs.getMetaData(); // 获取列 int cols = rsmd.getColumnCount(); while (rs.next()) { Map<String, Object> map = new HashMap<String, Object>(); for (int i = 0; i < cols; i++) { String colName = rsmd.getColumnName(i + 1); Object val = rs.getObject(i + 1); map.put(colName, val); } list.add(map); } } catch (Exception e) { throw new RuntimeException(); } finally { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } return list; } }
用回调函数实现数据的动态封装
回调是指在执行时,具体的封装处理工用由第三方的类来实现。回调一般由两部分组成:
1:调用类 - QueryRunner。实例类
2:回调规范 – ResultSetHandler。一般是一个接口。
3:回调规范定义回调方法且这个方法由调用类调用。
1、以下是基本的回调:
package cn.callback; public class callbackDemo { public static void main(String[] args) { Runner run =new Runner(); run.query("sql",new Runhandler(){ @Override public void handler(){ System.err.println("handler"); } }); System.err.println("over"); } } /** * @author sunhan *定义调用类 */ class Runner { public void query(String string, Runhandler runhandler) { runhandler.handler(); } } /** * @author sunhan *定义调用规范 */ interface Runhandler{ void handler(); }
2、以下是小测试:
面试题:关于一个线程问题:如何输出aabb
package cn.demo; public class ThreadDemo { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.err.print("aa"); } }) { public void run() { System.err.print("bb"); } }.start(); } }
面试题,如何不改变list 的情况下 得到如下输出:
aaaclass java.lang.String
999class java.lang.Integer
public void Test() { List<String> list = new ArrayList<String>(); list.add("aaa"); list.add(999); for (Object o : list) { System.err.println(o + "" + o.getClass()); } }
@org.junit.Test public void Test() { List<String> list = new ArrayList<String>(); list.add("aaa"); add(list, 99); for (Object o : list) { System.err.println(o + "" + o.getClass()); } } public void add(List aa, Object oo) { aa.add(oo); } @org.junit.Test public void Test2() { List<String> list = new ArrayList<String>(); list.add("aaa"); List list2 = list; list2.add(999); for (Object o : list) { System.err.println(o + "" + o.getClass()); } } @org.junit.Test public void Test3() throws Exception { List<String> list = new ArrayList<String>(); list.add("aaa"); list.getClass().getMethod("add", Object.class).invoke(list, 999); for (Object o : list) { System.err.println(o + "" + o.getClass()); } }
3、调回调可以返回数据
package cn.callback; public class callbackDemo { public static void main(String[] args) { Runner run =new Runner(); run.query("sql",new Runhandler(){ @Override public void handler(String str) { System.err.println("handler"+str); } }); System.err.println("over"); } } /** * @author sunhan 定义调用类 */ class Runner { public void query(String sql, Runhandler runhandler) { runhandler.handler(sql); } } /** * @author sunhan 定义调用规范 */ interface Runhandler { void handler(String str); }
4、让回调可以返回任意的数据
package cn.callback; public class callbackDemo { public static void main(String[] args) { Runner run = new Runner(); run.query("sql", new Runhandler<String>() { @Override public String handler(String str) { System.err.println("haha"+str); return null; } }); System.err.println("over"); } } /** * @author sunhan 定义调用类 */ class Runner { public <T> T query(String sql, Runhandler<T> runhandler) { return runhandler.handler(sql); } } /** * @author sunhan 定义调用规范 */ interface Runhandler<T> { T handler(String str); }
5、回调在QueryRunner中的应用
第一步:实现一个调用类:
/** * 有回调的查询 */ public <T> T query(String sql, MyHandler<T> mh) { T t = null; // 声明conn Connection con = null; try { con = ds.getConnection(); // 执行查询 Statement st = con.createStatement(); ResultSet rs = st.executeQuery(sql); // 让回调去执行数据封装 t = mh.handler(rs); } catch (Exception e) { e.printStackTrace(); } finally { try { con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return t; }
第二步:定义回调规范
package cn.utils; import java.sql.ResultSet; /** * 接收rs结果集 * @author Administrator * * @param <T> */ public interface MyHandler<T> { T handler(ResultSet rs); }
第三步:实现一个回调
package cn.utils; import java.lang.reflect.Method; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.util.ArrayList; import java.util.List; public class MyBeanListHandler<T> implements MyHandler<List<T>> { private Class<T> cls; public MyBeanListHandler(Class<T> cls) { this.cls = cls; } public List<T> handler(ResultSet rs) { List<T> list = new ArrayList<T>(); try { ResultSetMetaData rsmd = rs.getMetaData(); int cols = rsmd.getColumnCount(); while (rs.next()) { T t = cls.newInstance(); // 获取列名 for (int i = 0; i < cols; i++) { String colName = rsmd.getColumnName(i + 1); String methodName = "set" + colName.substring(0, 1).toUpperCase() + colName.substring(1).toLowerCase(); // 获取类型 String javaType = rsmd.getColumnClassName(i + 1);// ="java.lang.String"; try { Method mm = cls.getMethod(methodName, Class.forName(javaType)); Object val = rs.getObject(i + 1); mm.invoke(t, val); } catch (Exception e) { } } list.add(t); } } catch (Exception e) { } return list; } }
第四步:测试:
@Test public void myutils3(){ QueryRunner run = new QueryRunner(DataSourceUtils.getDataSource()); String sql = "select * from users"; List<User> cs = run.query(sql,new MyBeanListHandler<User>(User.class)); for(User c:cs){ System.err.println(">>:"+c); } }
5、在dbutils中处理事务
事务是指用户的一次操作。这一次操作有可能是一个表,也有可能是多个表,也有可能是对一个表的多次操作。
只要是:
1:对数据数据库进行多次操作。
2:多个表,还是一个表的多次update,detelete,inset都应该开始一个事务。
如果仅做一次与数据库的操作。即只执行一个sql语句,则可以不用开事务。
如果仅做select 则没有必要开事务。事务是指用户的一次操作,这一次操作,只能有一个结果,要不然就全部成功,要不然就全部不成功。
如果需要在dbutils中管理事务。则用户必须自己传递并控制connection。
@Test public void tx1() throws Exception { QueryRunner run = new QueryRunner(DataSourceUtils.getDataSource()); Connection con = DataSourceUtils.getConn(); try { String sql = "insert into users values('U008','AA','AA')"; // 设置事务的开始标记 con.setAutoCommit(false); run.update(con, sql); String sql2 = "insert into users values('U009,'AA','AA')"; run.update(con, sql2); // 提交 con.commit(); } catch (Exception e) { System.err.println("出错了"); con.rollback(); } finally { con.close(); } }
6、不确定条件的查询
// 不确定条件的查询 @Test public void query1() throws Exception { QueryRunner run = new QueryRunner(DataSourceUtils.getDataSource()); Contact c = new Contact(); // c.setId("C001"); c.setName("王'"); c.setSex("1"); c.setTel("123"); c.setAddr("中国"); c.setAge(55); String sql = "select * from contacts where 1=1"; List<Object> params = new ArrayList<Object>(); if (c.getId() != null) { sql += " and id=?"; params.add(c.getId()); } if (c.getSex() != null) { sql = sql + " and sex=?"; params.add(c.getSex()); } if (c.getName() != null) { sql += " and name like ?"; params.add("%" + c.getName() + "%"); } if (c.getAddr() != null) { sql += " and addr like ?"; params.add("%" + c.getAddr() + "%"); } if (c.getTel() != null) { sql += " and tel like ?"; params.add("%" + c.getTel() + "%"); } if (c.getAge() != null) { sql += " and age=?"; params.add(c.getAge()); } System.err.println(">>>>>>:" + sql); System.err.println(params); List<Contact> cs = run.query(sql, new BeanListHandler<Contact>( Contact.class), params.toArray()); for (Contact cc : cs) { System.err.println(cc); } }