编写自己的JDBC框架
目的
简化代码,提高开发效率
设计模式
策略设计模式
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #连接设置 2 driverClassName=com.mysql.jdbc.Driver 3 url=jdbc:mysql://localhost:3306/day17 4 username=root 5 password=sorry 6 7 #<!-- 初始化连接 --> 8 initialSize=10 9 10 #最大连接数量 11 maxActive=50 12 13 #<!-- 最大空闲连接 --> 14 maxIdle=20 15 16 #<!-- 最小空闲连接 --> 17 minIdle=5 18 19 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --> 20 maxWait=60000 21 22 23 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 24 #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。 25 connectionProperties=useUnicode=true;characterEncoding=utf8 26 27 #指定由连接池所创建的连接的自动提交(auto-commit)状态。 28 defaultAutoCommit=true 29 30 #driver default 指定由连接池所创建的连接的只读(read-only)状态。 31 #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix) 32 defaultReadOnly= 33 34 #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 35 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE 36 defaultTransactionIsolation=REPEATABLE_READ
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.List; 2 import org.junit.Test; 3 import com.itheima.dbassist.BeanHandler; 4 import com.itheima.dbassist.BeanListHandler; 5 import com.itheima.dbassist.DBAssist; 6 import com.itheima.domain.User; 7 import com.itheima.util.DBCPUtil; 8 9 public class UserDaoImpl { 10 private DBAssist da = new DBAssist(DBCPUtil.getDataSource()); 11 //SQL和参数 12 @Test 13 public void add(){ 14 da.update("insert into user values(?,?,?,?)", "aa","wf","123","非同寻常"); 15 } 16 @Test 17 public void update(){ 18 da.update("update user set password=? where id=?", "12345","aa"); 19 } 20 @Test 21 public void delete(){ 22 da.update("delete from user where id=?", "aa"); 23 } 24 @Test 25 public void query1(){ 26 User user = (User)da.query("select * from user where id=?", new BeanHandler(User.class), "a5cc6e18-f3b8-44a6-bcdd-c6476f1edb87"); 27 System.out.println(user); 28 } 29 @Test 30 public void query2(){ 31 List<User> users = (List<User>)da.query("select * from user", new BeanListHandler(User.class)); 32 for(User user:users) 33 System.out.println(user); 34 } 35 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.lang.reflect.Field; 2 import java.sql.ResultSet; 3 import java.sql.ResultSetMetaData; 4 import java.util.ArrayList; 5 import java.util.List; 6 /** 7 * 适合有多条结果记录的数据封装 8 * 返回的是一个List 9 * 10 */ 11 public class BeanListHandler implements ResultSetHandler { 12 private Class clazz; 13 public BeanListHandler(Class clazz){ 14 this.clazz = clazz; 15 } 16 public Object handle(ResultSet rs) { 17 try { 18 List list = new ArrayList(); 19 while(rs.next()){ 20 Object bean = clazz.newInstance(); 21 //封装数据:书写JavaBean的前提,类中的字段名或属性名与数据库表的字段名保持一致 22 ResultSetMetaData rsmd = rs.getMetaData(); 23 int columnCount = rsmd.getColumnCount(); 24 for(int i=0;i<columnCount;i++){ 25 String columnName = rsmd.getColumnName(i+1);//与JavaBean的字段名一致 26 Object columnValue = rs.getObject(columnName);//列值 27 28 //得到JavaBean的对应字段 29 Field field = clazz.getDeclaredField(columnName); 30 field.setAccessible(true);//强暴它 有可能是私有的 31 field.set(bean, columnValue); 32 } 33 list.add(bean); 34 35 } 36 return list; 37 } catch (Exception e) { 38 throw new RuntimeException("封装数据失败"); 39 } 40 } 41 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.sql.Connection; 2 import java.sql.ParameterMetaData; 3 import java.sql.PreparedStatement; 4 import java.sql.ResultSet; 5 import java.sql.SQLException; 6 import java.sql.Statement; 7 8 import javax.sql.DataSource; 9 10 import com.itheima.util.DBCPUtil; 11 12 public class DBAssist { 13 private DataSource dataSource; 14 public DBAssist(DataSource dataSource){ 15 this.dataSource = dataSource; 16 } 17 /* 18 * 能够执行DML语句:INSERT UPDATE DELETE 19 */ 20 public void update(String sql,Object...params){ 21 Connection conn = null; 22 PreparedStatement stmt = null; 23 ResultSet rs = null; 24 try{ 25 conn = dataSource.getConnection();//具体的数据源无关 26 stmt = conn.prepareStatement(sql); 27 //看sql中的占位符的个数:参数元信息的获取 28 ParameterMetaData pmd = stmt.getParameterMetaData(); 29 int paramCount = pmd.getParameterCount(); 30 //设置参数:略 31 if(paramCount>0){ 32 //判断参数占位符的个数和params的个数是否一致 33 if(params==null||params.length!=paramCount){ 34 throw new RuntimeException("参数个数不匹配"); 35 } 36 //设置SQL中的参数占位符的值 37 for(int i=0;i<paramCount;i++){ 38 stmt.setObject(i+1, params[i]); 39 } 40 } 41 stmt.executeUpdate(); 42 }catch(Exception e){ 43 throw new RuntimeException(e); 44 }finally{ 45 release(rs, stmt, conn); 46 } 47 } 48 /** 49 * 执行查询 50 * @return 封装了数据的对象 51 */ 52 public Object query(String sql,ResultSetHandler handler,Object...params){ 53 Connection conn = null; 54 PreparedStatement stmt = null; 55 ResultSet rs = null; 56 try{ 57 conn = dataSource.getConnection(); 58 stmt = conn.prepareStatement(sql); 59 //看sql中的占位符的个数:参数元信息的获取 60 ParameterMetaData pmd = stmt.getParameterMetaData(); 61 int paramCount = pmd.getParameterCount(); 62 //设置参数:略 63 if(paramCount>0){ 64 //判断参数占位符的个数和params的个数是否一致 65 if(params==null||params.length!=paramCount){ 66 throw new RuntimeException("参数个数不匹配"); 67 } 68 //设置SQL中的参数占位符的值 69 for(int i=0;i<paramCount;i++){ 70 stmt.setObject(i+1, params[i]); 71 } 72 } 73 rs = stmt.executeQuery();//如何封装呢: 74 //有结果集:不知道有什么字段和值 75 //不知道封装成什么对象:谁用谁知道 76 77 //策略:有数据----->有目标 78 return handler.handle(rs); 79 }catch(Exception e){ 80 throw new RuntimeException(e); 81 }finally{ 82 release(rs, stmt, conn); 83 } 84 } 85 private void release(ResultSet rs,Statement stmt,Connection conn){ 86 if(rs!=null){ 87 try { 88 rs.close(); 89 } catch (SQLException e) { 90 e.printStackTrace(); 91 } 92 rs = null; 93 } 94 if(stmt!=null){ 95 try { 96 stmt.close(); 97 } catch (SQLException e) { 98 e.printStackTrace(); 99 } 100 stmt = null; 101 } 102 if(conn!=null){ 103 try { 104 conn.close(); 105 } catch (SQLException e) { 106 e.printStackTrace(); 107 } 108 conn = null; 109 } 110 } 111 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.itheima.dbassist; 2 3 import java.sql.ResultSet; 4 //抽象策略 5 public interface ResultSetHandler { 6 /** 7 *把结果集中的数据封装到对象中 8 * @param rs 9 * @return 10 */ 11 Object handle(ResultSet rs); 12 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.lang.reflect.Field; 2 import java.sql.ResultSet; 3 import java.sql.ResultSetMetaData; 4 //策略的具体实现 5 /** 6 * 专门用于封装结果中只有一条的记录的情况 7 * 返回值:封装好的Java对象 8 * 9 */ 10 public class BeanHandler implements ResultSetHandler { 11 private Class clazz; 12 public BeanHandler(Class clazz){ 13 this.clazz = clazz; 14 } 15 public Object handle(ResultSet rs) { 16 try { 17 if(rs.next()){ 18 Object bean = clazz.newInstance(); 19 //封装数据:书写JavaBean的前提,类中的字段名或属性名与数据库表的字段名保持一致 20 ResultSetMetaData rsmd = rs.getMetaData(); 21 int columnCount = rsmd.getColumnCount(); 22 for(int i=0;i<columnCount;i++){ 23 String columnName = rsmd.getColumnName(i+1);//与JavaBean的字段名一致 24 Object columnValue = rs.getObject(columnName);//列值 25 26 //得到JavaBean的对应字段 27 Field field = clazz.getDeclaredField(columnName); 28 field.setAccessible(true);//强暴它 有可能是私有的 29 field.set(bean, columnValue); 30 } 31 32 return bean; 33 } 34 return null; 35 } catch (Exception e) { 36 throw new RuntimeException("封装数据失败"); 37 } 38 } 39 40 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class User { 2 private String id; 3 private String username; 4 private String password; 5 private String nick; 6 public String getId() { 7 return id; 8 } 9 public void setId(String id) { 10 this.id = id; 11 } 12 public String getUsername() { 13 return username; 14 } 15 public void setUsername(String username) { 16 this.username = username; 17 } 18 public String getPassword() { 19 return password; 20 } 21 public void setPassword(String password) { 22 this.password = password; 23 } 24 public String getNick() { 25 return nick; 26 } 27 public void setNick(String nick) { 28 this.nick = nick; 29 } 30 @Override 31 public String toString() { 32 return "User [id=" + id + ", username=" + username + ", password=" 33 + password + ", nick=" + nick + "]"; 34 } 35 36 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.InputStream; 2 import java.sql.Connection; 3 import java.sql.ResultSet; 4 import java.sql.SQLException; 5 import java.sql.Statement; 6 import java.util.Properties; 7 8 import javax.sql.DataSource; 9 10 import org.apache.commons.dbcp.BasicDataSourceFactory; 11 12 public class DBCPUtil { 13 private static DataSource dataSource; 14 static{ 15 try { 16 InputStream in = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); 17 Properties props = new Properties(); 18 props.load(in); 19 dataSource = BasicDataSourceFactory.createDataSource(props); 20 } catch (Exception e) { 21 throw new ExceptionInInitializerError("初始化数据源失败"); 22 } 23 } 24 public static Connection getConnection(){ 25 try { 26 return dataSource.getConnection(); 27 } catch (SQLException e) { 28 throw new RuntimeException("获取数据库连接失败"); 29 } 30 } 31 public static DataSource getDataSource(){ 32 return dataSource; 33 } 34 35 }
合群是堕落的开始 优秀的开始是孤行