获取数据库的元信息metadata,里面有数据库特性的描述信息,如是否支持事务,是否支持批处理等。

Connection conn = DriverManager.getConnection(url, userName,passwrod);
DatabaseMetaData md = conn,getMetaData();
System.out.println(md.supportTransactions());

还可以获取参数的metadata:

PreparedStatement ps = conn.prepareStatement(sql);

ParamterMetaData pm = ps.getParamterMetaData();

还可以获取返回的结果集中的metadata,用于将结果封装为需求的对象如Map,List等:

ResultSet rs = ps.executeQuery();
     ResultSetMetaData meta = rs.getMetaData();

  

class的无参数的newInstance方法要求类有一个无参数的构造方法。

Constructor con = class.getConstructor(String.class);     //取得对象的参数为String的构造方法,参数是可变长度的数组

   Object  obj = con.newInstance("test");         //参数是可变长度的数组

  Method [] ms = object.getClass.getDeclaredMethods();     //找到类中的所有方法,包括私有方法,但不包括父类方法

Method [] ms = object.getClass.getMethods();     //找到类及父类方法中的所有方法,但不包括私有方法

  

   Java类库中有三个类直接支持代理模式:Proxy,InvocationHandler和Method。

下面是在List加上代理,在添加元素的前后打印一些信息。

public class VectorProxy implements InvocationHandler{

    private Object proxyobj;

    public VectorProxy(Object obj){

        proxyobj = obj;

    }

    public static Object factory(Object obj){

        Class cls = obj.getClass();

        return Proxy.newProxyInstance( cls.getClassLoader(),

            cls.getInterfaces(),

            new VectorProxy(obj) );

    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{

        System.out.println("before calling " + method);

        if (args != null){

            for (int i=0; i<args.length; i++){

                System.out.println(args[i] + "");

            }

        }

        Object o = method.invoke(proxyobj, args);

        System.out.println("after calling " + method);

        return o;

    }

    public static void main(String[] args){

        List v = null;

        v = (List) factory(new Vector(10));

        v.add("New");

        v.add("York");

    }

}

  打印出的信息如下:

before calling public abstract boolean java.util.List.add(java.lang.Object)

New

after calling public abstract boolean java.util.List.add(java.lang.Object)

before calling public abstract boolean java.util.List.add(java.lang.Object)

York

after calling public abstract boolean java.util.List.add(java.lang.Object)

  代理模式需要一个原始类的实例,InvocationHandler中invoke方法实际调用的是原始类的实例,需要仿照着一个实例在内存中动态地生成字节码。因为方法除非是静态方法,否则都是要和实例来绑定使用的。

  利用代理模式,如果希望java.sql.Connection的close方法不是去关掉真正的数据库连接而是将连接放回到连接池中,可以使用下面的代码:

public class ConnectionProxy implements InvocationHandler{

    private java.sql.Connection wrappedConnection;

    private java.sql.Connection realConn;

    private DataSource dataSource;

    public ConnectionProxy(DataSource dataSource ){
this.dataSource = dataSource;
} public static java.sql.Connection bind(java.sql.Connection conn){
this.realConn = conn; Class cls = conn.getClass(); wrappedConnection = Proxy.newProxyInstance( cls.getClassLoader(), /*cls.getInterfaces()*/new class[]{java.sql.Connection.class},this); //这里需要继承自java.sql.Connection接口,否则创建出的连接在连接池添加,删除时有问题
return wrappedConnection; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ if (method.getName().equals("close")){ this.dataSource.connectionsPool.addLast(wrappedConnection);Q } Object o = method.invokerealConn;args); return o; } }

  DataSource类中产生connection时就换为ConnectionProxy即可。

private Connection createConnection(){
java.sql.Connection conn = DriverManager.getConnection(url,user,password);
ConnectionProxy proxy = new ConnectionProxy(this);
return proxy.bind(conn ); }

  

  通过数据源DataSource中的连接池获取的Connection都是包装后的Connection,已经修改了close方法,不是简单的关闭连接,而是要再放回连接池中。

  

  连接池一般会要求提供一个配置文件,基本的配置项包括:初始连接数,最大连接数,最大、最小空闲连接数等。下面的是一个Durid数据库连接池的配置文件: 

<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

        <property name="url" value="${jdbc_url}" />

        <property name="username" value="${jdbc_username}" />

        <property name="password" value="${jdbc_password}" />

        <!-- 初始化连接大小 -->

        <property name="initialSize" value="0" />

        <!-- 连接池最大使用连接数量 -->

        <property name="maxActive" value="20" />

        <!-- 连接池最大空闲 -->

        <property name="maxIdle" value="20" />

        <!-- 连接池最小空闲 -->

        <property name="minIdle" value="0" />

        <!-- 获取连接最大等待时间 -->

        <property name="maxWait" value="60000" />

        <!-- <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->

        <property name="validationQuery" value="${validationQuery}" />

        <property name="testOnBorrow" value="false" />

        <property name="testOnReturn" value="false" />

        <property name="testWhileIdle" value="true" />

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->

        <property name="timeBetweenEvictionRunsMillis" value="60000" />

        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->

        <property name="minEvictableIdleTimeMillis" value="25200000" />

        <!-- 打开removeAbandoned功能 -->

        <property name="removeAbandoned" value="true" />

        <!-- 1800秒,也就是30分钟 -->

        <property name="removeAbandonedTimeout" value="1800" />

        <!-- 关闭abanded连接时输出错误日志 -->

        <property name="logAbandoned" value="true" />

        <!-- 监控数据库 -->

        <!-- <property name="filters" value="stat" /> -->

        <property name="filters" value="mergeStat" />

    </bean>

  上面将配置信息直接写到程序中的方法并不好,可以写成配置文件druiddb.xml,去从配置文件中来读取配置。

driverClassName = com.mysql.jdbc.Driver
url =com.mysql.jdbc.Driver
uer = root
password = OSSDB123
initialSize =5

  再修改上面的DruidManager类,使之从配置文件中加载参数:

Properties p = new Properties();

InputStream is = DuridManager,class.getClassLoader().loadResourceAsStream("duriddb.xml");

p.load(is);

dataSource = new DruidDataSource(p);

  连接池的connection也是包装后的connection,需要改写close方法。

JDBC学习笔记(三)的更多相关文章

  1. JDBC 学习笔记(十一)—— JDBC 的事务支持

    1. 事务 在关系型数据库中,有一个很重要的概念,叫做事务(Transaction).它具有 ACID 四个特性: A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操 ...

  2. JDBC 学习笔记(十)—— 使用 JDBC 搭建一个简易的 ORM 框架

    1. 数据映射 当我们获取到 ResultSet 之后,显然这个不是我们想要的数据结构. 数据库中的每一个表,在 Java 代码中,一定会有一个类与之对应,例如: package com.gerrar ...

  3. JDBC学习笔记二

    JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...

  4. JDBC学习笔记一

    JDBC学习笔记一 JDBC全称 Java Database Connectivity,即数据库连接,它是一种可以执行SQL语句的Java API. ODBC全称 Open Database Conn ...

  5. Oracle学习笔记三 SQL命令

    SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)  

  6. [Firefly引擎][学习笔记三][已完结]所需模块封装

    原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读:        笔记三主要就是各个模块的封装了,这里贴 ...

  7. JSP学习笔记(三):简单的Tomcat Web服务器

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  8. java之jvm学习笔记三(Class文件检验器)

    java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...

  9. VSTO学习笔记(三) 开发Office 2010 64位COM加载项

    原文:VSTO学习笔记(三) 开发Office 2010 64位COM加载项 一.加载项简介 Office提供了多种用于扩展Office应用程序功能的模式,常见的有: 1.Office 自动化程序(A ...

随机推荐

  1. [bzoj1227] [SDOI2009]虔诚的墓主人

    终于填上了这个万年巨坑....从初二的时候就听说过这题...然后一直不敢写QAQ 现在感觉也不是很烦(然而我还是写麻烦了 离散化一波,预处理出组合数什么的.. 要维护对于当前行,每列上方和下方节点凑出 ...

  2. [bzoj1587] [Usaco2009 Mar]Cleaning Up 打扫卫生

    首先(看题解)可得...分成的任意一段中的不同颜色个数都<=根号n...不然的话直接分成n段会更优= = 然后就好做多了.. 先预处理出对于每头牛i,和它颜色相同的前一头和后一头牛的位置. 假设 ...

  3. 程序员之殇 —— (The Beginning of the End)噩梦、崩坏

    Look at all those faces out there (当我环视周遭的一张张脸孔) We are so different(我们是如此的不同) But we have one thing ...

  4. 数组的创建和各种API

    数组的创建方式: 1. 数组直接量 var arr = [] // 创建一个空数组 var arr = [1,2,3,4] // 创建同时初始化元素 2. 实例化对象 var arr=new Arra ...

  5. 本地如何使用phpstudy环境搭建多站点

    http://jingyan.baidu.com/article/e52e36154227ef40c70c5147.html 平时在开发项目的时候, 多个项目同时开发的时候会遇到都得放到根目录才能正常 ...

  6. 关于JWPlayer播放器的一些测试学习

    <!DOCTYPE html><html><head> <title>jwplayer播放器测试</title> <script ty ...

  7. 【开发技术】Java生成验证码

    Java生成验证码 为了防止用户恶意,或者使用软件外挂提交一些内容,就得用验证码来阻止,虽然这个会影响用户体验,但为了避免一些问题很多网站都使用了验证码;今天下午参考文档弄了一个验证码,这里分享一下; ...

  8. MySQL时间差返回月个数

    select PERIOD_DIFF(date_format(now(),'%Y%m'),date_format('2010-11-30','%Y%m')) 1. MySQL 为日期增加一个时间间隔: ...

  9. 使用axios post 提交数据,后台获取不到提交的数据解决方案

    一.问题发现 前后端分离使用vue开发,结合axios进行前后端交互数据,一开始使用 get 请求,获取数据,没有发现任何问题,当使用 post请求 传参时,发现,数据明明已经提交,在打开F12 开发 ...

  10. CDN页面刷新接口定义[高升]

    一 . 任务 分发 工作流程步骤 1. 合作方按照高升定义的 json 数据格式向高升分发接口 post 任务,高升分发接口会根据接收情况即时反馈接收成功还是失败的结果.二 . 高升 分发 接口 定义 ...