zoukankan      html  css  js  c++  java
  • JDBC

    1. Driver接口
    注册数据库驱动程序,分别为:
    DriverManager.registerDriver(new Driver());
    Class.forName("com.mysql.jdbc.Driver");

    推荐采用第二种方式,因为它本身采用静态代码块
    如果采用第一种的方式,会注册两次

    2. url:即连接协议
    jdbc:mysql:///127.0.0.1:3306/db9?useUnicode=true&characterEncoding=UTF8
    3. Connection
    Statement及其子类
    ResulSet
    select * from someTable   --N+2 查询结果永远是N+2条,因为包括行首,行尾

    连接池的引入

    创建Connection的过程是非常耗时的,为保证Connection可以重用,应该对其进行池管理.

    传统的连接只有一个,我们把它比作公路,我们连接创建后进行sql操作后再关闭连接,就相当于你从高速公路到达某个地方后,把走过的那条高速公路拆了,过河拆桥,别人就不能访问了,别人只好重修修建公路(自己再重新new 一个连接)

    于是,传统解决办法:创建一个静态工厂方法(多次使用,防止重复new),但是只有一个连接

    所以还是不行,于是引入了连接池,我们可以把它比作抽奖箱里面的小球,具体自己可以琢磨一下

    连接池的基本实现

             为什么要有连接池

              1:维护多个连接。必须要保证每一个线程获取到的是不同的connection对象。

              2:提供一个方法可以回收连接。

    而程序员,总是调用close方法,所以为了回收连接。我们应该重写close方法。对close方法增强。一下是三种实现方式:

    子类。(继承的体现)

    包装。

    代理。

    动态代理实现连接池

    动态代理:

    作用:1.对某个方法增强.

    2.在不污染原类的情况下,修改原类的行为.

    代理类,与被代理类,两个不同的实体

    要求:

    所有被代理的类,都必须要拥有一个接口.

    本质上是对方法的修改,但其实它是通过反射执行的某个方法.

    代理是代理接口

    代理的任务

    1.在内存中创建某个接口的子类.

    2.拦截所有在代理上知心的方法(出了getClass方法)

    用动态代理书写连接池

    设计:

    代理的目标:原生的Connection

    代理的目的:修改close方法,让close方法不可以关闭连接,且主动回收连接

    小技巧:在myeclipse中,资源文件创建时默认是iso 8859-1编码(不管你项目创建的是以什么编码方式的)

    具体代码实现:

     1 public class ConnUtils{
     2     //第一步:声明连接池维护所有的连接
     3     private static List<Connection> pool = new ArrayList<Connection>();
     4     //第二步:静态代码块中创建多个连接
     5     static{
     6         try{
     7             Class.forName("com.mysql.jdbc.Driver");
     8             String url = "jdbc:mysql:///db909?characterEncoding=UTF8";
     9             for(int i=0;i<3;i++){
    10                 final Connection con = DriverManager.getConnection(url,"root","1234");//com.mysql.jdbc.Jdbc4Connection@
    11                 //对con对象进行动态代理
    12                 Object proxyedCon = 
    13                         Proxy.newProxyInstance(
    14                                 ConnUtils4.class.getClassLoader(),
    15                                 new Class[]{Connection.class},
    16                                 //声明执行句柄,只对close方法设置拦截
    17                                 new InvocationHandler() {
    18                                     public Object invoke(Object proxy, Method method, Object[] args)
    19                                             throws Throwable {
    20                                         if(method.getName().equals("close")){
    21                                             System.err.println("有人想关闭连接,不能关,还连接");
    22                                             //将proxy再加到pool中,这个proxy就是proxyedCon
    23                                             synchronized (pool) {
    24                                                 pool.add((Connection) proxy);
    25                                                 pool.notify();
    26                                             }
    27                                             return null;
    28                                         }else{
    29                                             System.err.println("放行"+method.getName());
    30                                             return method.invoke(con, args);
    31                                         }
    32                                     }
    33                                 });
    34                 //一定要将代理对象添加到池中去。
    35                 pool.add((Connection) proxyedCon);
    36             }
    37         }catch(Exception e){
    38             throw new RuntimeException(e.getMessage(),e);
    39         }
    40     }
    41     /**
    42      * 提供一个静态工厂方法返回一个连接
    43      */
    44     public static Connection getCon(){
    45         synchronized (pool) {
    46             if(pool.size()==0){
    47                 try {
    48                     pool.wait();
    49                 } catch (InterruptedException e) {
    50                     e.printStackTrace();
    51                 }
    52                 return getCon();
    53             }
    54             Connection con = pool.remove(0);//返回一个代理的connection对象
    55             System.err.println("还有几个:"+pool.size());
    56             return con;
    57         }
    58     }
    59 }

    以上代码可以优化

    通过类加载器读取一个资源文件:

    SomeClass.class.getResourcre(xxx) --获取与SomeClass字节码同一个目录下的xxx文件.

    SomeClass.class.getClassLoader().getResource(xxxxx)  --获取classpath根上下的xxxxx文件

    1.将url,driver,name,pwd写到一个配置文件中去

    2.通过LinkedList来维护池.

    优化后的代码:

     1 public class ConnUtils3 {
     2     private static LinkedList<Connection> pool = new LinkedList<Connection>();
     3     static{
     4         try {
     5             //声明资源器类 - 
     6             Properties prop = new Properties();
     7             //获取这个文件的路径
     8             URL url = ConnUtils3.class.getClassLoader().getResource("jdbc.properties");
     9             String path = url.getPath();
    10             //为了防止有中文或是空格
    11             path = URLDecoder.decode(path,"UTf-8");
    12             File file = new File(path);
    13             //加载jdbc.properties这个文件
    14             prop.load(new FileInputStream(file));
    15             //获取信息
    16             String driver = prop.getProperty("driver");
    17             Class.forName(driver);
    18             String jdbcurl = prop.getProperty("url");
    19             String nm = prop.getProperty("name");
    20             String pwd = prop.getProperty("pwd");
    21             //创建三个原生的连接,都将它们代理
    22             String poolSize = prop.getProperty("poolSize");
    23             int size = Integer.parseInt(poolSize);
    24             for(int i=0;i<size;i++){
    25                 final Connection con = DriverManager.getConnection(jdbcurl,nm,pwd);
    26                 //对con进行动态代理
    27                 Object proxyedObj = 
    28                         Proxy.newProxyInstance(ConnUtils3.class.getClassLoader(),
    29                                     new Class[]{Connection.class},
    30                                     new InvocationHandler() {
    31                                         public Object invoke(Object proxy, Method method, Object[] args)
    32                                                 throws Throwable {
    33                                             //是否是close方法
    34                                             if(method.getName().equals("close")){
    35                                                 synchronized (pool) {
    36                                                     pool.addLast((Connection) proxy);
    37                                                     pool.notify();
    38                                                 }
    39                                                 return null;//如果调用的是close则不会调用被代理类的方法。
    40                                             }
    41                                             return method.invoke(con, args);
    42                                         }
    43                                     });
    44                 //将代理对象放到pool中
    45                 pool.add((Connection) proxyedObj);
    46             }
    47         } catch (Exception e) {
    48             e.printStackTrace();
    49         }
    50     }
    51     
    52     public static Connection getConn(){
    53         synchronized (pool) {
    54             if(pool.size()==0){
    55                 try {
    56                     pool.wait();
    57                 } catch (InterruptedException e) {
    58                     e.printStackTrace();
    59                 }
    60                 return getConn();
    61             }else{
    62                 Connection con = pool.removeFirst();
    63                 System.err.println("还有几个:"+pool.size());
    64                 return con;
    65             }
    66         }
    67     }
    68     
    69     
    70 }

    什么时候可以使用statement而不使用Perpstatement呢?

    在用户不需要输入的时候,可以采用statement,其他建议全部使用Perpstatement

    最后,附上开发开发分层图

  • 相关阅读:
    PHP面向对象(一)
    Linux(九)LNMP环境Nginx服务器
    Linux(八)Apache服务器
    [转]PHP高手干货分享:不能不看的50个细节!
    Linux(七)LAMP环境搭建
    Linux(六)Samba服务器与防火墙
    Linux(五)服务和进程管理
    Linux(四)用户和用户组管理
    Linux(三)安装包
    Linux(二)Linux常用命令
  • 原文地址:https://www.cnblogs.com/ylfeiu/p/3621886.html
Copyright © 2011-2022 走看看