JDBC

JDBC

1.连接数据库的方式

    常见有两种: ODBC和JDBC,分属两个不同的阵营。

    其中JDBC是java版本的ODBC

    ODBC(Open Database Connectivity)开放的数据库连接,由微软开发出来。是一套公共的接口(标准),用来连接数据库。

    JDBC是一套标准(接口),用来连接【关系型数据库】。各个数据库厂商去实现具体的功能,用户使用时使用相同一套标准即可。但是在使用时得导入不同公司提供的包(里面包含了具体实现)。

2.JDBC概念

JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API ,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

    JDBC API是什么?

Sun公司提供的一套标准的数据访问接口,用来访问关系型数据库。另外,它包含了一部分类和接口,属于Java语言的一部分。

    JDBC可以做什么:

连接数据库

发送sql语句到数据库

处理结果集

    JDBC API包含两部分内容:

Java应用程序开发接口(提供给用户)

Java驱动开发接口(实现公共接口功能,各大数据库厂商做)

3.JDBC驱动

    其实就是一组类和接口的集合,实现了JDBC相关的功能。

    java.sql.Driver 这个驱动接口很重要,我们借助这个类实现了数据库的连接。

    JDBC【驱动提供了特定厂商对JDBC API接口类的实现】,驱动必须要提供java.sql包下面这些类的实现:Connection,Statement,PreparedStatement,CallableStatement,ResultSet和Driver.

******************************

4.JDBC驱动类型

    Java中的JDBC驱动可以分为【四种类型】,包括【JDBC-ODBC桥、本地API驱动、网络协议驱动和本地协议驱动】。

5.JDBC-ODBC桥

    JDBC-ODBC 桥 是sun公司提供的,是jdk提供的的标准API.【底层是借助ODBC】实现功能,缺陷是效率较低,还得必须安装ODBC驱动。

****以下内容了解即可****

    这种类型的驱动实际是把所有 JDBC的调用传递给ODBC ,再由ODBC调用本地数据库驱动代码.( 本地数据库驱动代码是指 由数据库厂商提供的数据库操作二进制代码库,例如在oracle for windows中就是oci dll 文 件)

    只要本地机装有相关的ODBC驱动那么采用JDBC-ODBC桥几乎可以访问所有的数据库,JDBC- ODBC方法对于客户端已经具备ODBC driver的应用还是可行的.

但是,由于JDBC-ODBC先调用 ODBC再由ODBC去调用本地数据库接口访问数据库.所以,执行效率比较低,对于那些大数据量 存取的应用是不适合的.而且,这种方法要求客户端必须安装ODBC 驱动,所以对于基于 internet ,intranet的应用也是不合适的.因为,你不可能要求所有客户都能找到ODBC driver.

6.本地API驱动

    本地API驱动直接【把JDBC调用】转变为【数据库的标准调用】再去访问数据库.效率比第一种高,但得【需要额外的数据库工具】。

这种方法需要本地 数据库驱动代码、本地API驱动、厂商DB代码。这种驱动比起JDBC-ODBC桥执行效率大大提高了.但是,它仍然需要在客户端加载数据库厂商 提供的代码库.这样就不适合基于internet的应用.并且,他的执行效率比起其他的JDBC驱动 还是不够高.

7.网络协议驱动

    这种驱动实际上是根据我们熟悉的三层结构建立的.

    JDBC先把对数局库的访问请求传递给网络上的【中间件服务器】. 中间服务器再把请求【翻译为符合数据库规范的调用】,再把这种调用 【传给数据库服务器】.

    如果中间服务器也是用java开发的,那么在在中间层也可以使用上面说的那俩种驱动类型 JDBC驱动程序作为访问数据库的方法. 网络协议驱动---------中间服务器------------数据库Server

    由于这种驱动是基于server的.所以,它不需要在客户端加载数据库厂商提供的代码库.而且 他在执行效率和可升级性方面是比较好的.因为大部分功能实现都在server端,所以这种驱动 可以设计的很小,可以非常快速的加载到内存中.

    但是,这种驱动在中间件层仍然需要有配置 其它数据库驱动程序,并且由于多了一个中间层传递数据,它的执行效率还不是最好.

8.本地协议驱动

    我们【当前使用的JDBC驱动】一般都是这种类型。

    这种类型的驱动【完全由java实现】,实现了平台独立性。

它可以直接把JDBC调用转换为符合相关数据库系统规范的请求.这种驱动写的应用可以直接和数据库服务器通讯。

本地协议驱动【效率非常高】,因为它不需要先把JDBC的调用传给ODBC或本地数据库接口或者是中间层服务器。

而且,它不需要在客户端或服务器端装载任何的软件或驱动, 这种驱动程序可以动态的被下载。

但是对于不同的数据库【需要下载不同的驱动程序】(驱动实现jar包)。

*******************************

9.JDBC数据库操作相关类和接口

    Driver驱动接口

    DriverManager驱动管理器【类】

    Connection数据库连接

    Statement操作语句

PreparedStatement

CallableStatement

    ResultSet结果集

    DatabaseMetadata数据库信息(包含数据库有哪些表,视图,列,类型等信息,由表反向生成类)

    ResultSetMetadata结果集信息

    Types类型【类】(数据库表类型与java代码中类型String,int,double等的对应)

jdbc开发接口,存在于两个包下,其中【java.sql包】下实现了基本功能;剩余部分存在于【javax.sql包】中,实现扩展功能。

10.JDBC操作流程

    用户如何通过Java代码连接到 指定的数据库服务器,然后进行操作。

    有6个固定的步骤,按照步骤操作即可。

1).注册驱动(驱动:具体功能实现)

2).建立数据库连接

3).创建Statement对象(可以进行sql与执行)

4).执行SQL语句(增删改查)

5).处理结果集

6).关闭相应资源

11.注册驱动

【注册驱动】的过程,可以理解成【安装驱动】。想一下生活中安装好系统,usb外接鼠标不能用,安装个驱动就可以用了。此处注册好了驱动,数据库连接就可以使用了。

    注册驱动的三种方案:

使用类加载器

实例化一个驱动对象,使用new的方式

使用property


ojdbc5.jar Oracle11g配套推出的

ojdbc6.jar 11g配套推出

ojdbc14.jar Oracle10g发布时配套推出的

    14、5、6与JDK的版本有关系,14是1.4版本以上,ojdbc5.jar得jdk5,ojdbc6.jar得用jdk6及其以上版本。

查看自己jdk版本命令: java -version

    此后学习过程中,不仅仅要注意代码,还要关注环境是否配置正常。(防火墙、杀毒软件等都可能会影响最后的结果)

12.JDBC连接类型

JDBC的连接类型有两种,分别是oci 和 thin

    1)、JDBC OCI

oci是oracle call interface的缩写,此驱动类似于传统的ODBC 驱动。

因为它需要Oracle Call Interface and Net8,所以它【需要】在运行使用此驱动的JAVA程序的机器上安装【客户端软件】,其实主要是用到orcale客户端里以dll方式提供的oci和服务器配置。

    2)、JDBC Thin

thin是for thin client的意思,这种驱动一般用在运行在WEB浏览器中的JAVA程序。

它不是通过OCI or Net8,而是通过Java sockets进行通信,是纯java实现的驱动,因此【不需要】在使用JDBC Thin的客户端机器上安装orcale【客户端软件】,所以有很好的移植性,通常用在web开发中。


我们更多的【选择thin】这种方式进行服务器连接。

13.JDBC四要素

    1).String driver = "jar包Driver类全包名";

告诉我们具体数据库驱动在哪里,方便后期注册。

String dirver = "oracle.jdbc.driver.OracleDriver";


    2).URL 确定连接到那个具体的数据库

jdbc:oracle:oci:@  oci连接方式

jdbc:oracle:thin:@ thin连接方式

String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";

    3).String user = "用户名";

    4).String password = "密码";

14.注册driver和连接数据库

14.1 注册driver有三种方式

    a.使用类加载器

String driverName = "oracle.jdbc.driver.OracleDriver";

Class.forName(driverName);

    b.实例化一个驱动对象

实例化驱动对象

Driver driver = new oracle.jdbc.driver.OracleDriver();

注册驱动

DriverManager.registerDriver(driver);

    c.使用property

System.setProperty("jdbc.drivers", "oracle.jdbc.driver.OracleDriver");

使用【系统配置】进行驱动注册,其中【第一个参数值固定】,第二个参数为驱动类的全包名。

    补充: 也可以运行虚拟机时,设置运行参数。

这种方式也是通过系统配置进行驱动注册。

-Djdbc.drivers=oracle.jdbc.driver.OracleDriver

14.2 数据库连接的方式有两种:

第一种是利用DriverManager.getConnection(url, user, passwd);

第二种是利用Driver类直接连接(其实第一种底层也是通过Driver建立的连接)。

Driver driver = new oracle.jdbc.driver.OracDriver();

Properties info = new Properties();

info.setProperty("user","");

info.setProperty("password","");

conn = driver.connect(url,info);

关于DriverManager和Driver的关系

一个DriverManager可以管理多个Driver,在具体进行数据库连接时,管理类借助Driver里面的connect方法建立连接。

****************

数据库连接不成功解决方案

反复检查四要素是否写错

数据库未启动

防火墙影响

换个jar包试试

如果按照oracle出现中文路径,不行

如果按照成功后修改计算机用户名,也行

重装oracle

****************

15.Statement语句

    Statement stmt = conn.createStatement();

String sql = "";

    stmt.execute(sql);

    stmt.executeQuery(sql);

    stmt.executeUpdate(sql);

    一共有三种执行方式,他们都可以正常执行select insert update delete语句,区别在于返回值类型。

    execute(sql)返回boolean,执行【返回结果集则true】,否则false;

    executeUpdate(sql)【返回int】,执行影响了多少条数据;

    executeQuery(sql)返回结果集ResultSet。

16.java.util.Date和java.sql.Date

    java.util.Date是java.sql.Date的父类;

    一般情况下表示时间,用util.Date,在操作sql语句时才使用sql.Date

    通过【时间戳】值进行转换

    例如: new java.sql.Date(utilDate.getTime());

17.事务提交

DML语句

    设置事务自动提交 关闭,【默认是开启】的

    conn.setAutoCommit(false);

    ...创建stmt对象

    ...执行sql语句

    conn.commit();手动提交事务

    conn.rollback();回滚事务

    注意: 【conn.close();事务会自动提交】。

create table student(

id number primary key,

name varchar2(20) not null,

birthday date,

score number

);

同构:sql语句结构相同

插入100条数据

insert into student(id,name,birthday,score)

values(?,?,?,?);

PrepareStatement处理同构的sql语句

异构: 结构不同

insert into ;

delete;

update;

Statement来处理异构的sql语句。

//同构  ps执行原理

//1.构建ps对象的同时,先将sql语句发送到DB服务器

//2.将具体的值设置给ps

//3.ps执行,传递数据给DB服务器

//4.DB服务器接收数据,结合sql框架,完成功能

//5.返回数据给当前应用程序

//1.将sql语句发送到 DB数据库,

//2.DB数据库执行sql语句

//3.将结果返回给当前应用程序

18.同构和异构

    【异构】sql语句,结构不同的语句。

Statement语句执行,每次执行sql语句,都会把sql语句通过网络发送到服务器,然后让服务器实现功能。

    同构 【结构相同】的sql语句

insert into student(id,name,age,birthday)

values(x,y,z,m);

insert into student(id,name,age,birthday)

values(x,y,z,m);

    在实际使用时,可以提前将Sql语句发送给数据库进行【预编译】,然后每次只需要传输值即可,这样子可以提高效率。

String sql = "insert into student(id,name,age,birthday)

values(?,?,?,?)";

ps = conn.prepareStatement(sql);

ps.setInt(1,7);

ps.setString(2, "王五");

ps.setInt(3, 21);

注意,【将 util.Date转换为sql.Date】  通过时间戳值进行

java.util.Date utilDate = new java.util.Date();

ps.setDate(4, new java.sql.Date(utilDate.getTime()));

注意,ps执行sql语句时,没有必要也不能传sql语句,因为sql语句已经提前发送到服务器了

ps.execute();

create table student(

id number primary key,

name varchar2(20) not null,

birthday date,

score number

);

19.通过PrepareStatement进行其他操作

PrepareStatement可以预编译sql语句。

使用PrepareStatement语句进行增删改查。


使用PrepareStatement的好处,除了效率高,还有就是 【省去了字符串的拼接】。

在select时,将数据导入到Student对象中,然后添加到list集合中,最后统一遍历。

**************************

注意:如果同时在终端和代码里面操作sql语句,操作后一定要提交事务,否则会造成线程阻塞,代码一直运行不成功。

驱动注册的 4种方式

1.Class.forName();

2.OracleDriver od = new OracleDriver();

DriverManager.registerDriver(od);

3.系统配置

System.setProperty("jdbc.drivers","");

4.配置虚拟机运行时参数

-Djdbc.drivers=...;

数据连接的 2种方式

1.DriverManager.getConnection(url,user,passwd);

2.od.connect(url,info);

inof = new Properties();

事务的操作

终端  delete from student;(开启事务)

  commit;

源码  insert into ;(开启事务)

线程阻塞,由事务未提交引起的。

java.util.Date和java.sql.Date

sql下的Date 是 util的子类

时间戳 long值  毫秒

PrepareStatement和Statement

同构 异构

第二天课程

1.批处理测试

获取当前时间System.currentTimeMillis();

批处理:

    并不是逐条语句进行处理,而是时机成熟后,批量执行成功。

//添加到批处理

    stmt.addBatch(sql);

//执行批处理

    stmt.executeBatch();

模拟四种情况

    事务手动提交,不使用批处理,使用Statement

    事务手动提交,不使用批处理,PrepareStatement

    事务手动提交,使用批处理,Statement

    事务手动提交,使用批处理,PrepareStatement(实际应用最多,效果最明显)

    测试,不同方式插入上千条数据,计算实际使用时间。

    java.util.Date start = System.currentTimeMillis();

    java.util.Date end = System.currentTimeMillis();

syso("运行时间: "+(end-start));

2.Statement和PrepareStatement对比

            Statement  PrepareStatement

    sql在哪里创建      客户端 客户端

    sql代码存储到哪    客户端    服务器(预处理预编译)

    什么技术编写代码  sql语句  sql

    配置性       很高 第一次高,以后固定

    可移植性         高      高,数据库得支持预编译

    效率       低 高

客户端: 项目源码部分

服务器: 数据库服务器

student表

id  name  score  birthday

1 zs 78 09-9月-17

2 ls 78 09-9月-17

3.DatabaseMetaData数据库元对象

MetaData元数据,描述数据的数据。

    可以用来获得数据库的相关信息

    获得数据库对象(表、视图、索引)的相关信息

    获得数据库中列的信息

    获得RusultSet中包含的列信息

4.获得数据库相关信息

    metaData.getDatabaseProductName();

数据库名字

    metaData.getDatabaseProductName();

数据库版本详细信息

    metaData.getDatabaseProductName();

产品的主版本

    metaData.getDatabaseProductName();

产品的次版本

//获取数据库 里面  对象信息

ResultSet getTables(

String catalog, //null

String schema, //用户名

    String tableName,

String types[]) throws SQLException;

5.获得数据库中表相关信息

    catalog:

    schema:

    tableName: 表名

    types: 具体类型,表、视图、索引、同义词

    metaData.getTables(catalog,schema,tableName,types);

    catalog,schema:在SQL环境下这两个都属于抽象概念,用来解决命名冲突问题。

从概念上说,一个数据库系统包含多个Catalog,每个Catalog包含多个Schema,而每个Schema又包含多个数据库对象(表、视图、索引)。

也可以说一个数据库对象必然属于一个schema,而schema又属于一个catalog。

常用实现方式是使用【数据库名作为Catalog名】,使用【用户名作为Schema名】。

数据库 Catalog Schema

Oracle 不支持 用户名

MySql 不支持 数据库名

具体应用:

    rs = metaData.getTables(null,"TEST",null,new String[]{"TABLE"});

    while(rs.next()) {

String tName = rs.getString("TABLE_NAME");

String tType = rs.getString("TABLE_TYPE");

    }

通过数据字典可以实现相同功能:

select table_name from user_tables;

查询出来的BIN$开头的属于数据库回收站里面的残留信息。

purge recyclebin; 可以【清空回收站】

6.获取数据库中列信息

    metaData.getColumns(catalog,schema,tableName,columnName);

    rs = metaData.getColumns(null,"TEST","STUDENT",null);

    while(rs.next()){

String colName = rs.getString("COLUMN_NAME");

String colType = rs.getString("TYPE_NAME");

    }

7.获取ResultSet中包含的列信息

    包含多少列

    每列都是什么数据类型

    ResultSetMetaData metaData = rs.getMetaData();

    //获取列数

    int columnNum = metaData.getColumnCount();

    for(int i = 1;i <= columnNum;i++){

//获取每一列名称

syso(metaData.getColumnName(i));

//获取每一列类型

syso(metaData.getColumnTypeName(i));

    }

同构和异构

同构: sql语句结构相同

String sql = "?,?,?";

PrepareStatement ps = conn.prepareStatement(sql);

ps.setXXX(1,*);

ps.setXXX(2,*);

...

ps.execute();

异构: sql语句结构不同

Statement

引入: 驱动注册 4种  Class.forName();

new OracleDriver();

System.setProperty("jdbc.drivers",OracleDriver全包名);

-Djdbc.drivers=oracle.jdbc.driver.OracleDriver

数据库连接的两种方式

DriverManager.getConnection(url,user,password);

Driver dr = new ;

dr.connect(url,info);  info(user,password);

批处理

stmt|ps.addBatch();

...

stmt|ps.executeBatch();

结论: ps 和 批处理结合使用,会大大提高效率。

事务控制

conn.setAutoCommit(false);

conn.commit();

conn.rollback();

理解: 为什么封装,封装的好处,具体研发中,谁来进行封装。

程序员使用起来更简单

架构组的人员|业务组长|主要编程  公共代码

自己

8.封装jdbc操作过程

    a.创建一个工厂类,生成数据库连接对象

      将数据库连接四要素,放入配置文件

properties文件  xml文件两种情况

    b.封装关闭方法

    c.封装sql语句的执行

9.进一步封装

    在上述基础上,将具体的功能实现,封装到一个接口内部,用户在具体实现功能时,匿名内部类操作即可。

MyBatis 对JDBC的封装。

封装注意事项:

代码相同的,直接封装成公共代码

代码不同的,留给用户来实现

你可能感兴趣的:(JDBC)