一、连接池介绍

1) 什么是连接池

实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection。这样我们就不需要每次都创建连接、释放连接了,这些操作都交给了连接池.

2) 连接池的好处

用池来管理Connection,这样可以重复使用Connection。 当使用完Connection后,调用Connectio的
close()方法也不会真的关闭Connection,而是把Connection“归还”给池。

未使用连接池
image.png
使用连接池
数据库连接池.jpg

3)如何使用数据库连接池

Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。
这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池有 DBCP连接池, C3P0连接池, Druid连接池

二、DBCP连接池的使用和测试

DBCP也是一个开源的连接池,是Apache成员之一,在企业开发中也比较常见,tomcat内置的连接池。

(1)数据准备

  1. #创建数据库
  2. CREATE DATABASE db5 CHARACTER SET utf8;
  3. #使用数据库
  4. USE db5;
  5. #创建员工表
  6. CREATE TABLE employee
  7. (
  8. eid INT PRIMARY KEY AUTO_INCREMENT ,
  9. ename VARCHAR (20), -- 员工姓名
  10. age INT , -- 员工年龄
  11. sex VARCHAR (6), -- 员工性别
  12. salary DOUBLE , -- 薪水
  13. empdate DATE -- 入职日期
  14. );
  15. #插入数据
  16. INSERT INTO employee (eid, ename, age, sex, salary, empdate) VALUES(NULL,'李清 照',22,'女',4000,'2018-11-12');
  17. INSERT INTO employee (eid, ename, age, sex, salary, empdate) VALUES(NULL,'林黛 玉',20,'女',5000,'2019-03-14');
  18. INSERT INTO employee (eid, ename, age, sex, salary, empdate) VALUES(NULL,'杜 甫',40,'男',6000,'2020-01-01');
  19. INSERT INTO employee (eid, ename, age, sex, salary, empdate) VALUES(NULL,'李白',25,'男',3000,'2017-10-01');

(2)编码实现

import org.apache.commons.dbcp.BasicDataSource;
import org.omg.CORBA.DATA_CONVERSION;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DBCPUtils {
    //1,定义常量,保存数据库连接的相关信息
    public  static  final  String DRIVENAME="com.mysql.jdbc.Driver";
    public  static  final  String URL="jdbc:mysql://localhost:3306/db5?characterEncoding=utf-8";
    public  static  final  String USERNAME="root";
    public  static  final  String PASSWORD="root";

    //2,创建连接池对象
    public  static  final BasicDataSource datasource=new BasicDataSource();

    static {
        //3,创建连接池对象并加载
        datasource.setDriverClassName(DRIVENAME);
        datasource.setUrl(URL);
        datasource.setUsername(USERNAME);
        datasource.setPassword(PASSWORD);
    }


    //3,创建连接的成员方法
    public  static Connection getConnection() throws SQLException {
        //4,从连接池中获取连接
        Connection conn= datasource.getConnection();
        return  conn;
    }

    //5,创建释放资源的方法
    public  static  void close(Connection conn, Statement stt){
        if (conn!=null&&stt!=null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                stt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }


    //重载
    public  static  void close(Connection conn, Statement stt, ResultSet rs){
        if (conn!=null&&stt!=null&&rs!=null) {
            try {
                conn.close();
                stt.close();
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }

        }
    }
}

(3)编码测试

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBCPTest {
    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            //使用连接池连接数据库
            conn= DBCPUtils.getConnection();
            //创建sql语句执行平台
            String sql="select ename from employee";
            ps=conn.prepareStatement(sql);
            rs = ps.executeQuery();
            while (rs.next()){
                String ename=rs.getString("ename");
                System.out.println("员工姓名为 "+ename);

            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DBCPUtils.close(conn,ps,rs);
        }


    }
}

输出结果:
image.png

(4)区别使用驱动连接数据库

驱动连接:

package JDBCTest;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class InsertTest {
    public static void main(String[] args) throws Exception {
        //1,注册驱动,加载驱动程序 ,通过Class的静态方法,注册mysql驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2,获取连接Connection对象
        String url="jdbc:mysql://localhost:3306/db_neu?characterEncoding=utf-8";
        Connection con = DriverManager.getConnection(url, "root", "root");

        //打印连接对象,测试由谁提供  com.mysql.jdbc.JDBC4Connection@4b9af9a9
        System.out.println(con);

        //3,获取语句执行平台对象 Statement
        Statement stt = con.createStatement();
        //3.1通过executeUpdate()方法,创建一张表
        String sql="INSERT INTO jdbc_user(id,username,PASSWORD,birthday) VALUES (6,'test4','456','199-02-03')";
        int rows= stt.executeUpdate(sql);
        if (rows>0){
            System.out.println("插入成功!");

        }
        //关闭流  先开后关
        stt.close();
        con.close();
    }

}

Connection con = DriverManager.getConnection(url, “root”, “root”);
是使用驱动包的类进行连接。

而使用连接池进行连接,是通过类BasicDataSource进行连接,是从数据库池里获取连接的。

(5)常见的配置项

image.png

三、C3P0连接池的使用和测试

C3P0是一个开源的JDBC连接池,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、 Spring等。

(1)连接准备

导包
image.png
添加配置文件
image.png

(2)编码

package C3P0;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class C3P0Utils {
    //创建对象连接数据库
    //ComboPooledDataSource dataSource=new ComboPooledDataSource();
    public  static  final  ComboPooledDataSource datasource2=new ComboPooledDataSource("mysql");


    //创建实现连接的成员方法
    public  static Connection getConnection() throws SQLException {
       return  datasource2.getConnection();
    }


    //归还资源到数据库连接池中
    //5,创建释放资源的方法
    public  static  void close(Connection conn, Statement stt){
        if (conn!=null&&stt!=null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                stt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }


    //重载
    public  static  void close(Connection conn, Statement stt, ResultSet rs){
        if (conn!=null&&stt!=null&&rs!=null) {
            try {
                conn.close();
                stt.close();
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }

        }
    }
}
package C3P0;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class C3P0Test {
    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        //创建连接
        try {
            conn = C3P0Utils.getConnection();
            String sql="select * from employee where ename = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"李白");
            rs = ps.executeQuery();
            while(rs.next()){
                int eid=rs.getInt("eid");
                String ename=rs.getString("ename");
                int age=rs.getInt("age");
                String sex=rs.getString("sex");
                System.out.println("信息:"+ename+" "+eid+" "+age+" "+sex);
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            C3P0Utils.close(conn,ps,rs);
        }


    }
}

输出
image.png
(3)常见配置项
image.png

四、Druid连接池的使用和测试

Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。

(1)连接准备

导包
image.png
导入配置文件
image.png(第二个)

(2)编码实现

package Druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;


import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DruidUtils {
    //1,定义一个常量
    public  static  DataSource dataSource;


    static {
        try {
            //2,创建属性集对象,加载配置文件
            Properties properties=new Properties();

            //3,加载配置文件信息,通过反射使用类加载器获取文件中的信息
            InputStream inputStream = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");

            //4,加载文件到Properties属性集中
            properties.load(inputStream);
            //5,通过工厂类获取连接池对象
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //6创建建立连接的方法
    public  static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return null;
        }

    }


    //7,创建释放资源的方法
    public  static  void close(Connection conn, Statement stt){
        if (conn!=null&&stt!=null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                stt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }


    //重载
    public  static  void close(Connection conn, Statement stt, ResultSet rs){
        if (conn!=null&&stt!=null&&rs!=null) {
            try {
                conn.close();
                stt.close();
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }

        }
    }
}

(3)测试

package Druid;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DruidTest {
    public static void main(String[] args) {

        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            //获取连接
            conn=DruidUtils.getConnection();

            String sql="select ename from  employee where salary between 3000 and 5000";

            //创建执行sql语句的平台
            ps=conn.prepareStatement(sql);

            rs = ps.executeQuery();

            while (rs.next()){
                String ename=rs.getString("ename");
                System.out.println(ename);
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DruidUtils.close(conn,ps,rs);
        }
    }
}

输出结果
image.png

五、DBUtils工具类

(1)简介

使用JDBC我们发现冗余的代码太多了,为了简化开发 我们选择使用 DbUtils
Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。

(2)使用方式

DBUtils就是JDBC的简化开发工具包。需要项目导入commons-dbutils-1.6.jar。
image.png

(3)Dbutils核心功能介绍

  1. QueryRunner 中提供对sql语句操作的API.
    2. ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
    3. DbUtils类,他就是一个工具类,定义了关闭资源与事务处理相关方法.

    六、案例相关知识

    (1)表和类之间的关系

    整个表可以看做是一个类
    表中的一行记录,对应一个类的实例(对象)
    表中的一列,对应类中的一个成员属性
    image.png

    (2)JavaBean组件

    1) JavaBean 就是一个类, 开发中通常用于封装数据,有一下特点
    1. 需要实现 序列化接口, Serializable (暂时可以省略)
    2. 提供私有字段: private 类型 变量名;
    3. 提供 getter 和 setter
    4. 提供 空参构造
    2)创建Employee类和数据库的employee表对应

    • 创建一个 entity包,专门用来存放 JavaBean类
    • image.png ```java package entity;

import javax.xml.crypto.Data; import java.io.Serializable;

public class Employee implements Serializable { private static final long serialVersionUID = 8241123515628108345L; private int eid; private String ename; private int age; private String sex; private double salary; private Data empdate;

public Employee() {
}

public Employee(int eid, String ename, int age, String sex, double salary, Data empdate) {
    this.eid = eid;
    this.ename = ename;
    this.age = age;
    this.sex = sex;
    this.salary = salary;
    this.empdate = empdate;
}


public int getEid() {
    return eid;
}

public void setEid(int eid) {
    this.eid = eid;
}

public String getEname() {
    return ename;
}

public void setEname(String ename) {
    this.ename = ename;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public String getSex() {
    return sex;
}

public void setSex(String sex) {
    this.sex = sex;
}

public double getSalary() {
    return salary;
}

public void setSalary(double salary) {
    this.salary = salary;
}

public Data getEmpdate() {
    return empdate;
}

public void setEmpdate(Data empdate) {
    this.empdate = empdate;
}

@Override
public String toString() {
    return "Employee{" +
            "eid=" + eid +
            ", ename='" + ename + '\'' +
            ", age=" + age +
            ", sex='" + sex + '\'' +
            ", salary=" + salary +
            ", empdate=" + empdate +
            '}';
}

}

<a name="s3Shs"></a>
# 七、使用DBUtils完成CRUD操作
<a name="H5Xqq"></a>
##  (1)QueryRunner核心类 
构造方法 :

   1. QueryRunner() 
   1. QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection 常用方法 
   1. update(Connection conn, String sql, Object... params) ,用来完成表数据的增加、删除、更新操作
   1. query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) ,用来完成表数据的查询操作
<a name="jcSMv"></a>
## (2)QueryRunner的创建
手动模式、自动模式,自动模式要传入数据库连接池的连接源(datasource)
```java
  //手动模式
        QueryRunner qr=new QueryRunner();

        //自动模式
        QueryRunner queryRunner=new QueryRunner(DruidUtils.getDataSource());
  public  static  DataSource getDataSource(){
        return  dataSource;
    }

(3)使用QueryRunner实现插入操作

package TestDBUtils;

import Druid.DruidUtils;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.SQLException;

public class DBUtilsTestDemo02 {

    @Test
    public  void  insert() throws SQLException {
        //1,创建QueryRunner对象
        QueryRunner qr=new QueryRunner();

        //2,编写占位符方式 sql语句
        String sql="insert into employee (eid,ename,age,sex,salary,empdate) values (?,?,?,?,?,?)";

        //3,设置占位符的参数
        Object [] params={null,"林一",18,"男",10000,"1999-02-01"};

        //4,建立连接
        Connection conn= DruidUtils.getConnection();
        int update = qr.update(conn, sql, params);

        //5,释放资源
        DbUtils.close(conn);

    }
}

image.png
image.png

(4)使用QueryRunner实现修改和删除

    @Test
    public  void  update() throws SQLException {
        //1,创建QueryRunner对象  自动模式
        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());

        //2,写sql语句
        String sql="update employee set salary=? where ename=?";

        Object [] params={15000,"林一"};

        //执行sql语句
        qr.update(sql,params);


    }
    @Test
    public  void delete() throws SQLException {
        //1,创建QueryRunner对象
        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());

        //2,写sql语句
        String sql="delete from employee where eid=?";

        //3,执行sql语句
        qr.update(sql,1);

    }

(5)使用QueryRunner实现查询操作

package TestDBUtils;

import Druid.DruidUtils;
import entity.Employee;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import org.omg.CORBA.PUBLIC_MEMBER;

import java.sql.Array;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class DBUtilsTestDemo03 {
    /**
     * 查询id为5的员工信息
     * @throws SQLException
     */
    @Test
    public  void query() throws SQLException {
        //创建QueryRunner对象
        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());

        //创建sql语句  查询id为5的数据信息
        String sql="select * from employee where eid=?";
        //执行sql语句并返回结果集 ArrayHandler()
        Object[] query = qr.query(sql, new ArrayHandler(), 5);
        System.out.println(Arrays.toString(query));
    }


    /**
     * 查询所有员工的信息
     * @throws SQLException
     */
    @Test
    public void queryList() throws SQLException {
        //创建QueryRunner类
        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());

        //创建sql语句并返回结果集
        String sql="select * from employee";

        //执行sql语句并放在List中   ArrayListHandler
        List<Object[]> query = qr.query(sql, new ArrayListHandler());
        //遍历集合获取数据
        for (Object[] list2:query) {
            System.out.println(Arrays.toString(list2));
        }
    }


    /**
     * 查询id为3的员工信息,并把数据封装到javaBean中
     * @throws SQLException
     */
    @Test
    public  void queryByIdForJavaBean() throws SQLException {
        //创建QueryRunner对象
        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());

        //创建sql语句
        String sql="select * from employee where eid=?";

        //执行语句,封装到javaBean中
        Employee query = qr.query(sql, new BeanHandler<Employee>(Employee.class), 3);

        System.out.println(query);
    }


    /** 查询薪资大于 3000 的所员工信息,
     * 封装到JavaBean中再封装到List集合中
     * * BeanListHandler 将结果集的每一条和数据封装到 JavaBean中 再将JavaBean 放到list集合中 * */
    @Test
    public  void queryBySalaryForListJavaBean() throws SQLException {
        //创建QueryRunner对象
        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());

        String sql="select * from employee where salary>?";

        List<Employee> query = qr.query(sql, new BeanListHandler<Employee>(Employee.class), 3000);
        for (Employee list3:query){
            System.out.println(list3);
        }

    }


    /** 查询姓名是 张百万的员工信息,将结果封装到Map集合中 *
     *  MapHandler 将结果集的第一条记录封装到
     *  Map<String,Object>中 * key对应的是 列名 value对应的是 列的值 * */
    @Test
    public  void queryByEnameFroMap() throws SQLException {
        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());
        String sql="select *  from employee where ename=?";
        Map<String, Object> map = qr.query(sql, new MapHandler(), "林一");
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry<String,Object> entry:entries)
        {
            System.out.print(entry.getKey()+"="+entry.getValue()+" ");
        }

    }


    /** 查询所有员工的薪资总额 * ScalarHandler 用于封装单个的数据 * */
    @Test
    public  void querySalarySum() throws SQLException {

        QueryRunner qr=new QueryRunner(DruidUtils.getDataSource());
        String sql="select sum(salary) from employee";
        Double query = (Double) qr.query(sql, new ScalarHandler<>());
        System.out.println(query);

    }


}

八、批处理

(1)什么是批处理

  • 批处理(batch) 操作数据库
    • 批处理指的是一次操作中执行多条SQL语句,批处理相比于一次一次执行效率会提高很多。
    • 当向数据库中添加大量的数据时,需要用到批处理。
  • 举例: 送货员的工作:
    • 未使用批处理的时候,送货员每次只能运送 一件货物给商家;
    • 使用批处理,则是送货员将所有要运送的货物, 都用车带到发放处派给客户。

      九、批处理的实现

      Statement和PreparedStatement都支持批处理操作,这里我们介绍一下PreparedStatement的批处理方式:

      1) 要用到的方法

      image.png

      2) mysql 批处理是默认关闭的,所以需要加一个参数才打开mysql 数据库批处理,在url中添加

      rewriteBatchedStatements=true
      例如: url=jdbc:mysql://127.0.0.1:3306/db5?characterEncoding=UTF-8&rewriteBatchedStatements=true
      image.png

      3) 创建一张表

      CREATE TABLE testBatch ( id INT PRIMARY KEY AUTO_INCREMENT, uname VARCHAR(50) )
      

      4) 测试向表中插入 1万条数据

      ```java package TestBath;

import Druid.DruidUtils; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException;

public class BathTest { public static void main(String[] args) throws SQLException { //获取连接 Connection con= DruidUtils.getConnection(); //创建执行连接的平台 PreparedStatement ps = con.prepareStatement(“insert into testBatch(uname) values(?)”);

    //批量处理一万次插入操作
    for (int i =1 ; i <=10000 ; i++) {
        ps.setString(1,"小强"+i);

        //添加到批处理中
        ps.addBatch();
    }
    long l = System.currentTimeMillis();

    //执行批处理操作
    ps.executeBatch();
    long l1 = System.currentTimeMillis();
    System.out.println("插入1000条数据使用了:"+(l1-l)+"毫秒!");
}

}

<a name="QmOUh"></a>
# 十、MySql元数据
<a name="JXFei"></a>
## (1)什么是元数据 
除了表之外的数据都是元数据,可以分为三类 

1. **查询结果信息:** UPDATE 或 DELETE语句 受影响的记录数。 
1. **数据库和数据表的信息: **包含了数据库及数据表的结构信息。 
1. **MySQL服务器信息: **包含了数据库服务器的当前状态,版本号等。
<a name="jmtyQ"></a>
## (2)常用命令
-- 1.查看服务器当前状态 <br />show status; 查看服务器的状态信息<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22605889/1633537290336-19af62dc-870a-4776-a6fe-70b0a1bc5045.png#clientId=ua2743d1a-2fc1-4&from=paste&height=233&id=IQu8j&margin=%5Bobject%20Object%5D&name=image.png&originHeight=466&originWidth=1370&originalType=binary&ratio=1&size=458628&status=done&style=none&taskId=uf0eab8ea-4a56-4a12-8de9-e00b8612e52&width=685)<br />-- 2.查看MySQl的版本信息 <br />select version(); 获取mysql服务器的版本信息<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22605889/1633537367526-5dc99730-c825-412d-9f2c-2777b425d920.png#clientId=ua2743d1a-2fc1-4&from=paste&height=59&id=u82433352&margin=%5Bobject%20Object%5D&name=image.png&originHeight=117&originWidth=404&originalType=binary&ratio=1&size=4833&status=done&style=none&taskId=u5cabace4-0234-4838-a084-a3958c1fa5b&width=202)<br />-- 3.查询表中的详细信息 <br />show columns from table_name; 显示表的字段信息等,和desc table_name一样<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22605889/1633537442921-b09089e2-51af-4f2f-b0ca-dabf6a0a466d.png#clientId=ua2743d1a-2fc1-4&from=paste&height=92&id=u4add291a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=184&originWidth=741&originalType=binary&ratio=1&size=16391&status=done&style=none&taskId=ueba89d02-3168-411d-b32f-1aa96d8b35c&width=370.5)<br />-- 4.显示数据表的详细索引信息 <br />show index from table_name; 显示数据表的详细索引信息,包括PRIMARY KEY(主键)<br />-- 5.列出所有数据库 <br />show databases:列出所有数据库 <br />-- 6.显示当前数据库的所有表 <br />show tables : 显示当前数据库的所有表 <br />-- 7.获取当前的数据库名<br />select database(): 获取当前的数据库名
<a name="t2CiR"></a>
## 十一、通过JDBC获取元数据
通过JDBC 也可以获取到元数据,比如数据库的相关信息,或者当我们使用程序查询一个不熟悉的表时, 我们可以通过获取元素据信息,了解表中有多少个字段,字段的名称 和 字段的类型
<a name="n3CEo"></a>
## (1)常用类介绍
JDBC描述元数据的类<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22605889/1633537768234-2371b2d8-8d20-42bf-b7dd-69b276e45ee8.png#clientId=ua2743d1a-2fc1-4&from=paste&height=115&id=u4e4a902b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=229&originWidth=1437&originalType=binary&ratio=1&size=46360&status=done&style=none&taskId=ub91651c3-bdcb-40be-828e-ffe0abd76de&width=718.5)<br />获取元数据对象的方法 : getMetaData () <br />connection 连接对象, 调用 getMetaData () 方法,获取的是DatabaseMetaData 数据库元数据对象 <br />PrepareStatement 预处理对象调用 getMetaData () , 获取的是ResultSetMetaData , 结果集元数据对象 
<a name="BBJvs"></a>
## (2)DatabaseMetaData的常用方法
![image.png](https://cdn.nlark.com/yuque/0/2021/png/22605889/1633537833368-f5a34b4b-fe0c-42b9-8226-770424d8de78.png#clientId=ua2743d1a-2fc1-4&from=paste&height=262&id=u1727249d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=524&originWidth=1363&originalType=binary&ratio=1&size=116365&status=done&style=none&taskId=u4360c090-5660-43c3-83a4-3815299e4e4&width=681.5)
<a name="c8adK"></a>
## (3)ResultSetMetaData的常用方法
![image.png](https://cdn.nlark.com/yuque/0/2021/png/22605889/1633537866303-4c37fcb7-9385-47ab-b148-2b630367f245.png#clientId=ua2743d1a-2fc1-4&from=paste&height=155&id=uf8aaab69&margin=%5Bobject%20Object%5D&name=image.png&originHeight=310&originWidth=1361&originalType=binary&ratio=1&size=73430&status=done&style=none&taskId=u622bc38d-df25-4c3f-8484-cccea4876b6&width=680.5)

```java
package com.lagou.testmetadata;

import com.lagou.utils.DruidUtils;
import org.junit.Test;

import java.sql.*;

public class TestMetaData {

    //1.获取数据库相关的元数据信息 使用DatabaseMetaData
    @Test
    public void testDataBaseMetaData() throws SQLException {

        //1.获取数据库连接对象 connection
        Connection connection = DruidUtils.getConnection();

        //2.获取代表数据库的 元数据对象 DatabaseMetaData
        DatabaseMetaData metaData = connection.getMetaData();

        //3.获取数据库相关的元数据信息
        String url = metaData.getURL();
        System.out.println("数据库URL: " + url);

        String userName = metaData.getUserName();
        System.out.println("当前用户: " + userName );

        String productName = metaData.getDatabaseProductName();
        System.out.println("数据库产品名: " + productName);

        String version = metaData.getDatabaseProductVersion();
        System.out.println("数据库版本: " + version);

        String driverName = metaData.getDriverName();
        System.out.println("驱动名称: " + driverName);

        //判断当前数据库是否只允许只读
        boolean b = metaData.isReadOnly();  //如果是 true 就表示 只读
        if(b){
            System.out.println("当前数据库只允许读操作!");
        }else{
            System.out.println("不是只读数据库");
        }

        connection.close();
    }

   //获取结果集中的元数据信息
    @Test
    public void testResultSetMetaData() throws SQLException {

        //1.获取连接
        Connection con = DruidUtils.getConnection();

        //2.获取预处理对象
        PreparedStatement ps = con.prepareStatement("select * from employee");
        ResultSet resultSet = ps.executeQuery();

        //3.获取结果集元素据对象
        ResultSetMetaData metaData = ps.getMetaData();

        //1.获取当前结果集 共有多少列
        int count = metaData.getColumnCount();
        System.out.println("当前结果集中共有: " + count + " 列");

        //2.获结果集中 列的名称 和 类型
        for (int i = 1; i <=  count; i++) {
            String columnName = metaData.getColumnName(i);
            System.out.println("列名: "+ columnName);

            String columnTypeName = metaData.getColumnTypeName(i);
            System.out.println("类型: " +columnTypeName);
        }

        //释放资源
        DruidUtils.close(con,ps,resultSet);
    }

}