• JDBC


    一、JDBC简介


    ### 1、JDBC基础
    * JDBC(Java Database Connectivity)是一个**独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API)**,定义了用来访问数据库的标准Java类库,使用这个类库可以以一种标准的方法、方便地访问数据库资源。
    • JDBC为访问不同的数据库提供了一种 统一的途径,为开发者屏蔽了一些细节问题。

    • JDBC的目标是使Java程序员 使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。

    JDBC提供了连接不同数据库的实现

    • JDBC接口(API)包括两个层次:

      • 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
      • 面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
    • JDBC驱动程序:各个数据库厂商根据JDBC的规范制作的 JDBC 实现类的类库

      • JDBC驱动程序总共有四种类型:
        第一类:JDBC-ODBC桥。
        第二类:部分本地API部分Java的驱动程序。
        第三类:JDBC网络纯Java驱动程序。
        第四类:本地协议的纯 Java 驱动程序。

    四两类都是纯Java的驱动程序,因此,对于Java开发者来说,它们在性能、可移植性、功能等方面都有优势。

    JDBC-ODBC

    部分本地API

    JDBC网络纯Java驱动程序

    本地协议的纯 Java 驱动程序

    • JDBC API 是一系列的接口,它使得应用程序能够进行数据库联接,执行SQL语句,并且得到返回结果。

    JDBC API

    二、JDBC应用


    ### 1、Driver接口
    • Java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现

    • 在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。

    • 加载和注册JDBC驱动

      • 加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名

      • DriverManager 类是驱动程序管理器类,负责管理驱动程序

      • 通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例。

    • 建立连接

      • 可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接
        JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。

      • JDBC URL的标准由三部分组成,各部分间用冒号分隔。

        • jdbc:<子协议>:<子名称>
        • 协议:JDBC URL中的协议总是jdbc
        • 子协议:子协议用于标识一个数据库驱动程序
        • 子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息
    • 几种常用的JDBC URL

    对于 Oracle 数据库连接,采用如下形式:
    jdbc:oracle:thin:@localhost:1521:sid
    对于 SQLServer 数据库连接,采用如下形式:
    jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid
    对于 MYSQL 数据库连接,采用如下形式:
    jdbc:mysql://localhost:3306/sid

    • 访问数据库

    数据库连接被用于向数据库服务器发送命令和 SQL 语句,在连接建立后,需要对数据库进行访问,执行 sql 语句
    在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
    -Statement
    -PrepatedStatement
    -CallableStatement

    1、Statement

    • 通过调用 Connection 对象createStatement 方法创建该对象
      该对象用于执行静态的 SQL 语句,并且返回执行结果

    • Statement 接口中定义了下列方法用于执行 SQL 语句:

    ResultSet excuteQuery(String sql)
    int excuteUpdate(String sql)

    2、ResultSet

    • 通过调用 Statement 对象的 excuteQuery() 方法创建该对象

    • ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商实现

    • ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行

    • ResultSet 接口的常用方法:

    boolean next()
    getString()

    3、数据类型转换

    数据类型转换

    ** 小结**

    java.sql.DriverManager用来装载驱动程序,获取数据库连接。
    java.sql.Connection完成对某一指定数据库的联接
    java.sql.Statement在一个给定的连接中作为SQL执行声明的容器,他包含了两个重要的子类型。
    Java.sql.PreparedSatement 用于执行预编译的sql声明
    Java.sql.CallableStatement用于执行数据库中存储过程的调用
    java.sql.ResultSet对于给定声明取得结果的途径

    三、JDBC深入


    ###1、SQL注入攻击
    • SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,从而利用系统的 SQL 引擎完成恶意行为的做法

    • 对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement 取代 Statement 就可以了

    2、PreparedStatement

    • 可以通过调用 Connection 对象preparedStatement() 方法获取 PreparedStatement 对象

    • PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句

    • PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXXX() 方法来设置这些参数. setXXX() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值

    • PreparedStatement 与Statement

    • PreparedStatement 能最大可能提高性能:
      DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
    • 在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.这样每执行一次都要对传入的语句编译一次。
      (语法检查,语义检查,翻译成二进制命令,缓存)
    • PreparedStatement 可以防止 SQL 注入 。

    3、使用JDBC驱动程序处理元数据

    • Java 通过JDBC获得连接以后,得到一个Connection 对象,可以从这个对象获得有关数据库管理系统的各种信息,包括数据库中的各个表,表中的各个列,数据类型,触发器,存储过程等各方面的信息。根据这些信息,JDBC可以访问一个实现事先并不了解的数据库。

    • 获取这些信息的方法都是在DatabaseMetaData类的对象上实现的,而DataBaseMetaData对象是在Connection对象上获得的。

    4、DateBaseMetaDate

    • DatabaseMetaData 类中提供了许多方法用于获得数据源的各种信息,通过这些方法可以非常详细的了解数据库的信息:
      • getURL():返回一个String类对象,代表数据库的URL。
      • getUserName():返回连接当前数据库管理系统的用户名。
      • isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
      • getDatabaseProductName():返回数据库的产品名称。
      • getDatabaseProductVersion():返回数据库的版本号。
      • getDriverName():返回驱动驱动程序的名称。
      • getDriverVersion():返回驱动程序的版本号。

    5、ResultMetaDate

    • 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象:
      • getColumnName(int column):获取指定列的名称
      • getColumnCount():返回当前 ResultSet 对象中的列数。
      • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
      • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
      • isNullable(int column):指示指定列中的值是否可以为 null。
      • isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。

    用例

    • 获取数据库自动生成的主键*
    Connection conn = JdbcUtil.getConnection();
    
    String sql = "insert into user(name,password,email,birthday) values('abc','123','abc@sina.com','1978-08-08')";
    
    PreparedStatement st = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS );
    
    st.executeUpdate();
    
    ResultSet rs = st.getGeneratedKeys();  //得到插入行的主键
    
    if(rs.next()){
    	System.out.println(rs.getObject(1));
    }
    

    ### 6、数据库事务
    • 在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态

    • 为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。

    • 事务的操作:先定义开始一个事务,然后对数据作修改操作,这时如果提交(COMMIT),这些修改就永久地保存下来,如果回退(ROLLBACK),数据库管理系统将放弃所作的所有修改而回到开始事务时的状态。

    • 事务的ACID(acid)属性

      • 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

      • 一致性(Consistency) 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。

      • 隔离性(Isolation) 事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

      • 持久性(Durability) 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。


    7、JDBC事务处理

    • 事务:指构成单个逻辑工作单元的操作集合

    • 事务处理:保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),要么整个事务回滚(rollback)到最初状态

    • 当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚

    • 为了让多个 SQL 语句作为一个事务执行:

      • 调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
      • 在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
      • 在出现异常时,调用 rollback(); 方法回滚事务
      • 若此时 Connection 没有被关闭, 则需要恢复其自动提交状态

    8、数据库的隔离级别

    • 对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:

      • 脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
      • 不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2** 更新**了该字段. 之后, T1再次读取同一个字段, 值就不同了.
      • 幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
    • 数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.

    • 一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱

    • 数据库的隔离级别

    数据库的四种隔离级别

    • Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. Oracle 默认的事务隔离级别为: READ COMMITED
    • Mysql 支持 4 中事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ
  • 相关阅读:
    ASP.NET Web API 2 之文件下载
    Windows 查看某个端口号是否被占用
    C# 数据类型之 String(字符串)
    数据表对应关系(一对一、一对多、多对多)
    嫁给程序员的好处,你get到了吗?
    ASP.NET Web API 2 之 HttpRequestMessage 对象
    C# 使用 log4net 记录日志
    Chrome 浏览器快捷键
    C# 获取程序运行时路径
    SpringBoot整合Pagehelper分页插件
  • 原文地址:https://www.cnblogs.com/jianshu/p/6023098.html
Copyright © 2020-2023  润新知