连接池原理
数据库连接池:1.提前创建好多个连接对象,放到缓存中(集合),客户端用时直接从缓存中获取连接 ,用完连接后一定要还回来。
目的:提高数据库访问效率。
模拟代码:
1 package com.itheima.pool; 2 3 import java.sql.Connection; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import com.itheima.util.JdbcUtil; 8 9 //模拟连接池的实现原理:帮助理解 10 public class SimpleConnectionPool { 11 private static List<Connection> pool = new ArrayList<Connection>(); 12 static{ 13 for(int i=0;i<10;i++){ 14 //com.mysql.jdbc.Connection数据库的那个Connection实现类型 15 Connection conn = JdbcUtil.getConnection(); 16 pool.add(conn); 17 } 18 } 19 //从池中获取的连接 20 public synchronized static Connection getConnection(){ 21 if(pool.size()>0){ 22 Connection conn = pool.remove(0); 23 return conn; 24 }else{ 25 throw new RuntimeException("服务器真忙"); 26 } 27 } 28 //归还连接 29 public static void release(Connection conn){ 30 pool.add(conn); 31 } 32 public static List<Connection> getPool(){ 33 return pool; 34 } 35 }
List的Remove方法在删除元素的时候总会保持下标连续。例如,删掉第一个元素的时候,后面的元素会依次往前覆盖。
1 package com.itheima.util; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.sql.Connection; 6 import java.sql.DriverManager; 7 import java.sql.ResultSet; 8 import java.sql.SQLException; 9 import java.sql.Statement; 10 import java.util.Properties; 11 12 public class JdbcUtil { 13 14 private static String driverClass; 15 private static String url; 16 private static String user; 17 private static String password; 18 19 20 static{ 21 try { 22 ClassLoader cl = JdbcUtil.class.getClassLoader(); 23 InputStream in = cl.getResourceAsStream("dbcfg.properties"); 24 Properties props = new Properties(); 25 props.load(in); 26 driverClass = props.getProperty("driverClass"); 27 url = props.getProperty("url"); 28 user = props.getProperty("user"); 29 password = props.getProperty("password"); 30 in.close(); 31 } catch (IOException e) { 32 throw new ExceptionInInitializerError("获取数据库配置文件信息失败"); 33 } 34 try { 35 Class.forName(driverClass); 36 } catch (ClassNotFoundException e) { 37 throw new ExceptionInInitializerError("加载驱动失败"); 38 } 39 } 40 41 public static Connection getConnection(){ 42 try { 43 Connection conn = DriverManager.getConnection(url,user,password); 44 return conn; 45 } catch (Exception e) { 46 throw new RuntimeException("链接数据库的url或用户名密码错误,请检查您的配置文件"); 47 } 48 } 49 public static void release(ResultSet rs,Statement stmt,Connection conn){ 50 if(rs!=null){ 51 try { 52 rs.close(); 53 } catch (SQLException e) { 54 e.printStackTrace(); 55 } 56 rs = null; 57 } 58 if(stmt!=null){ 59 try { 60 stmt.close(); 61 } catch (SQLException e) { 62 e.printStackTrace(); 63 } 64 stmt = null; 65 } 66 if(conn!=null){ 67 try { 68 conn.close(); 69 } catch (SQLException e) { 70 e.printStackTrace(); 71 } 72 conn = null; 73 } 74 } 75 }
1 import java.sql.Connection; 2 3 public class Client { 4 5 public static void main(String[] args) { 6 7 System.out.println("开始时池中的连接有:"); 8 for(Connection conn:SimpleConnectionPool.getPool()){ 9 System.out.println(conn); 10 } 11 System.out.println("---------------"); 12 Connection conn1 = SimpleConnectionPool.getConnection(); 13 System.out.println("取走的连接是:"+conn1); 14 System.out.println("---------------"); 15 System.out.println("池中的连接有:"); 16 for(Connection conn:SimpleConnectionPool.getPool()){ 17 System.out.println(conn); 18 } 19 System.out.println("---------------"); 20 Connection conn2 = SimpleConnectionPool.getConnection(); 21 System.out.println("取走的连接是:"+conn2); 22 System.out.println("---------------"); 23 System.out.println("池中的连接有:"); 24 for(Connection conn:SimpleConnectionPool.getPool()){ 25 System.out.println(conn); 26 } 27 28 System.out.println("开始归还---------------"); 29 SimpleConnectionPool.release(conn1); 30 System.out.println("池中的连接有:"); 31 for(Connection conn:SimpleConnectionPool.getPool()){ 32 System.out.println(conn); 33 } 34 System.out.println("开始归还---------------"); 35 SimpleConnectionPool.release(conn2); 36 System.out.println("池中的连接有:"); 37 for(Connection conn:SimpleConnectionPool.getPool()){ 38 System.out.println(conn); 39 } 40 } 41 42 }
dbfg.properties:
1 #driver config for mysql 2 driverClass=com.mysql.jdbc.Driver 3 url=jdbc:mysql://localhost:3306/day16 4 user=root 5 password=sorry
编写标准的数据源
1.Sun定义了一个标准:javax.sql.DataSource接口(数据源)
2.
1 //一班标准的数据源:一般都带有连接池 2 public class MyDataSource1 implements DataSource { 3 private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>()); 4 static{ 5 for(int i=0;i<10;i++){ 6 //com.mysql.jdbc.Connection数据库的那个Connection实现类型 7 Connection conn = JdbcUtil.getConnection(); 8 pool.add(conn); 9 } 10 } 11 12 public Connection getConnection() throws SQLException { 13 if(pool.size()>0){ 14 Connection conn = pool.remove(0);//com.mysql.jdbc.Connection 15 MyConnection1 myconn = new MyConnection1(conn, pool); 16 return myconn; 17 }else{ 18 throw new RuntimeException("服务器真忙"); 19 } 20 }
专题编程难点
背景:义在池中获取连接后不需要使用了不能用close()方法进行处理,导致pool中连接对象就close了,数量就会减小
1.更改已知的某个或者某些方法(不能修改原有的代码,应该拓展)解决方案如下:
1.继承:此处不行
2.利用包装设计模式(装饰设计模式)
3.利用动态代理
2.装饰设计模式:I/O
口诀:a.编写一个类实现与被包装类(com.mysql.jdbc.Connection)相同的接口
b.定义一个变量,引用被包装类的实例
c.定义构造方法,传入被包装类实例的引用
d.对于要改变的方法,编写自己的代码即可
e.对于不需要改变的方法,调用原有的对应方法
配上图解(防蒙):
Jdbcutil:
1 import java.io.IOException; 2 import java.io.InputStream; 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.sql.Statement; 8 import java.util.Properties; 9 10 public class JdbcUtil { 11 12 private static String driverClass; 13 private static String url; 14 private static String user; 15 private static String password; 16 17 18 static{ 19 try { 20 ClassLoader cl = JdbcUtil.class.getClassLoader(); 21 InputStream in = cl.getResourceAsStream("dbcfg.properties"); 22 Properties props = new Properties(); 23 props.load(in); 24 driverClass = props.getProperty("driverClass"); 25 url = props.getProperty("url"); 26 user = props.getProperty("user"); 27 password = props.getProperty("password"); 28 in.close(); 29 } catch (IOException e) { 30 throw new ExceptionInInitializerError("获取数据库配置文件信息失败"); 31 } 32 try { 33 Class.forName(driverClass); 34 } catch (ClassNotFoundException e) { 35 throw new ExceptionInInitializerError("加载驱动失败"); 36 } 37 } 38 39 public static Connection getConnection(){ 40 try { 41 Connection conn = DriverManager.getConnection(url,user,password); 42 return conn; 43 } catch (Exception e) { 44 throw new RuntimeException("链接数据库的url或用户名密码错误,请检查您的配置文件"); 45 } 46 } 47 public static void release(ResultSet rs,Statement stmt,Connection conn){ 48 if(rs!=null){ 49 try { 50 rs.close(); 51 } catch (SQLException e) { 52 e.printStackTrace(); 53 } 54 rs = null; 55 } 56 if(stmt!=null){ 57 try { 58 stmt.close(); 59 } catch (SQLException e) { 60 e.printStackTrace(); 61 } 62 stmt = null; 63 } 64 if(conn!=null){ 65 try { 66 conn.close(); 67 } catch (SQLException e) { 68 e.printStackTrace(); 69 } 70 conn = null; 71 } 72 } 73 }
MyConnection:
1 import java.sql.Array; 2 import java.sql.Blob; 3 import java.sql.CallableStatement; 4 import java.sql.Clob; 5 import java.sql.Connection; 6 import java.sql.DatabaseMetaData; 7 import java.sql.NClob; 8 import java.sql.PreparedStatement; 9 import java.sql.SQLClientInfoException; 10 import java.sql.SQLException; 11 import java.sql.SQLWarning; 12 import java.sql.SQLXML; 13 import java.sql.Savepoint; 14 import java.sql.Statement; 15 import java.sql.Struct; 16 import java.util.List; 17 import java.util.Map; 18 import java.util.Properties; 19 20 //a、编写一个类实现与被包装类(com.mysql.jdbc.Connection)相同的接口 21 //b、定义一个变量,引用被包装类的实例 22 //c、定义构造方法,传入被包装类实例的引用 23 //d、对于要改变的方法,编写自己的代码即可 24 //e、对于不需要改变的方法,调用原有对象的对应方法 25 public class MyConnection1 implements Connection{//a、编写一个类实现与被包装类(com.mysql.jdbc.Connection)相同的接口 26 27 private List<Connection> pool; 28 29 private Connection oldConnection;//b、定义一个变量,引用被包装类的实例 30 public MyConnection1(Connection oldConnection,List<Connection> pool){//c、定义构造方法,传入被包装类实例的引用 31 this.oldConnection = oldConnection; 32 this.pool = pool;//注入 33 } 34 35 //d、对于要改变的方法,编写自己的代码即可 36 public void close() throws SQLException { 37 pool.add(oldConnection); 38 } 39 //e、对于不需要改变的方法,调用原有对象的对应方法 40 public <T> T unwrap(Class<T> iface) throws SQLException { 41 return oldConnection.unwrap(iface); 42 } 43 @Override 44 public boolean isWrapperFor(Class<?> iface) throws SQLException { 45 return oldConnection.isWrapperFor(iface); 46 } 47 @Override 48 public Statement createStatement() throws SQLException { 49 return oldConnection.createStatement(); 50 } 51 //后面省略不写 52 @Override 53 public PreparedStatement prepareStatement(String sql) throws SQLException { 54 // TODO Auto-generated method stub 55 return null; 56 } 57 @Override 58 public CallableStatement prepareCall(String sql) throws SQLException { 59 // TODO Auto-generated method stub 60 return null; 61 } 62 @Override 63 public String nativeSQL(String sql) throws SQLException { 64 // TODO Auto-generated method stub 65 return null; 66 } 67 @Override 68 public void setAutoCommit(boolean autoCommit) throws SQLException { 69 // TODO Auto-generated method stub 70 71 } 72 @Override 73 public boolean getAutoCommit() throws SQLException { 74 // TODO Auto-generated method stub 75 return false; 76 } 77 @Override 78 public void commit() throws SQLException { 79 // TODO Auto-generated method stub 80 81 } 82 @Override 83 public void rollback() throws SQLException { 84 // TODO Auto-generated method stub 85 86 } 87 88 @Override 89 public boolean isClosed() throws SQLException { 90 // TODO Auto-generated method stub 91 return false; 92 } 93 @Override 94 public DatabaseMetaData getMetaData() throws SQLException { 95 // TODO Auto-generated method stub 96 return null; 97 } 98 @Override 99 public void setReadOnly(boolean readOnly) throws SQLException { 100 // TODO Auto-generated method stub 101 102 } 103 @Override 104 public boolean isReadOnly() throws SQLException { 105 // TODO Auto-generated method stub 106 return false; 107 } 108 @Override 109 public void setCatalog(String catalog) throws SQLException { 110 // TODO Auto-generated method stub 111 112 } 113 @Override 114 public String getCatalog() throws SQLException { 115 // TODO Auto-generated method stub 116 return null; 117 } 118 @Override 119 public void setTransactionIsolation(int level) throws SQLException { 120 // TODO Auto-generated method stub 121 122 } 123 @Override 124 public int getTransactionIsolation() throws SQLException { 125 // TODO Auto-generated method stub 126 return 0; 127 } 128 @Override 129 public SQLWarning getWarnings() throws SQLException { 130 // TODO Auto-generated method stub 131 return null; 132 } 133 @Override 134 public void clearWarnings() throws SQLException { 135 // TODO Auto-generated method stub 136 137 } 138 @Override 139 public Statement createStatement(int resultSetType, int resultSetConcurrency) 140 throws SQLException { 141 // TODO Auto-generated method stub 142 return null; 143 } 144 @Override 145 public PreparedStatement prepareStatement(String sql, int resultSetType, 146 int resultSetConcurrency) throws SQLException { 147 // TODO Auto-generated method stub 148 return null; 149 } 150 @Override 151 public CallableStatement prepareCall(String sql, int resultSetType, 152 int resultSetConcurrency) throws SQLException { 153 // TODO Auto-generated method stub 154 return null; 155 } 156 @Override 157 public Map<String, Class<?>> getTypeMap() throws SQLException { 158 // TODO Auto-generated method stub 159 return null; 160 } 161 @Override 162 public void setTypeMap(Map<String, Class<?>> map) throws SQLException { 163 // TODO Auto-generated method stub 164 165 } 166 @Override 167 public void setHoldability(int holdability) throws SQLException { 168 // TODO Auto-generated method stub 169 170 } 171 @Override 172 public int getHoldability() throws SQLException { 173 // TODO Auto-generated method stub 174 return 0; 175 } 176 @Override 177 public Savepoint setSavepoint() throws SQLException { 178 // TODO Auto-generated method stub 179 return null; 180 } 181 @Override 182 public Savepoint setSavepoint(String name) throws SQLException { 183 // TODO Auto-generated method stub 184 return null; 185 } 186 @Override 187 public void rollback(Savepoint savepoint) throws SQLException { 188 // TODO Auto-generated method stub 189 190 } 191 @Override 192 public void releaseSavepoint(Savepoint savepoint) throws SQLException { 193 // TODO Auto-generated method stub 194 195 } 196 @Override 197 public Statement createStatement(int resultSetType, 198 int resultSetConcurrency, int resultSetHoldability) 199 throws SQLException { 200 // TODO Auto-generated method stub 201 return null; 202 } 203 @Override 204 public PreparedStatement prepareStatement(String sql, int resultSetType, 205 int resultSetConcurrency, int resultSetHoldability) 206 throws SQLException { 207 // TODO Auto-generated method stub 208 return null; 209 } 210 @Override 211 public CallableStatement prepareCall(String sql, int resultSetType, 212 int resultSetConcurrency, int resultSetHoldability) 213 throws SQLException { 214 // TODO Auto-generated method stub 215 return null; 216 } 217 @Override 218 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) 219 throws SQLException { 220 // TODO Auto-generated method stub 221 return null; 222 } 223 @Override 224 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) 225 throws SQLException { 226 // TODO Auto-generated method stub 227 return null; 228 } 229 @Override 230 public PreparedStatement prepareStatement(String sql, String[] columnNames) 231 throws SQLException { 232 // TODO Auto-generated method stub 233 return null; 234 } 235 @Override 236 public Clob createClob() throws SQLException { 237 // TODO Auto-generated method stub 238 return null; 239 } 240 @Override 241 public Blob createBlob() throws SQLException { 242 // TODO Auto-generated method stub 243 return null; 244 } 245 @Override 246 public NClob createNClob() throws SQLException { 247 // TODO Auto-generated method stub 248 return null; 249 } 250 @Override 251 public SQLXML createSQLXML() throws SQLException { 252 // TODO Auto-generated method stub 253 return null; 254 } 255 @Override 256 public boolean isValid(int timeout) throws SQLException { 257 // TODO Auto-generated method stub 258 return false; 259 } 260 @Override 261 public void setClientInfo(String name, String value) 262 throws SQLClientInfoException { 263 // TODO Auto-generated method stub 264 265 } 266 @Override 267 public void setClientInfo(Properties properties) 268 throws SQLClientInfoException { 269 // TODO Auto-generated method stub 270 271 } 272 @Override 273 public String getClientInfo(String name) throws SQLException { 274 // TODO Auto-generated method stub 275 return null; 276 } 277 @Override 278 public Properties getClientInfo() throws SQLException { 279 // TODO Auto-generated method stub 280 return null; 281 } 282 @Override 283 public Array createArrayOf(String typeName, Object[] elements) 284 throws SQLException { 285 // TODO Auto-generated method stub 286 return null; 287 } 288 @Override 289 public Struct createStruct(String typeName, Object[] attributes) 290 throws SQLException { 291 // TODO Auto-generated method stub 292 return null; 293 } 294 }
client:
1 package com.itheima.ds; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.SQLException; 6 import java.sql.Statement; 7 8 public class Client { 9 10 public static void main(String[] args) { 11 MyDataSource2 ds = new MyDataSource2(); 12 Connection conn = null; 13 Statement stmt = null; 14 try{ 15 conn = ds.getConnection();//MyConnection1从池中获取一个连接 16 stmt = conn.createStatement();//调用的是MyConnection1中的createStatement(),调用驱动最原始的对应方法 17 //..... 18 }catch(Exception e){ 19 e.printStackTrace(); 20 }finally{ 21 if(stmt!=null){ 22 try { 23 stmt.close(); 24 } catch (SQLException e) { 25 e.printStackTrace(); 26 } 27 } 28 if(conn!=null){ 29 try { 30 conn.close();//关闭连接(com.mysql.jdbc.Connection) 31 //不要关闭,还回池中(更改已知类的某个方法的默认行为) 32 } catch (SQLException e) { 33 e.printStackTrace(); 34 } 35 } 36 } 37 } 38 39 }
MyDataSource:
1 package com.itheima.ds; 2 3 import java.io.PrintWriter; 4 import java.sql.Connection; 5 import java.sql.SQLException; 6 import java.util.ArrayList; 7 import java.util.Collections; 8 import java.util.List; 9 10 import javax.sql.DataSource; 11 12 import com.itheima.util.JdbcUtil; 13 //一把标准的数据源:一般都带有连接池 14 public class MyDataSource1 implements DataSource { 15 private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>()); 16 static{ 17 for(int i=0;i<10;i++){ 18 //com.mysql.jdbc.Connection数据库的那个Connection实现类型 19 Connection conn = JdbcUtil.getConnection(); 20 pool.add(conn); 21 } 22 } 23 24 public Connection getConnection() throws SQLException { 25 if(pool.size()>0){ 26 Connection conn = pool.remove(0);//com.mysql.jdbc.Connection 27 MyConnection1 myconn = new MyConnection1(conn, pool); 28 return myconn; 29 }else{ 30 throw new RuntimeException("服务器真忙"); 31 } 32 } 33 34 35 @Override 36 public PrintWriter getLogWriter() throws SQLException { 37 // TODO Auto-generated method stub 38 return null; 39 } 40 41 @Override 42 public void setLogWriter(PrintWriter out) throws SQLException { 43 // TODO Auto-generated method stub 44 45 } 46 47 @Override 48 public void setLoginTimeout(int seconds) throws SQLException { 49 // TODO Auto-generated method stub 50 51 } 52 53 @Override 54 public int getLoginTimeout() throws SQLException { 55 // TODO Auto-generated method stub 56 return 0; 57 } 58 59 @Override 60 public <T> T unwrap(Class<T> iface) throws SQLException { 61 // TODO Auto-generated method stub 62 return null; 63 } 64 65 @Override 66 public boolean isWrapperFor(Class<?> iface) throws SQLException { 67 // TODO Auto-generated method stub 68 return false; 69 } 70 71 72 @Override 73 public Connection getConnection(String username, String password) 74 throws SQLException { 75 // TODO Auto-generated method stub 76 return null; 77 } 78 79 }
默认适配器
背景:义在池中获取
1.适配器类:
//适配器,还是一个包装类
//a、编写一个类实现与被包装类(com.mysql.jdbc.Connection)相同的接口
//b、定义一个变量,引用被包装类的实例
//c、定义构造方法,传入被包装类实例的引用
//d、对于不需要改变的方法,调用原有对象的对应方法
1 import java.sql.Array; 2 import java.sql.Blob; 3 import java.sql.CallableStatement; 4 import java.sql.Clob; 5 import java.sql.Connection; 6 import java.sql.DatabaseMetaData; 7 import java.sql.NClob; 8 import java.sql.PreparedStatement; 9 import java.sql.SQLClientInfoException; 10 import java.sql.SQLException; 11 import java.sql.SQLWarning; 12 import java.sql.SQLXML; 13 import java.sql.Savepoint; 14 import java.sql.Statement; 15 import java.sql.Struct; 16 import java.util.Map; 17 import java.util.Properties; 18 19 //适配器,还是一个包装类 20 //a、编写一个类实现与被包装类(com.mysql.jdbc.Connection)相同的接口 21 //b、定义一个变量,引用被包装类的实例 22 //c、定义构造方法,传入被包装类实例的引用 23 //d、对于不需要改变的方法,调用原有对象的对应方法 24 public class ConnectionAdapter implements Connection{ 25 private Connection oldConnection; 26 public ConnectionAdapter(Connection oldConnection){ 27 this.oldConnection = oldConnection; 28 } 29 public <T> T unwrap(Class<T> iface) throws SQLException { 30 return oldConnection.unwrap(iface); 31 } 32 @Override 33 public boolean isWrapperFor(Class<?> iface) throws SQLException { 34 return oldConnection.isWrapperFor(iface); 35 } 36 //省略 37 @Override 38 public Statement createStatement() throws SQLException { 39 // TODO Auto-generated method stub 40 return null; 41 } 42 @Override 43 public PreparedStatement prepareStatement(String sql) throws SQLException { 44 // TODO Auto-generated method stub 45 return null; 46 } 47 @Override 48 public CallableStatement prepareCall(String sql) throws SQLException { 49 // TODO Auto-generated method stub 50 return null; 51 } 52 @Override 53 public String nativeSQL(String sql) throws SQLException { 54 // TODO Auto-generated method stub 55 return null; 56 } 57 @Override 58 public void setAutoCommit(boolean autoCommit) throws SQLException { 59 // TODO Auto-generated method stub 60 61 } 62 @Override 63 public boolean getAutoCommit() throws SQLException { 64 // TODO Auto-generated method stub 65 return false; 66 } 67 @Override 68 public void commit() throws SQLException { 69 // TODO Auto-generated method stub 70 71 } 72 @Override 73 public void rollback() throws SQLException { 74 // TODO Auto-generated method stub 75 76 } 77 @Override 78 public void close() throws SQLException { 79 // TODO Auto-generated method stub 80 81 } 82 @Override 83 public boolean isClosed() throws SQLException { 84 // TODO Auto-generated method stub 85 return false; 86 } 87 @Override 88 public DatabaseMetaData getMetaData() throws SQLException { 89 // TODO Auto-generated method stub 90 return null; 91 } 92 @Override 93 public void setReadOnly(boolean readOnly) throws SQLException { 94 // TODO Auto-generated method stub 95 96 } 97 @Override 98 public boolean isReadOnly() throws SQLException { 99 // TODO Auto-generated method stub 100 return false; 101 } 102 @Override 103 public void setCatalog(String catalog) throws SQLException { 104 // TODO Auto-generated method stub 105 106 } 107 @Override 108 public String getCatalog() throws SQLException { 109 // TODO Auto-generated method stub 110 return null; 111 } 112 @Override 113 public void setTransactionIsolation(int level) throws SQLException { 114 // TODO Auto-generated method stub 115 116 } 117 @Override 118 public int getTransactionIsolation() throws SQLException { 119 // TODO Auto-generated method stub 120 return 0; 121 } 122 @Override 123 public SQLWarning getWarnings() throws SQLException { 124 // TODO Auto-generated method stub 125 return null; 126 } 127 @Override 128 public void clearWarnings() throws SQLException { 129 // TODO Auto-generated method stub 130 131 } 132 @Override 133 public Statement createStatement(int resultSetType, int resultSetConcurrency) 134 throws SQLException { 135 // TODO Auto-generated method stub 136 return null; 137 } 138 @Override 139 public PreparedStatement prepareStatement(String sql, int resultSetType, 140 int resultSetConcurrency) throws SQLException { 141 // TODO Auto-generated method stub 142 return null; 143 } 144 @Override 145 public CallableStatement prepareCall(String sql, int resultSetType, 146 int resultSetConcurrency) throws SQLException { 147 // TODO Auto-generated method stub 148 return null; 149 } 150 @Override 151 public Map<String, Class<?>> getTypeMap() throws SQLException { 152 // TODO Auto-generated method stub 153 return null; 154 } 155 @Override 156 public void setTypeMap(Map<String, Class<?>> map) throws SQLException { 157 // TODO Auto-generated method stub 158 159 } 160 @Override 161 public void setHoldability(int holdability) throws SQLException { 162 // TODO Auto-generated method stub 163 164 } 165 @Override 166 public int getHoldability() throws SQLException { 167 // TODO Auto-generated method stub 168 return 0; 169 } 170 @Override 171 public Savepoint setSavepoint() throws SQLException { 172 // TODO Auto-generated method stub 173 return null; 174 } 175 @Override 176 public Savepoint setSavepoint(String name) throws SQLException { 177 // TODO Auto-generated method stub 178 return null; 179 } 180 @Override 181 public void rollback(Savepoint savepoint) throws SQLException { 182 // TODO Auto-generated method stub 183 184 } 185 @Override 186 public void releaseSavepoint(Savepoint savepoint) throws SQLException { 187 // TODO Auto-generated method stub 188 189 } 190 @Override 191 public Statement createStatement(int resultSetType, 192 int resultSetConcurrency, int resultSetHoldability) 193 throws SQLException { 194 // TODO Auto-generated method stub 195 return null; 196 } 197 @Override 198 public PreparedStatement prepareStatement(String sql, int resultSetType, 199 int resultSetConcurrency, int resultSetHoldability) 200 throws SQLException { 201 // TODO Auto-generated method stub 202 return null; 203 } 204 @Override 205 public CallableStatement prepareCall(String sql, int resultSetType, 206 int resultSetConcurrency, int resultSetHoldability) 207 throws SQLException { 208 // TODO Auto-generated method stub 209 return null; 210 } 211 @Override 212 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) 213 throws SQLException { 214 // TODO Auto-generated method stub 215 return null; 216 } 217 @Override 218 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) 219 throws SQLException { 220 // TODO Auto-generated method stub 221 return null; 222 } 223 @Override 224 public PreparedStatement prepareStatement(String sql, String[] columnNames) 225 throws SQLException { 226 // TODO Auto-generated method stub 227 return null; 228 } 229 @Override 230 public Clob createClob() throws SQLException { 231 // TODO Auto-generated method stub 232 return null; 233 } 234 @Override 235 public Blob createBlob() throws SQLException { 236 // TODO Auto-generated method stub 237 return null; 238 } 239 @Override 240 public NClob createNClob() throws SQLException { 241 // TODO Auto-generated method stub 242 return null; 243 } 244 @Override 245 public SQLXML createSQLXML() throws SQLException { 246 // TODO Auto-generated method stub 247 return null; 248 } 249 @Override 250 public boolean isValid(int timeout) throws SQLException { 251 // TODO Auto-generated method stub 252 return false; 253 } 254 @Override 255 public void setClientInfo(String name, String value) 256 throws SQLClientInfoException { 257 // TODO Auto-generated method stub 258 259 } 260 @Override 261 public void setClientInfo(Properties properties) 262 throws SQLClientInfoException { 263 // TODO Auto-generated method stub 264 265 } 266 @Override 267 public String getClientInfo(String name) throws SQLException { 268 // TODO Auto-generated method stub 269 return null; 270 } 271 @Override 272 public Properties getClientInfo() throws SQLException { 273 // TODO Auto-generated method stub 274 return null; 275 } 276 @Override 277 public Array createArrayOf(String typeName, Object[] elements) 278 throws SQLException { 279 // TODO Auto-generated method stub 280 return null; 281 } 282 @Override 283 public Struct createStruct(String typeName, Object[] attributes) 284 throws SQLException { 285 // TODO Auto-generated method stub 286 return null; 287 } 288 }
2.继承包装类:
//a、编写一个类继承已经实现了被包装类(com.mysql.jdbc.Connection)相同的接口的类
//b、定义一个变量,引用被包装类的实例
//c、定义构造方法,传入被包装类实例的引用
//d、对于要改变的方法,覆盖即可
1 import java.sql.Connection; 2 import java.sql.SQLException; 3 import java.util.List; 4 5 //a、编写一个类继承已经实现了被包装类(com.mysql.jdbc.Connection)相同的接口的类 6 //b、定义一个变量,引用被包装类的实例 7 //c、定义构造方法,传入被包装类实例的引用 8 //d、对于要改变的方法,覆盖即可 9 public class MyConnection2 extends ConnectionAdapter{ 10 private Connection oldConnection; 11 private List<Connection> pool; 12 public MyConnection2(Connection oldConnection,List<Connection> pool){ 13 super(oldConnection); 14 this.oldConnection = oldConnection; 15 this.pool = pool; 16 } 17 public void close() throws SQLException { 18 pool.add(oldConnection); 19 } 20 21 }
动态代理:
示例代码:
1.接口:
1 package com.itheima.proxy1; 2 3 public interface Human { 4 void sing(float money); 5 void dance(float money); 6 void eat(); 7 }
2. 实现接口类:
1 public class SpringBrother implements Human { 2 3 public void sing(float money) { 4 System.out.println("拿到钱:"+money+"开唱"); 5 } 6 7 public void dance(float money) { 8 System.out.println("拿到钱:"+money+"开跳"); 9 } 10 11 public void eat() { 12 System.out.println("狼吞虎咽的吃"); 13 } 14 15 }
3.代理类:
1 package com.itheima.proxy1; 2 //静态代理:代理类写好了 3 public class ProxyMan implements Human{ 4 private Human oldHuman; 5 public ProxyMan(Human oldHuman){ 6 this.oldHuman = oldHuman; 7 } 8 public void sing(float money) { 9 if(money<10000) 10 throw new RuntimeException("不干"); 11 oldHuman.sing(money/2); 12 } 13 14 public void dance(float money) { 15 if(money<20000) 16 throw new RuntimeException("不干"); 17 oldHuman.dance(money/2); 18 } 19 public void eat() { 20 oldHuman.eat(); 21 } 22 23 }
4.动态代理及测试:
1 import java.lang.reflect.InvocationHandler; 2 import java.lang.reflect.Method; 3 import java.lang.reflect.Proxy; 4 //如果被代理对象没有实现任何接口,Proxy代理不能用。基于接口的动态代理 5 public class Boss { 6 7 public static void main(String[] args) { 8 final Human h = new SpringBrother();//被代理对象 9 // Human proxyMan = new ProxyMan(h);//静态代理 10 //动态代理 11 /* 12 * public static Object newProxyInstance(ClassLoader loader, 13 Class<?>[] interfaces, 14 InvocationHandler h) 15 返回值:代理对象的引用 16 参数: 17 loader:代理对象用的类加载器。固定写法:和被代理对象一致 18 interfaces:代理对象实现的接口。固定写法:代理对象实现什么接口它就实现什么接口(保持代理对象和被代理对象有相同的行为) 19 h:如何代理,怎么代理,代理什么?策略设计模式(InvocationHandler是一个接口) 20 */ 21 Human proxyMan = (Human)Proxy.newProxyInstance(h.getClass().getClassLoader(), 22 h.getClass().getInterfaces(), new InvocationHandler() { 23 //如何代理啊:具体策略 24 //调用代理对象的任何方法,都会经过该方法 25 /* 26 * 返回值:当前方法的返回值 27 * proxy:代理对象的引用 28 * method:当前调用的代理的哪个方法 29 * args:当前方法需要的参数 30 */ 31 public Object invoke(Object proxy, Method method, Object[] args) 32 throws Throwable { 33 if("sing".equals(method.getName())){ 34 float money = (Float)args[0]; 35 if(money>10000){ 36 return method.invoke(h, money/2); 37 } 38 }else if("dance".equals(method.getName())){ 39 float money = (Float)args[0]; 40 if(money>20000){ 41 return method.invoke(h, money/2); 42 } 43 }else{ 44 return method.invoke(h, args); 45 } 46 return null; 47 } 48 }); 49 proxyMan.sing(100000); 50 proxyMan.dance(200000); 51 proxyMan.eat(); 52 } 53 54 }
2.基于动态代理更改驱动close()方法:
1 import java.io.PrintWriter; 2 import java.lang.reflect.InvocationHandler; 3 import java.lang.reflect.Method; 4 import java.lang.reflect.Proxy; 5 import java.sql.Connection; 6 import java.sql.SQLException; 7 import java.util.ArrayList; 8 import java.util.Collections; 9 import java.util.List; 10 11 import javax.sql.DataSource; 12 13 import com.itheima.util.JdbcUtil; 14 //一把标准的数据源:一般都带有连接池。使用动态代理来做 15 public class MyDataSource2 implements DataSource { 16 private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>()); 17 static{ 18 for(int i=0;i<10;i++){ 19 //com.mysql.jdbc.Connection数据库的那个Connection实现类型 20 Connection conn = JdbcUtil.getConnection(); 21 pool.add(conn); 22 } 23 } 24 25 public Connection getConnection() throws SQLException { 26 if(pool.size()>0){ 27 final Connection conn = pool.remove(0);//com.mysql.jdbc.Connection 28 return (Connection)Proxy.newProxyInstance(conn.getClass().getClassLoader(), 29 conn.getClass().getInterfaces(), 30 new InvocationHandler() { 31 public Object invoke(Object proxy, Method method, Object[] args) 32 throws Throwable { 33 if("close".equals(method.getName())){ 34 return pool.add(conn); 35 }else{ 36 return method.invoke(conn, args); 37 } 38 } 39 }); 40 }else{ 41 throw new RuntimeException("服务器真忙"); 42 } 43 } 44 45 46 @Override 47 public PrintWriter getLogWriter() throws SQLException { 48 // TODO Auto-generated method stub 49 return null; 50 } 51 52 @Override 53 public void setLogWriter(PrintWriter out) throws SQLException { 54 // TODO Auto-generated method stub 55 56 } 57 58 @Override 59 public void setLoginTimeout(int seconds) throws SQLException { 60 // TODO Auto-generated method stub 61 62 } 63 64 @Override 65 public int getLoginTimeout() throws SQLException { 66 // TODO Auto-generated method stub 67 return 0; 68 } 69 70 @Override 71 public <T> T unwrap(Class<T> iface) throws SQLException { 72 // TODO Auto-generated method stub 73 return null; 74 } 75 76 @Override 77 public boolean isWrapperFor(Class<?> iface) throws SQLException { 78 // TODO Auto-generated method stub 79 return false; 80 } 81 82 83 @Override 84 public Connection getConnection(String username, String password) 85 throws SQLException { 86 // TODO Auto-generated method stub 87 return null; 88 } 89 90 }
3.CGLIB生成代理 对象:
(代理类是被代理的子类)
被代理类要求:
a.必须是public
b.必须不是final
1.导入架包:cglib-nodep-2.1_3.jar
2:被代理类:
1 //没有实现任何接口。domain包中的普通的JavaBean,有时并没有实现任何接口,需要他的代理类怎么办? 2 //借助第三方的开发:CGLIB 3 public class SpringBrother{ 4 5 public void sing(float money) { 6 System.out.println("拿到钱:"+money+"开唱"); 7 } 8 9 public void dance(float money) { 10 System.out.println("拿到钱:"+money+"开跳"); 11 } 12 13 public void eat() { 14 System.out.println("狼吞虎咽的吃"); 15 } 16 17 }
3.代理:
1 import java.lang.reflect.Method; 2 3 import net.sf.cglib.proxy.Enhancer; 4 import net.sf.cglib.proxy.InvocationHandler; 5 //如果被代理对象没有实现任何接口,Proxy代理不能用。基于接口的动态代理 6 //CGLIB:基于子类的动态代理 7 public class Boss { 8 9 public static void main(String[] args) { 10 final SpringBrother h = new SpringBrother();//被代理对象 11 /* 12 * Enhancer.create(type, callback) 13 * type:代理类的父类型 14 * callback:如何代理 15 */ 16 SpringBrother proxyMan = (SpringBrother)Enhancer.create(SpringBrother.class, new InvocationHandler(){ 17 18 public Object invoke(Object proxy, Method method, Object[] args) 19 throws Throwable { 20 if("sing".equals(method.getName())){ 21 float money = (Float)args[0]; 22 if(money>10000){ 23 return method.invoke(h, money/2); 24 } 25 }else if("dance".equals(method.getName())){ 26 float money = (Float)args[0]; 27 if(money>20000){ 28 return method.invoke(h, money/2); 29 } 30 }else{ 31 return method.invoke(h, args); 32 } 33 return null; 34 } 35 36 }); 37 proxyMan.sing(100000); 38 proxyMan.dance(200000); 39 proxyMan.eat(); 40 } 41 42 }
AOP面向切向思想:
1 之前写了一篇关于IOC的博客——《Spring容器IOC解析及简单实现》,今天再来聊聊AOP。大家都知道Spring的两大特性是IOC和AOP。 2 IOC负责将对象动态的注入到容器,从而达到一种需要谁就注入谁,什么时候需要就什么时候注入的效果,可谓是招之则来,挥之则去。想想都觉得爽,如果现实生活中也有这本事那就爽歪歪了,至于有多爽,各位自己脑补吧;而AOP呢,它实现的就是容器的另一大好处了,就是可以让容器中的对象都享有容器中的公共服务。那么容器是怎么做到的呢?它怎么就能让在它里面的对象自动拥有它提供的公共性服务呢?答案就是我们今天要讨论的内容——动态代理。 3 动态代理其实并不是什么新鲜的东西,学过设计模式的人都应该知道代理模式,代理模式是一种静态代理,而动态代理就是利用反射和动态编译将代理模式变成动态的。原理跟动态注入一样,代理模式在编译的时候就已经确定代理类将要代理谁,而动态代理在运行的时候才知道自己要代理谁。 4 Spring的动态代理有两种:一是JDK的动态代理;另一个是cglib动态代理(通过修改字节码来实现代理)。今天咱们主要讨论JDK动态代理的方式。JDK的代理方式主要就是通过反射跟动态编译来实现的,下面咱们就通过代码来看看它具体是怎么实现的。 5 假设我们要对下面这个用户管理进行代理: 6 //用户管理接口 7 package com.tgb.proxy; 8 9 public interface UserMgr { 10 void addUser(); 11 void delUser(); 12 } 13 14 //用户管理的实现 15 package com.tgb.proxy; 16 17 public class UserMgrImpl implements UserMgr { 18 19 @Override 20 public void addUser() { 21 System.out.println("添加用户....."); 22 } 23 24 @Override 25 public void delUser() { 26 System.out.println("删除用户....."); 27 } 28 29 } 30 按照代理模式的实现方式,肯定是用一个代理类,让它也实现UserMgr接口,然后在其内部声明一个UserMgrImpl,然后分别调用addUser和delUser方法,并在调用前后加上我们需要的其他操作。但是这样很显然都是写死的,我们怎么做到动态呢?别急,接着看。 我们知道,要实现代理,那么我们的代理类跟被代理类都要实现同一接口,但是动态代理的话我们根本不知道我们将要代理谁,也就不知道我们要实现哪个接口,那么要怎么办呢?我们只有知道要代理谁以后,才能给出相应的代理类,那么我们何不等知道要代理谁以后再去生成一个代理类呢?想到这里,我们好像找到了解决的办法,就是动态生成代理类! 31 这时候我们亲爱的反射又有了用武之地,我们可以写一个方法来接收被代理类,这样我们就可以通过反射知道它的一切信息——包括它的类型、它的方法等等(如果你不知道怎么得到,请先去看看我写的反射的博客《反射一》《反射二》)。 32 JDK动态代理的两个核心分别是InvocationHandler和Proxy,下面我们就用简单的代码来模拟一下它们是怎么实现的: 33 InvocationHandler接口: 34 package com.tgb.proxy; 35 36 import java.lang.reflect.Method; 37 38 public interface InvocationHandler { 39 public void invoke(Object o, Method m); 40 } 41 实现动态代理的关键部分,通过Proxy动态生成我们具体的代理类: 42 package com.tgb.proxy; 43 44 import java.io.File; 45 import java.io.FileWriter; 46 import java.lang.reflect.Constructor; 47 import java.lang.reflect.Method; 48 import java.net.URL; 49 import java.net.URLClassLoader; 50 import javax.tools.JavaCompiler; 51 import javax.tools.StandardJavaFileManager; 52 import javax.tools.ToolProvider; 53 import javax.tools.JavaCompiler.CompilationTask; 54 55 public class Proxy { 56 /** 57 * 58 * @param infce 被代理类的接口 59 * @param h 代理类 60 * @return 61 * @throws Exception 62 */ 63 public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception { 64 String methodStr = ""; 65 String rt = "\r\n"; 66 67 //利用反射得到infce的所有方法,并重新组装 68 Method[] methods = infce.getMethods(); 69 for(Method m : methods) { 70 methodStr += " @Override" + rt + 71 " public "+m.getReturnType()+" " + m.getName() + "() {" + rt + 72 " try {" + rt + 73 " Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt + 74 " h.invoke(this, md);" + rt + 75 " }catch(Exception e) {e.printStackTrace();}" + rt + 76 " }" + rt ; 77 } 78 79 //生成Java源文件 80 String srcCode = 81 "package com.tgb.proxy;" + rt + 82 "import java.lang.reflect.Method;" + rt + 83 "public class $Proxy1 implements " + infce.getName() + "{" + rt + 84 " public $Proxy1(InvocationHandler h) {" + rt + 85 " this.h = h;" + rt + 86 " }" + rt + 87 " com.tgb.proxy.InvocationHandler h;" + rt + 88 methodStr + rt + 89 "}"; 90 String fileName = 91 "d:/src/com/tgb/proxy/$Proxy1.java"; 92 File f = new File(fileName); 93 FileWriter fw = new FileWriter(f); 94 fw.write(srcCode); 95 fw.flush(); 96 fw.close(); 97 98 //将Java文件编译成class文件 99 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 100 StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); 101 Iterable units = fileMgr.getJavaFileObjects(fileName); 102 CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); 103 t.call(); 104 fileMgr.close(); 105 106 //加载到内存,并实例化 107 URL[] urls = new URL[] {new URL("file:/" + "d:/src/")}; 108 URLClassLoader ul = new URLClassLoader(urls); 109 Class c = ul.loadClass("com.tgb.proxy.$Proxy1"); 110 111 Constructor ctr = c.getConstructor(InvocationHandler.class); 112 Object m = ctr.newInstance(h); 113 114 return m; 115 } 116 117 } 118 这个类的主要功能就是,根据被代理对象的信息,动态组装一个代理类,生成$Proxy1.java文件,然后将其编译成$Proxy1.class。这样我们就可以在运行的时候,根据我们具体的被代理对象生成我们想要的代理类了。这样一来,我们就不需要提前知道我们要代理谁。也就是说,你想代理谁,想要什么样的代理,我们就给你生成一个什么样的代理类。 119 然后,在客户端我们就可以随意的进行代理了。 120 package com.tgb.proxy; 121 122 public class Client { 123 public static void main(String[] args) throws Exception { 124 UserMgr mgr = new UserMgrImpl(); 125 126 //为用户管理添加事务处理 127 InvocationHandler h = new TransactionHandler(mgr); 128 UserMgr u = (UserMgr)Proxy.newProxyInstance(UserMgr.class,h); 129 130 //为用户管理添加显示方法执行时间的功能 131 TimeHandler h2 = new TimeHandler(u); 132 u = (UserMgr)Proxy.newProxyInstance(UserMgr.class,h2); 133 134 u.addUser(); 135 System.out.println("\r\n==========华丽的分割线==========\r\n"); 136 u.delUser(); 137 } 138 } 139 运行结果: 140 开始时间:2014年-07月-15日 15时:48分:54秒 141 开启事务..... 142 添加用户..... 143 提交事务..... 144 结束时间:2014年-07月-15日 15时:48分:57秒 145 耗时:3秒 146 147 ==========华丽的分割线========== 148 149 开始时间:2014年-07月-15日 15时:48分:57秒 150 开启事务..... 151 删除用户..... 152 提交事务..... 153 结束时间:2014年-07月-15日 15时:49分:00秒 154 耗时:3秒 155 这里我写了两个代理的功能,一个是事务处理,一个是显示方法执行时间的代理,当然都是非常简单的写法,只是为了说明这个原理。当然,我们可以想Spring那样将这些AOP写到配置文件,因为之前那篇已经写了怎么通过配置文件注入了,这里就不重复贴了。 到这里,你可能会有一个疑问:你上面说,只要放到容器里的对象,都会有容器的公共服务,我怎么没看出来呢?好,那我们就继续看一下我们的代理功能: 156 事务处理: 157 package com.tgb.proxy; 158 159 import java.lang.reflect.Method; 160 161 public class TransactionHandler implements InvocationHandler { 162 163 private Object target; 164 165 public TransactionHandler(Object target) { 166 super(); 167 this.target = target; 168 } 169 170 @Override 171 public void invoke(Object o, Method m) { 172 System.out.println("开启事务....."); 173 try { 174 m.invoke(target); 175 } catch (Exception e) { 176 e.printStackTrace(); 177 } 178 System.out.println("提交事务....."); 179 } 180 181 } 182 从代码中不难看出,我们代理的功能里没有涉及到任何被代理对象的具体信息,这样有什么好处呢?这样的好处就是将代理要做的事情跟被代理的对象完全分开,这样一来我们就可以在代理和被代理之间随意的进行组合了。也就是说同一个功能我们只需要一个。同样的功能只有一个,那么这个功能不就是公共的功能吗?不管容器中有多少给对象,都可以享受容器提供的服务了。这就是容器的好处。 183 不知道我讲的够不够清楚,欢迎大家积极交流、讨论。
开源数据源的使用(实际开发中用):
一:DBCP
a、简介:DBCP DataBase Connection Pool
b、Apache组织搞的开源的数据源(DataSource)实现
c、使用:
1、拷贝jar包:数据库的驱动jar;commons-dbcp-1.4.jar;commons-pool-1.5.6.jar
2、在构建路径的顶层,建立一个配置文件,内容如下:dbcpconfig.properties:
3、编写工具类:
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
1 package com.Util; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 6 import org.junit.Test; 7 8 public class Client { 9 10 public Client() { 11 // TODO Auto-generated constructor stub 12 } 13 @Test 14 public void test1(){ 15 Connection conn=DbcpUtil.getConnection(); 16 try { 17 conn.close(); 18 } catch (SQLException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 } 23 24 }
二:C3p0
a.简介:非常优秀的开源的数据
b,使用方法:
1、拷贝jar包:c3p0-0.9.1.2.jar;c3p0-0.9.1.2-jdk1.3.jar(JDK版本低);c3p0-oracle-thin-extras-0.9.1.2.jar(为oracle服务)
2、编写配置文件:参考发行包中的文档
3、编写工具类:
4.3利用Tomcat管理数据源
1、JavaWeb服务器一般都提供数据源的实现,一般只需要做一些简单的配置即可。
2、配置Tomcat的数据源
Tomcat一旦配置了数据源,在启动时利用JNDI技术(JavaEE技术之一),把数据源放在JNDI容器中。
JNDI:Java Naming and Directory Interface(Java命名和目录接口)
简单理解:JNDI是一个Map<String,Object>结构的容器,类似window系统的注册表。
key:String | value:Object |
HEY_SOFTWARE/Microsoft/Ports |
|
HEY_MATHINCES/Microsoft/Ports |
|
java:/comp/env/jdbc/day17 | DataSource对象 |
3、配置步骤:
a、拷贝数据库驱动jar到Tomcat\lib目录中
b、在应用的META-INF目录下配置一个名称为context.xml的配置文件
c、从JNDI容器中取出创建好的数据源
使用JNDI的API来取:(javax.naming.*)
数据库元信息的获取(编写JDBC框架)
1、什么数据库元信息
指数据库、表等的定义信息
2、元信息:
l 数据库的元信息:DatabaseMetaData dmd = conn.getMetaData();//数据库的元信息。全部都是getter方法
l 参数元信息:执行的SQL语句中的占位符元信息
l 结果集元信息:
编写属于自己的JDBC框架
1、目的:简化代码,提高开发效率
策略设计模式