第八章 JDBC的简介

8.1 简介

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

Java 具有坚固、安全、易于使用、易于理解和可从网络上自动下载等特性,是编写数据库应用程序的杰出语言。所需要的只是 Java应用程序与各种不同数据库之间进行对话的方法。

JDBC可以在各个平台上使用JAVA,如Windows,Mac OS 和各种版本的UNIX

JDBC库包括通常与数据库使用相关的下面提到的每个任务API

  • 连接数据库
  • 创建SQL语句或MySQL语句
  • 在数据库中执行SQL语句或者MySQL查询
  • 查看和修改生成的记录

8.2 JDBC体系结构

JDBC API 支持用于数据库访问的两层和三层处理模型,但通常,JDBC体系结构由两层组成:

  • JDBC API:提供应用程序到JDBC管理器连接。

  • JDBC Driver API:支持JDBC管理器到驱动程序连接

    JDBC API使用驱动程序管理器和特定于数据库的驱动程序来提供与异构数据库的透明连接。


8.3 JDBC的核心组件

JDBC API提供了以下接口和类:

  • DriverManager: 这个类管理数据库驱动程序的列表。确定内容是否符合从Java应用程序使用的通信子协议正确的数据库驱动程序的连接请求。识别JDBC在一定子协议的第一个驱动器将被用来建立数据库连接。
  • Driver: 此接口处理与数据库服务器通信。很少直接直接使用驱动程序(Driver)对象,一般使用DriverManager中的对象,它用于管理此类型的对象。它也抽象与驱动程序对象工作相关的详细信息
  • Connection : 此接口与接触数据库的所有方法。连接对象表示通信上下文,即,与数据库中的所有的通信是通过此唯一的连接对象。
  • Statement : 可以使用这个接口创建的对象的SQL语句提交到数据库。一些派生的接口接受除执行存储过程的参数。
  • ResultSet: 这些对象保存从数据库后,执行使用Statement对象的SQL查询中检索数据。它作为一个迭代器,可以通过移动它来检索下一个数据。
  • SQLException: 这个类用于处理发生在数据库应用程序中的任何错误。

第九章 JDBC相关的SQL语法

9.1 CRUD语法介绍

SQL 是一种标准化的语言,它允许你在数据库上执行操作,如创建项目,查询内容,更新内容,并删除条目等操作。

Create, Read, Update, and Delete 通常称为CRUD操作。

CREATE DATABASE语句用于创建新的数据库:

SQL> CREATE DATABASE DATABASE_NAME;

DROP DATABASE语句用于删除现有数据库:

SQL> DROP DATABASE DATABASE_NAME;1

CREATE TABLE语句用于创建新表。语法是 -

SQL> CREATE TABLE Employees(id INT NOT NULL,   age INT NOT NULL,first VARCHAR(255),last VARCHAR(255),   PRIMARY KEY ( id ));

DROP TABLE语句用于删除现有表。

SQL> DROP TABLE table_name;

INSERT的语法类似于以下内容,其中column1,column2等表示要显示在相应列中的新数据

SQL> INSERT INTO table_name VALUES (column1, column2, ...);

SELECT语句用于从数据库中检索数据。SELECT的语法是 -

SQL> SELECT column_name, column_name, ...FROM table_nameWHERE conditions;123

WHERE子句可以使用比较运算符,例如=,!=,,<=和> =,以及BETWEEN和LIKE运算符。

UPDATE语句用于更新数据。

SQL> UPDATE table_nameSET column_name = value, column_name = value, ...WHERE conditions;123

WHERE子句可以使用比较运算符,例如=,!=,,<=和> =,以及BETWEEN和LIKE运算符。

DELETE语句用于从表中删除数据。

SQL> DELETE FROM table_name WHERE conditions;1

WHERE子句可以使用比较运算符,例如=,!=,,<=和> =,以及BETWEEN和LIKE运算符。

第十章 JDBC初始

10.1 使用步骤

构建JDBC应用程序涉及以下六个步骤:

**导入JDBC驱动包:**需要下载包含数据库编程所需的JDBC的jar包。

  • **注册JDBC驱动程序:**要求您初始化驱动程序,以便您可以打开与数据库的通信通道。
  • **创建连接:**需要使用*DriverManager.getConnection()*方法创建一个Connection对象,该对象表示与数据库的物理连接。
  • **执行查询:**需要使用类型为Statement的对象来构建和提交SQL语句到数据库。
  • **从结果集中提取数据:**需要使用相应的*ResultSet.getXXX()*方法从结果集中检索数据。
  • **释放资源:**需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。

(1)导入jar包,在项目下创建lib目录,把mysql的jdbc包放入此目录,并添加到build path中(idea不同)。

[jar 包]:

(2)注册驱动

第一种方式(推荐写法):Class.forName()

注册驱动程序最常见的方法是使用Java的**Class.forName()**方法,将驱动程序的类文件动态加载到内存中,并将其自动注册

//2注册驱动try {   Class.forName("com.mysql.jdbc.Driver");  Class.forName("com.mysql.cj.jdbc.Driver");//JDBC8.0版本之后使用}catch(ClassNotFoundException ex) {   System.out.println("Error: unable to load driver class!");   System.exit(1);}

第二种方式:是使用静态**DriverManager.registerDriver()**方法。

//2注册驱动try {   Driver myDriver = new com.mysql.jdbc.Driver();   DriverManager.registerDriver( myDriver );}catch(ClassNotFoundException ex) {   System.out.println("Error: unable to load driver class!");   System.exit(1);}

 * 1>驱动程序注册两次 * 2>java程序依赖mysql驱动包

(3)获取连接

3.1数据库URL配置

加载驱动程序后,可以使用**DriverManager.getConnection()**方法建立连接。为了方便参考,让我列出三个重载的DriverManager.getConnection()方法 -

  • getConnection(String url)
  • getConnection(String url,Properties prop)
  • getConnection(String url,String user,String password)
RDBMS JDBC驱动程序名称 连接字符串格式
MySQL的 com.mysql.jdbc.Driver **jdbc:mysql://**hostname:3306 / databaseName
ORACLE oracle.jdbc.driver.OracleDriver jdbc:oracle:thin:@ hostname:port Number:databaseName
DB2 COM.ibm.db2.jdbc.net.DB2Driver **jdbc:db2:**hostname:port Number / databaseName
SYBASE com.sybase.jdbc.SybDriver jdbc:sybase:Tds: hostname:port Number / databaseName

MySql8.0版本后进行了一些更新

JDBC驱动名称更新为com.mysql.cj.jdbc.Driver

连接字符串格式更新为jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT

3.2 创建数据库连接对象

//3使用DriverManager打开连接//3.1url  连接字符串 jdbc://localhost:3306 /数据库名  String URL = "jdbc:mysql://localhost:3306/emp";String USER = "root";String PASS = "root"Connection conn = DriverManager.getConnection(URL, USER, PASS);
/** *此处以我使用的版本进行演示 * driverclass--com.mysql.cj.jdbc.Driver * url--jdbc:jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT */

String URL = "jdbc:jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT";String USER = "数据库用户名";String PASS = "数据库密码";Connection conn = DriverManager.getConnection(URL, USER, PASS);

(4)执行查询(暂不执行,下一章内容)

(5)处理结果(暂不处理,下一章内容)

(6)关闭数据库连接

为确保连接关闭,您可以在代码中提供一个“finally”块。finally块总是执行,不管是否发生异常。

要关闭上面打开的连接,你应该调用close()方法如下 -

conn.close();

第十一章 JDBC执行SQL语句

一旦获得了连接,我们可以与数据库进行交互。JDBC Statement和PreparedStatement接口定义了能够发送SQL命令并从数据库接收数据的方法和属性。

接口 使用
Statement 用于对数据库进行通用访问。在运行时使用静态SQL语句时很有用。Statement接口不能接受参数。
PreparedStatement(推荐使用) 当您计划多次使用SQL语句时使用。PreparedStatement接口在运行时接受输入参数。

11.1Statement

创建语句对象

在使用Statement对象执行SQL语句之前,需要使用Connection对象的createStatement()方法创建一个,如下例所示:

Statement stmt = null;try {   stmt = conn.createStatement( );   . . .}catch (SQLException e) {   . . .}finally {   . . .}

创建Statement对象后,可以使用它来执行一个SQL语句,其中有三个常用执行方法:

  • boolean execute(String SQL):如果可以检索到ResultSet对象,则返回一个布尔值true; 否则返回false。使用此方法执行SQL DDL语句或需要使用真正的动态SQL时。
  • int executeUpdate(String SQL):返回受SQL语句执行影响的行数。使用此方法执行预期会影响多个行的SQL语句,例如INSERT,UPDATE或DELETE语句。
  • ResultSet executeQuery(String SQL):返回一个ResultSet对象。当需要获得结果集时,请使用此方法,就像使用SELECT语句一样。

关闭Statement对象

就像我们关闭一个Connection对象以保存数据库资源一样,由于同样的原因,还应该关闭Statement对象。

一个简单的调用close()方法将执行该作业。如果先关闭Connection对象,它也会关闭Statement对象。但是,应始终显式关闭Statement对象,以确保正确清理。

Statement stmt = null;try {   stmt = conn.createStatement( );   . . .}catch (SQLException e) {   . . .}finally {   stmt.close();}

11.2SQL注入

就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。

11.3PreparedStatement

PreparedStatement的接口扩展了Statement接口,它提供了一个通用的Statement对象,并且提供了两个附加功能:1.预编译,效率高 2 .安全,避免SQL注入

此语句可以动态地提供参数。

PreparedStatement pstmt = null;try {   String SQL = "Update Employees SET age = ? WHERE id = ?";//3创建命令 //?表示占位符,执行时?会替换为实际数据 预编译   pstmt = conn.prepareStatement(SQL);

   . . .}catch (SQLException e) {   . . .}finally {   . . .}

JDBC中的所有参数都由【?】符号,这被称为参数标记。在执行SQL语句之前,必须为每个参数提供值。

所述的setXXX()**方法将值绑定到所述参数,其中**XXX代表要绑定到输入参数的值的Java数据类型。如果忘记提供值,将收到一个SQLException。

每个参数标记由其顺序位置引用。第一个标记表示位置1,下一个位置2等等。该方法与Java数组索引不同,从0开始。

关闭PreparedStatement对象

就像关闭Statement对象一样,由于同样的原因,还应该关闭PreparedStatement对象。

一个简单的调用close()方法将执行该作业。如果先关闭Connection对象,它也会关闭PreparedStatement对象。但是,应始终显式关闭PreparedStatement对象,以确保正确清理。

PreparedStatement pstmt = null;try {   String SQL = "Update Employees SET age = ? WHERE id = ?";   pstmt = conn.prepareStatement(SQL);   . . .}catch (SQLException e) {   . . .}finally {   pstmt.close();}

11.4 ResultSet

SELECT语句是从数据库中选择行并在结果集中查看行的标准方法。该java.sql.ResultSet中的接口表示结果集数据库查询。

ResultSet对象维护指向结果集中当前行的游标。术语“结果集”是指包含在ResultSet对象中的行和列数据。我们应该知道在cmd或者图形化界面下执行查询语句返回的是一个二维的数据表格。那么如果JDBC需要拿到查询结果数据,就必须遍历表格。JDBC给执行查询结果指定了一个返回结果集的类型ResultSet ,在ResultSet中有一个指向行的光标。光标默认的起始位置不是从实际数据开始,而是从表格的表头开始。我们可以通过结果集对象的next()方法进行行遍历,通过结果集对象的getString(i)【此处i表示具体的列数】或getString(“列名”)方法进行列遍历,从而获得查询结果集的具体内容。

ResultSet 对象具有指向其当前数据行的指针。最初,指针被置于第一行之前。指针可以方便我们对结果集进行遍历。默认的 ResultSet 对象不可更新,仅有一个向前移动的指针。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。

如果没有指定任何ResultSet类型,将自动获得一个TYPE_FORWARD_ONLY。

类型 描述
ResultSet.TYPE_FORWARD_ONLY 光标只能在结果集中向前移动。
ResultSet.TYPE_SCROLL_INSENSITIVE 光标可以向前和向后滚动,结果集对创建结果集后发生的数据库的其他更改不敏感。
ResultSet.TYPE_SCROLL_SENSITIVE。 光标可以向前和向后滚动,结果集对创建结果集之后发生的其他数据库所做的更改敏感。

第十二章 JDBC批处理

Statement接口可以简单实现在Java编译器中处理单条SQL语句,但也会造成恶意表单注入。PrepareStatement接口解决了Statement恶意表单注入的安全问题,并且扩展了Statement接口的功能,实现了SQL语句预编译的效果,但是仍然只能一次处理单条SQL语句,但实际操作中会遇到大量SQL语句执行的情况,此时单条语句进行注入就无法满足需求,于是出现了批处理技术:

批量处理允许将相关的SQL语句分组到批处理中,并通过对数据库的一次调用提交它们。

当需要一次向数据库发送多个SQL语句时,可以减少连接数据库的开销,从而提高性能。

12.1Statement批处理

以下是使用语句对象的批处理的典型步骤(步骤3和步骤5在数据库事务处会进行详细介绍)

  • 1 注册驱动获取连接
  • 2 使用createStatement ()方法创建Statement对象。
  • 3 使用setAutoCommit ()将auto-commit设置为false 。(可选)
  • 4 使用addBatch ()方法在创建的语句对象上添加可能使用的SQL语句到批处理中。
  • 5 在创建的语句对象上使用executeBatch ()方法执行所有SQL语句。
  • 6 使用commit ()方法提交所有更改。(可选)
  • 7 释放资源
// 3创建命令 Create statement objectStatement stmt = conn.createStatement();// 4 执行// 4.1设置事务 Set auto-commit to falseconn.setAutoCommit(false);

// Create SQL statementString SQL = "INSERT INTO Employees (id, first, last, age) VALUES(200,'Zia', 'Ali', 30)";// Add above SQL statement in the batch.stmt.addBatch(SQL);

// Create one more SQL statementString SQL = "INSERT INTO Employees (id, first, last, age) VALUES(201,'Raj', 'Kumar', 35)";// Add above SQL statement in the batch.stmt.addBatch(SQL);

// Create one more SQL statementString SQL = "UPDATE Employees SET age = 35 WHERE id = 100";// Add above SQL statement in the batch.stmt.addBatch(SQL);

// 执行一下 Create an int[] to hold returned valuesint[] count = stmt.executeBatch();

//4.2 提交事务 Explicitly commit statements to apply changesconn.commit();

12.2PrepareStatement批处理

以下是使用语句对象的批处理的典型步骤(步骤4和步骤7在数据库事务处会进行详细介绍)

  • 1 注册驱动获取连接
  • 2 使用占位符创建SQL语句。
  • 3 使用prepareStatement ()方法创建PrepareStatement对象。
  • 4 使用setAutoCommit ()将auto-commit设置为false 。(可选)
  • 5 使用addBatch ()方法在创建的语句对象上添加可能使用的SQL语句到批处理中。
  • 6 在创建的语句对象上使用executeBatch ()方法执行所有SQL语句。
  • 7 最后,使用commit ()方法提交所有更改。(可选)
  • 8 释放资源
// Create SQL statementString SQL = "INSERT INTO Employees (id, first, last, age) VALUES(?, ?, ?, ?)";

// Create PrepareStatement objectPreparedStatemen pstmt = conn.prepareStatement(SQL);

//Set auto-commit to falseconn.setAutoCommit(false);

// 4给pstmt设置参数 Set the variables pstmt.setInt( 1, 400 );pstmt.setString( 2, "Pappu" );pstmt.setString( 3, "Singh" );pstmt.setInt( 4, 33 );//放入批处理 Add it to the batchpstmt.addBatch();

// Set the variablespstmt.setInt( 1, 401 );pstmt.setString( 2, "Pawan" );pstmt.setString( 3, "Singh" );pstmt.setInt( 4, 31 );// Add it to the batchpstmt.addBatch();

//add more batches

//执行批处理Create an int[] to hold returned valuesint[] count = stmt.executeBatch();//清空批处理pstat.clearBatch//Explicitly commit statements to apply changesconn.commit();

12.3 Statment批处理和PrepareStatment批处理区别:

<1>Statment批处理可以添加不同Sql语句,而PrepareStatment只能添加一种sql语句 <2>PrepareStatment效率比Statment高,而且更安全。

第十三章 JDBC操作二进制数据

PreparedStatement对象可以使用输入和输出流来提供参数数据。这使您可以将整个文件放入可以保存大值的数据库列,例如Text和BLOB数据类型。

有以下方法可用于流式传输数据 -

  • setAsciiStream():此方法用于提供大的ASCII值。
  • setCharacterStream():此方法用于提供大型UNICODE值。
  • setBinaryStream():此方法用于提供较大的二进制值。

setXXXStream()方法除了参数占位符之外还需要额外的参数,文件大小。

考虑我们要将XML文件XML_Data.xml上传到数据库表中。这是XML文件的内容 -

案例:将文件放入数据库
<?xml version="1.0" encoding="UTF-8"?><Employee><id>100id><first>张first><last>无极last><Salary>10000Salary><Dob>18-08-1978Dob>Employee>
//Import required packagesimport java.sql.*;import java.io.*;import java.util.*;

public class JDBCExample {// JDBC driver name and database URLstatic final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";  static final String DB_URL = "jdbc:jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT";

//  Database credentialsstatic final String USER = "username";static final String PASS = "password";

public static void main(String[] args) {   Connection conn = null;   PreparedStatement pstmt = null;   Statement stmt = null;   ResultSet rs = null;try{//1 注册驱动  Register JDBC driver     Class.forName("com.mysql.cj.jdbc.Driver");// Open a connection      System.out.println("Connecting to database...");//2 获取连接      conn = DriverManager.getConnection(DB_URL,USER,PASS);

//3 创建命令对象Create a Statement object and build table      stmt = conn.createStatement();      createXMLTable(stmt);//4 添加数据//Open a FileInputStream      File f = new File("XML_Data.xml");long fileLength = f.length();      FileInputStream fis = new FileInputStream(f);

//Create PreparedStatement and stream data      String SQL = "INSERT INTO XML_Data VALUES (?,?)";      pstmt = conn.prepareStatement(SQL);      pstmt.setInt(1,100);      pstmt.setAsciiStream(2,fis,(int)fileLength);      pstmt.execute();

//Close input stream      fis.close();//5 读取数据// Do a query to get the row      SQL = "SELECT Data FROM XML_Data WHERE id=100";      rs = stmt.executeQuery (SQL);// Get the first rowif (rs.next ()){//Retrieve data from input stream         InputStream xmlInputStream = rs.getAsciiStream (1);int c;//读取流         ByteArrayOutputStream bos = new ByteArrayOutputStream();while (( c = xmlInputStream.read ()) != -1)            bos.write(c);//Print results         System.out.println(bos.toString());      }// Clean-up environment      rs.close();      stmt.close();      pstmt.close();      conn.close();   }catch(SQLException se){//Handle errors for JDBC      se.printStackTrace();   }catch(Exception e){//Handle errors for Class.forName      e.printStackTrace();   }finally{//finally block used to close resourcestry{if(stmt!=null)            stmt.close();      }catch(SQLException se2){      }// nothing we can dotry{if(pstmt!=null)            pstmt.close();      }catch(SQLException se2){      }// nothing we can dotry{if(conn!=null)            conn.close();      }catch(SQLException se){         se.printStackTrace();      }//end finally try   }//end try   System.out.println("Goodbye!");}//end main

public static void createXMLTable(Statement stmt) throws SQLException{   System.out.println("Creating XML_Data table..." );//Create SQL Statement   String streamingDataSql = "CREATE TABLE XML_Data " +"(id INTEGER, Data TEXT)";//Drop table first if it exists.try{      stmt.executeUpdate("DROP TABLE IF EXISTS XML_Data");//Build table.       stmt.executeUpdate(streamingDataSql);   }catch(SQLException se){   }// do nothing

}//end createXMLTable}//end JDBCExample
案例:把图片放入数据库
/** * 把图片放入数据库 * @author wgy * */public class Demo4 {public static void main(String[] args) throws Exception{//write();       read();   }public static void write() throws Exception{       Class.forName("com.mysql.cj.jdbc.Driver");      String url="jdbc:jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT";      Connection conn=DriverManager.getConnection(url, "root", "root");        PreparedStatement pstat=conn.prepareStatement("insert into bigdata2(id,img) values(?,?)");     FileInputStream fis=new FileInputStream("图片所在路径");     pstat.setInt(1, 1);       pstat.setBinaryStream(2, fis);int count=pstat.executeUpdate();     System.out.println(count);        pstat.close();        conn.close(); }public static void read() throws Exception{        Class.forName("com.mysql.cj.jdbc.Driver");      String url="jdbc:jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT";      Connection conn=DriverManager.getConnection(url, "用户名", "密码");       PreparedStatement pstat=conn.prepareStatement("select * from bigdata2 where id=1");

     ResultSet rs=pstat.executeQuery();if(rs.next()) {int id=rs.getInt("id");          System.out.println(id);//处理图片           InputStream is=rs.getBinaryStream("img");          FileOutputStream fos=new FileOutputStream("存储图片的路径");byte[] buf=new byte[1024];int len=0;while((len=is.read(buf))!=-1) {             fos.write(buf,0,len);         }         fos.close();          is.close();

     }     rs.close();       pstat.close();        conn.close();     System.out.println("读取完成"); }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051

第十四章 数据库事务

一组要么同时执行成功,要么同时失败的SQL语句。是数据库操作的一个不能分割执行单元。

14.1事务概述

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

事务开始于

  • 连接到数据库上,并执行一条DML语句insert、update或delete
  • 前一个事务结束后,又输入了另一条DML语句

事务结束于

  • 执行commit或rollback语句。
  • 执行一条DDL语句,例如create table语句,在这种情况下,会自动执行commit语句。
  • 执行一条DDL语句,例如grant语句,在这种情况下,会自动执行commit。
  • 断开与数据库的连接
  • 执行了一条DML语句,该语句却失败了,在这种情况中,会为这个无效的DML语句执行rollback语句。

14.2 事务的四大特点

(ACID)

  • Atomicity(原子性)

表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败

  • Consistency(一致性)

表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态

  • Isolation(隔离性)

事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。

  • Durability(持久性)

持久性事务完成之后,它对于系统的影响是永久性的。

案例演示
CREATE TABLE account(id INT PRIMARY KEY,NAME VARCHAR(20) NOT NULL,  money DOUBLE(10,2))
public static void main(String[] args) {       Connection connection=null;      PreparedStatement pstat1=null;       PreparedStatement pstat2=null;

//1注册驱动try {         Class.forName("com.mysql.cj.jdbc.Driver");//2获取连接         connection=DriverManager.getConnection("jdbc:jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT");//3创建命令//3.1开启事务 ,设置事务自动提交为false          connection.setAutoCommit(false);          pstat1=connection.prepareStatement("update account set money=money-1000 where name='张莎强'");            pstat1.executeUpdate();//int c=10/0;           pstat2=connection.prepareStatement("update account set money=money+1000 where name='小苍'");            pstat2.executeUpdate();

         System.out.println("转账成功...");//3.2提交事务           connection.commit();

        } catch (Exception e) {           System.out.println("出现异常");try {              connection.rollback();//出现问题,要回滚(撤销事务做过的修改)                connection.commit();//可加也不不加          } catch (SQLException e1) {// TODO Auto-generated catch block               e1.printStackTrace();         }     }finally {if(pstat1!=null){try {                 pstat1.close();               } catch (SQLException e) {// TODO Auto-generated catch block                    e.printStackTrace();              }         }if(pstat2!=null){try {                  pstat2.close();               } catch (SQLException e) {// TODO Auto-generated catch block                    e.printStackTrace();              }         }if(connection!=null){try {                  connection.close();               } catch (SQLException e) {// TODO Auto-generated catch block                    e.printStackTrace();              }         }     } }
Mysql支持的事务语句
#开启事务START TRANSACTION;     # connection.setAutoCommit(false);UPDATE account SET money=money-1000 WHERE id=1;UPDATE account SET money=money+1000 WHERE id=2;#提交事务COMMIT;#connection.commit();#回滚ROLLBACK; #connection.rollback();

14.3事务隔离级别

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

Read Uncommitted(读取未提交内容)

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

Read Committed(读取提交内容)

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别出现不可重复读(Nonrepeatable Read)问题,因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

**Repeatable Read **可重读

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻读” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable 可串行化 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。效率最低的。

这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。

例如:

脏读(Drity Read):某个事务已更新一份数据未提交前,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

演示案例:

# 修改事务的隔离级别:SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]# 查看事务隔离级别SELECT @@tx_isolation;# 5.7.20版本后使用此语句查询SELECT @@transaction_isolation;

不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

演示案例:

# A方 买家 本伟SELECT @@transaction_isolation;START TRANSACTION;UPDATE account SET money=money-2000 WHERE id=1;UPDATE account SET money=money+2000 WHERE id=2;COMMIT;ROLLBACK;

START TRANSACTION;UPDATE account SET money=money+1000 WHERE id=2;COMMIT;

# B方  卖家  郑帅#(修改隔离级别)SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;#查看隔离级别SELECT @@transaction_isolation;SELECT *FROM account;#发货#修改隔离级别SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT *FROM account;

#不可重复读

START TRANSACTION;SELECT SUM(money) FROM account;SELECT SUM(money) FROM account;SELECT SUM(money) FROM account;COMMIT; 

#再次修改隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

START TRANSACTION;SELECT SUM(money) FROM account;SELECT SUM(money) FROM account;SELECT SUM(money) FROM account;COMMIT;   

幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。但是InnoDB存储引擎通过多版本并发控制机制解决了该问题。

14.4 JDBC中事务应用

JDBC连接默认处于自动提交模式,则每个SQL语句在完成后都会提交到数据库。

事务使您能够控制是否和何时更改应用于数据库。它将单个SQL语句或一组SQL语句视为一个逻辑单元,如果任何语句失败,则整个事务将失败。

要启用手动事务支持,而不是JDBC驱动程序默认使用的自动提交模式,请使用Connection对象的setAutoCommit()方法。如果将boolean false传递给setAutoCommit(),则关闭自动提交。我们可以传递一个布尔值true来重新打开它。

(1) 事务的提交和回滚

完成更改后,我们要提交更改,然后在连接对象上调用**commit()**方法,如下所示:

conn.commit( );1

否则,要使用连接名为conn的数据库回滚更新,请使用以下代码 -

conn.rollback( );1try{//开启事务   conn.setAutoCommit(false);   Statement stmt = conn.createStatement();

   String SQL = "INSERT INTO Employees VALUES (106, 20, 'Rita', 'Tez')";   stmt.executeUpdate(SQL);  //有可能出现异常   String SQL = "INSERT IN Employees VALUES (107, 22, 'Sita', 'Singh')";   stmt.executeUpdate(SQL);// 没有错误提交   conn.commit();}catch(SQLException se){//出现错误回滚   conn.rollback();   conn.commit();}1234567891011121314151617

(2) Savepoint

新的JDBC 3.0 Savepoint接口为您提供了额外的事务控制。

设置保存点时,可以在事务中定义逻辑回滚点。如果通过保存点发生错误,则可以使用回滚方法来撤消所有更改或仅保存在保存点之后所做的更改。

Connection对象有两种新的方法来帮助管理保存点 -

  • setSavepoint(String savepointName):定义新的保存点。它还返回一个Savepoint对象。
  • releaseSavepoint(Savepoint savepointName):删除保存点。请注意,它需要一个Savepoint对象作为参数。此对象通常是由setSavepoint()方法生成的保存点。
public static void main(String[] args) {     Connection conn = null;      Statement stmt = null;       Savepoint savepoint1 = null;try {          Class.forName("com.mysql.cj.jdbc.Driver");          conn = DriverManager.getConnection("jdbc:jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT", "用户名", "密码");// Assume a valid connection object conn          conn.setAutoCommit(false);            stmt = conn.createStatement();

// set a Savepoint         String SQL = "INSERT INTO Employees VALUES (106, 20, 'Rita', 'Tez');";         stmt.executeUpdate(SQL);          savepoint1 = conn.setSavepoint("Savepoint1");// Submit a malformed SQL statement that breaks         SQL = "INSERT IN Employees VALUES (107, 22, 'Sita', 'Tez')";           stmt.executeUpdate(SQL);// If there is no error, commit the changes.            conn.commit();            System.out.println("执行成功");

       } catch (Exception se) {// If there is any error.try {                se.printStackTrace();             conn.rollback(savepoint1);                conn.commit();                System.out.println("回滚");           } catch (SQLException e) {// TODO Auto-generated catch block                e.printStackTrace();          }     } }

DAO模式、连接池和DBUtils应用

第十五章 工具类封装、DAO模式和自定义连接池

1.1 工具类封装

案例实现:实现emp表的查询、添加、删除、修改

1.1.1 封装DbUtils

由于多个地方都需要使用数据库连接和释放,所以把功能封装到工具类中DbUtils

四个功能:1注册驱动 2 获取连接 3 释放资源 4 执行命令 【5 执行查询】

public class DbUtils {private static String driver;private static String url;private static String user;private static String password;

static{

try {                      driver="com.mysql.jdbc.Driver";             url="jdbc:mysql://localhost:3306/school";              user="root";               password="root";//加载驱动          Class.forName(driver);

      } catch (Exception e) {// TODO Auto-generated catch block           e.printStackTrace();      } }/**     * 获取连接    * @return    * @throws SQLException   */public static Connection getConnection() throws SQLException{return DriverManager.getConnection(url,user,password);    }

/**   * 释放资源    * @param rs  * @param stat    * @param conn    */public static void release(ResultSet rs,Statement stat,Connection conn){if(rs!=null){try {              rs.close();           } catch (SQLException e) {// TODO Auto-generated catch block                e.printStackTrace();          }     }if(stat!=null){try {                stat.close();         } catch (SQLException e) {// TODO Auto-generated catch block                e.printStackTrace();          }     }if(conn!=null){try {                conn.close();         } catch (SQLException e) {// TODO Auto-generated catch block                e.printStackTrace();          }     } }

/**   * 根据参数执行sql语句  Insert Delete Update   * @param sql     * @param params  * @return    */public static int executeUpdate(String sql, Object...params){        Connection conn=null;        PreparedStatement pstat=null;try {//1创建连接            conn=getConnection();//2创建命令对象         pstat=conn.prepareStatement(sql);//3设置参数for (int i = 0; i < params.length; i++) {              pstat.setObject(i+1, params[i]);         }//4执行int result=pstat.executeUpdate();return result;

        } catch (Exception e) {throw new RuntimeException(e);       }finally {            release(null, pstat, conn);       } }

}

1.1.2优化DbUtils工具类:把数据库连接信息封装到Properties文件中

           Properties properties=new Properties();          InputStream is=DbUtils.class.getClassLoader().getResourceAsStream("database.properties");          properties.load(is);//初始化参数         driver=properties.getProperty("driver");           url=properties.getProperty("url");         user=properties.getProperty("user");           password=properties.getProperty("password");
1.2 DAO设计模式

DAO(Database Access Object 数据库访问对象)

为了降低耦合性,提出了DAO封装数据库操作的设计模式。

它可以实现业务逻辑与数据库访问相分离。相对来说,数据库是比较稳定的,其中DAO组件依赖于数据库系统,提供数据库访问的接口,隔离了不同的数据库实现。

DAO模式的组成部分

1 DAO接口(主要包 添加 修改 查询 删除方法)

2 DAO实现类

3 实体类 (domain、beans、entity、pojo、model)

PO (VO)(Persistent Object, Value Object)

VO (View Object)

DTO (Data Transfer Object)

--作用:用在数据访问代码和业务逻辑代码之间通过实体类来传输数据

--实体类特征:

◦属性一般使用private修饰

◦提供public修饰的getter/setter方法

◦实体类提供无参构造方法,根据业务提供有参构造

◦实现java.io.Serializable接口,支持序列化机制

4 数据库连接和关闭工具类

设计的包名 :

domain 存放实体类

utils 存放工具类

dao 存放接口

dao.impl 存放实现类

使用DAO设计模式实现emp表的查询、添加、删除、修改

Employee类

/** * 员工类 * 实体类 * */public class Employee implements Serializable {/**  *     */private static final long serialVersionUID = 373910607014836778L;private int empno;private String ename;private String job;private int mgr;private Date hiredate;private double sal;private double comm;private int deptno;

public Employee() {// TODO Auto-generated constructor stub }

public Employee(int empno, String ename, String job, int mgr, Date hiredate, double sal, double comm, int deptno) {super();this.empno = empno;this.ename = ename;this.job = job;this.mgr = mgr;this.hiredate = hiredate;this.sal = sal;this.comm = comm;this.deptno = deptno;  }

public int getEmpno() {return empno;   }

public void setEmpno(int empno) {this.empno = empno;  }

public String getEname() {return ename;    }

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

public String getJob() {return job;    }

public void setJob(String job) {this.job = job;   }

public int getMgr() {return mgr;   }

public void setMgr(int mgr) {this.mgr = mgr;  }

public Date getHiredate() {return hiredate;    }

public void setHiredate(Date hiredate) {this.hiredate = hiredate; }

public double getSal() {return sal;    }

public void setSal(double sal) {this.sal = sal;   }

public double getComm() {return comm;  }

public void setComm(double comm) {this.comm = comm;   }

public int getDeptno() {return deptno; }

public void setDeptno(int deptno) {this.deptno = deptno;  }

@Overridepublic String toString() {return "Employee [empno=" + empno + ", ename=" + ename + ", job=" + job + ", mgr=" + mgr + ", hiredate="              + hiredate + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + "]";   }

}

接口:

public interface EmployeeDao {

//1查询ListfindAll();//2更新void update(Employee e);//3删除void delete(int empno);//4添加void add(Employee e);   }1234567891011

实现类

public class EmployeeDaoImpl implements EmployeeDao{

@Overridepublic ListfindAll() {

        ArrayList employees=new ArrayList();//1获取连接      Connection conn=null;        PreparedStatement pstat=null;        ResultSet rs=null;try {          conn=DbUtils.getConnection();            pstat=conn.prepareStatement("select * from emp;");         rs=pstat.executeQuery();while(rs.next()){int empno=rs.getInt("empno");                String ename=rs.getString("ename");                String job=rs.getString("job");int mgr=rs.getInt("mgr");                Date date=rs.getDate("hiredate");double sal=rs.getDouble("sal");double comm=rs.getDouble("comm");int deptno=rs.getInt("deptno");              Employee employee=new Employee(empno, ename, job, mgr, date, sal, comm, deptno);             employees.add(employee);          }return employees;        } catch (Exception e) {throw new RuntimeException("查询emp失败");       } finally {           DbUtils.closeAll(rs, pstat, conn);        } }@Overridepublic void update(Employee e) {       Object[] params={e.getEname(),e.getJob(),e.getMgr(),e.getHiredate(),e.getSal(),e.getComm(),e.getDeptno(),e.getEmpno()};      DbUtils.executeUpdate("update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno=?", params); }@Overridepublic void delete(int empno) {        DbUtils.executeUpdate("delete from emp where empno=?", empno); }@Overridepublic void add(Employee e) {      Object[] params={e.getEmpno(),e.getEname(),e.getJob(),e.getMgr(),e.getHiredate(),e.getSal(),e.getComm(),e.getDeptno()};      DbUtils.executeUpdate("insert into emp values(?,?,?,?,?,?,?,?)", params);   }}##### 1.3 自定义实现连接池为什么要使用连接池: 用户每次请求都需要向数据库获得连接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。Java为连接池实现提供了一个规范(接口),规范的写法,我们需要实现DataSource接口!```java/** * 连接池 * */public class MyDbPool implements DataSource{//创建集合 并且线程安全public static List  connctions=Collections.synchronizedList(new LinkedList()) ;static{try {            InputStream is=MyDbPool.class.getClassLoader().getResourceAsStream("database.properties");         Properties properties=new Properties();          properties.load(is);          String driver=properties.getProperty("driver");            String url=properties.getProperty("url");          String user=properties.getProperty("user");            String password=properties.getProperty("password");//1加载驱动         Class.forName(driver);for(int i=0;i<5;i++){             Connection connection=DriverManager.getConnection(url, user, password);              connctions.add(connection);               System.out.println(i+"....."+connection.hashCode());          }     } catch (Exception e) {// TODO Auto-generated catch block         e.printStackTrace();      } }@Overridepublic Connection getConnection() throws SQLException {// TODO Auto-generated method stub      Connection connection=connctions.remove(0);      System.out.println("获取一个连接.."+connection.hashCode());      System.out.println("池中还剩"+connctions.size());return connection;    }@Overridepublic Connection getConnection(String username, String password) throws SQLException {// TODO Auto-generated method stubreturn null;  }/**   * 把连接再放入池中    * @param conn    */public void release(Connection conn){      connctions.add(conn);     System.out.println("放入了一个连接"+conn.hashCode());     System.out.println("池中还剩"+connctions.size());  }@Overridepublic PrintWriter getLogWriter() throws SQLException {// TODO Auto-generated method stubreturn null;  }@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {// TODO Auto-generated method stub  }@Overridepublic void setLoginTimeout(int seconds) throws SQLException {// TODO Auto-generated method stub   }@Overridepublic int getLoginTimeout() throws SQLException {// TODO Auto-generated method stubreturn 0;  }@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {// TODO Auto-generated method stubreturn null; }@Overridepublic T unwrap(Class iface) throws SQLException {// TODO Auto-generated method stubreturn null;   }@Overridepublic boolean isWrapperFor(Class> iface) throws SQLException {// TODO Auto-generated method stubreturn false;  }}

第十六章 DBCP连接池

DBCP(DataBase Connection Pool),[数据库连接池]。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

#####2.1 DBCP连接池的使用

16.1.1 创建项目

创建Java项目

16.1.2 导入相应jar包

mysql驱动包

commons-dbcp.jar

commons-pool.jar

commons-logging.jar 日志支持

16.1.3 硬编码使用DBCP

所谓的硬编码方式就是在代码中添加配置

@Testpublic void testHard() throws SQLException{//TODO 硬编码 使用DBCP连接池子       BasicDataSource source = new BasicDataSource();//设置连接的信息       source.setDriverClassName("com.mysql.jdbc.Driver");     source.setUrl("jdbc:mysql://localhost:3306/day2");      source.setUsername("root");     source.setPassword("111");

        Connection connection = source.getConnection();

        String sql = "select * from student";

        Statement createStatement = connection.createStatement();

      ResultSet executeQuery = createStatement.executeQuery(sql);

while (executeQuery.next()) {

           System.out.println(executeQuery.getString(2));        }     connection.close(); //回收  }

16.1.4 软编码使用DBCP

所谓的软编码,就是在项目中添加配置文件,这样就不需要每次代码中添加配合!

  1. 项目中添加配置

文件名称: dbcp.properties

文件位置: src下

#连接设置driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/schoolusername=rootpassword=root#initialSize=10#最大连接数量maxTotal=50#maxIdle=20#minIdle=5#maxWaitMillis=5000
  1. 代码实现
  @Testpublic void testSoft() throws Exception{      Properties properties = new  Properties();//配置文件添加到properties对象中  javase       properties.load(new FileInputStream("src/info.properties"));//生成连接池子  需要配置文件      DataSource source = BasicDataSourceFactory.createDataSource(properties);         Connection connection = source.getConnection();      String sql = "select * from student";      Statement createStatement = connection.createStatement();        ResultSet executeQuery = createStatement.executeQuery(sql);while (executeQuery.next()) {           System.out.println(executeQuery.getString(2));        }     connection.close(); //回收  }

第十三章 C3P0连接池

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

c3p0与dbcp区别     1.       dbcp没有自动回收空闲连接的功能     c3p0有自动回收空闲连接功能    2.       dbcp需要手动加载配置文件        c3p0自动加载

13.1 使用步骤

13.1.1 创建项目
13.1.2 导入jar包

c3p0-0.9.1.2.jar

mchange-commons-java-0.2.11.jar

mysql驱动包

13.1.3.添加配置文件

c3p0是在外部添加配置文件,工具直接进行应用,因为直接引用,所以要求固定的命名和文件位置

文件位置: src

文件命名:c3p0-config.xml/c3p0.properties

<c3p0-config>

<default-config>

<property name="driverClass">com.mysql.jdbc.Driverproperty><property name="jdbcUrl">jdbc:mysql://localhost:3306/schoolproperty><property name="user">rootproperty><property name="password">rootproperty>

<property name="checkoutTimeout">10000property>

<property name="idleConnectionTestPeriod">30property>

<property name="initialPoolSize">10property>

<property name="acquireIncrement">5property>

<property name="maxIdleTime">30property><property name="maxPoolSize">50property><property name="minPoolSize">5property>default-config> 

<named-config name="bj1805"><property name="driverClass">com.mysql.jdbc.Driverproperty><property name="jdbcUrl">jdbc:mysql://localhost:3306/day2property><property name="user">rootproperty><property name="password">111property>

<property name="acquireIncrement">5property><property name="initialPoolSize">20property><property name="minPoolSize">10property><property name="maxPoolSize">40property>named-config>c3p0-config> 

c3p0.properties

c3p0.driverClass=com.mysql.jdbc.Driverc3p0.jdbcUrl=jdbc:mysql://localhost:3306/schoolc3p0.user=rootc3p0.password=rootc3p0.acquireIncrement=5c3p0.initialPoolSize=20c3p0.minPoolSize=10c3p0.maxPoolSize=40

注意:

1: c3p0的配置文件内部可以包含命名配置文件和默认配置文件!默认是选择默认配置!如果需要切换命名配置可以在创建c3p0连接池的时候填入命名即可!

2:如果xml配置文件和属性文件都存在时,xml优先级高于属性文件

13.1.4 c3p0进行数据库操作
public class TestC3p0 {

public static void main(String[] args) throws Exception {//创建ComboPooledDataSource对象使用默认配置      ComboPooledDataSource  dataSource = new ComboPooledDataSource();//1.创建C3P0连接池子     Connection connection = dataSource.getConnection();

        Statement createStatement = connection.createStatement();

      String sql = "select * from student;";

       ResultSet resultSet = createStatement.executeQuery(sql);

while (resultSet.next()) {     System.out.println(resultSet.getString(1));       }

       resultSet.close();        createStatement.close();          connection.close();

    }    }

第十四章 Druid连接池

Druid 是目前比较流行的高性能的,分布式列存储的OLAP框架(具体来说是MOLAP)。它有如下几个特点:一. 亚秒级查询     druid提供了快速的聚合能力以及亚秒级的OLAP查询能力,多租户的设计,是面向用户分析应用的理想方式。二.实时数据注入     druid支持流数据的注入,并提供了数据的事件驱动,保证在实时和离线环境下事件的实效性和统一性三.可扩展的PB级存储     druid集群可以很方便的扩容到PB的数据量,每秒百万级别的数据注入。即便在加大数据规模的情况下,也能保证时其效性四.多环境部署     druid既可以运行在商业的硬件上,也可以运行在云上。它可以从多种数据系统中注入数据,包括hadoop,spark,kafka,storm和samza等五.丰富的社区     druid拥有丰富的社区,供大家学习

14.1 使用步骤

配置文件 database.properties:

#连接设置driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/schoolusername=rootpassword=root#initialSize=10#最大连接数量maxActive=50#minIdle=5#maxWait=5000
14.1.1 导入jar包

druid-1.1.5.jar

14.1.2 编写工具类
 /** * 阿里的数据库连接池 * 性能最好的 * Druid * */public class DbUtils {//声明连接池对象private static DruidDataSource ds;static{

//实例化配置对象      Properties properties=new Properties();try {//加载配置文件内容              properties.load(DbUtils.class.getResourceAsStream("database.properties"));              ds = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);        } catch (IOException e) {// TODO Auto-generated catch block         e.printStackTrace();      } }//获取连接对象public static Connection getConnection() {try {return ds.getConnection();        } catch (SQLException e) {// TODO Auto-generated catch block            e.printStackTrace();      }return null;   }   }
14.1.3 测试
import java.sql.Connection;

public class Test {public static void main(String[] args) throws Exception {for(int i=0;i<100;i++) {          Connection connection=DbUtils.getConnection();if(connection!=null) {              System.out.println("连接成功"+i+"..."+connection.hashCode()+connection.toString());           }         connection.close();       } }}

第十五章 DBUtils使用

Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。

15.1 DBUtils简介

DBUtils是java编程中的数据库操作实用工具,小巧简单实用,

1.对于数据表的读操作,可以把结果转换成List,Array,Set等java集合,便于程序员操作。

2.对于数据表的写操作,也变得很简单(只需写sql语句)。

DBUtils包括主要类

DbUtils类:启动类

ResultSetHandler接口:转换类型接口

--ArrayHandler类:实现类,把记录转化成数组

--ArrayListHandler类:把记录转化成数组,并放入集合中

--ColumnListHandler类:取某一列的数据。封装到List中。

ScalarHandler类:适合获取一行一列数据。

BeanHandler类:实现类,把记录转成对象。

BeanListHandler类:实现类,把记录转化成List,使记录为JavaBean类型的对象

QueryRunner类:执行SQL语句的类

15.2 DBUtils工具类封装

15.2.1 项目准备
  • 创建项目
  • 导入jar包 工具类 配置文件 commons-dbutils-1.6.jar druid-1.1.5.jar DruidUtils.java工具类 database.properties配置文件
15.2.2 实现代码
public class ResultHanlder {

@Testpublic void testArrayHander() throws SQLException {

// ArrayHandler:适合取1条记录。把该条记录的每列值封装到一个数组中Object[]        QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());

      Object[] query = runner.query("select * from school where empno = ?", new ArrayHandler(), 1234);

for (Object object : query) {

           System.out.println(object);       }

   }

@Testpublic void testArrayListHander() throws SQLException {

// ArrayHandler:适合取1条记录。把该条记录的每列值封装到一个数组中Object[]     QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());

      List query = runner.query("select * from emp ", new ArrayListHandler());for (Object[] objects : query) {for (Object object : objects) {                System.out.println(object);           }     } }@Testpublic void testColumnListHander() throws SQLException {// ColumnListHandler:取某一列的数据。封装到List中。     QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());        List query = runner.query("select * from emp ", new ColumnListHandler(2));for (Object objects : query) {           System.out.println(objects);      } }@Testpublic void testScalarHandler() throws SQLException {// ScalarHandler:适合取单行单列数据        QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());        Object query = runner.query("select count(*) from emp ", new ScalarHandler());     System.out.println(query);    }@Testpublic void testBeanHandler() throws SQLException {// BeanHandler:适合取单行单列数据        QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());        Employee query = runner.query("select * from emp where empno=1234 ", new BeanHandler(Employee.class));        System.out.println(query.toString()); }@Testpublic void testBeanListHandler() throws SQLException {// BeanHandler:适合取多行多列数据        QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());        List query2 = runner.query("select * from emp", new BeanListHandler(Employee.class));for (Employee employee : query2) {            System.out.println(employee);     } }}

jdbc驱动_JDBC概述和CRUD相关推荐

  1. jdbc和jdbc驱动_JDBC布尔兼容性列表

    jdbc和jdbc驱动 有趣的是,布尔类型只是在SQL标准后期才引入,即SQL:1999 . 即使在今天,并非所有数据库本身都支持BOOLEAN或BIT类型. 最重要的是,我们仍然可以在Oracle中 ...

  2. mysql jdbc驱动_JDBC认识与实践

    一.什么是JDBC? Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数 ...

  3. db2 jdbc驱动参数_JDBC详细整理(一)

    一.什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使用SQL语句来操作数据库 ...

  4. org.gjt.mm.mysql.Driver和com.mysql.jdbc.Driver的概述

    org.gjt.mm.mysql.Driver和com.mysql.jdbc.Driver同为数据库驱动类的概述 org.gjt.mm.mysql.Driver是早期的驱动名称,后来就改名为com.m ...

  5. mysql jdbc简介_JDBC简介

    JDBC是什么? 相对于数据库而言,Web应用是数据库的客户端,我们需要为客户端与数据库之间建立连接,双方才能交互. 我们已经学习了SQL,这是操纵数据库的语言.我们现在开发Web应用使用的Java语 ...

  6. matlab jdbc mysql_Matlab连接MySQL(ODBC及JDBC驱动)

    前言: MySQL最新版本已经更新到了8.0,MATLAB最新版本是2018a,教程基于最新版. 电脑需安装MATLAB以及MySQL数据库. ODBC操作步骤: 安装 MySQL Connector ...

  7. 解决maven官方库中没有oracle jdbc驱动问题 编辑

    2019独角兽企业重金招聘Python工程师标准>>> 刚研究maven不久,遇到一个比较头疼的问题,在工程里怎么下都下载不了oracle的jdbc驱动. 刚还以为是网络问题,重新下 ...

  8. SQLite三种JDBC驱动的区别

    在DBeaver中看到SQLite有三种JDBC驱动,查了它们官方网站的相关解释,发现它们还是挺不一样的. SQLite Wrapper by Christian http://www.ch-wern ...

  9. Ubuntu下eclipse部署mysql jdbc驱动

    1.mysql jdbc驱动包下载地址:http://dev.mysql.com/downloads/connector/j/ 版本:mysql-connector-java-5.1.17.zip 2 ...

最新文章

  1. 明白了缓存穿透和缓存雪崩,再了解一下缓存击穿!
  2. linux命令(51):set 指定行,直接替换并修改文件
  3. 安装kilo版本openstack-dashboard时出现的python compress command not found错误解决办法
  4. python getattr_Python中的getattr()函数详解
  5. HBase Replication源码解析之HLog读取
  6. 大数据发展的问题与机遇
  7. 利用 CocoaPods 服务器中的一个 RCE 漏洞,投毒数百万款app
  8. MFC:VS拖拽多个文件到控件并获取路径
  9. (转)“在证券行业,技术不重要,不要过分强调!”
  10. 数据库系统的三级模式结构
  11. windows10中charles设置代理,android手机无法上网
  12. 【Yolov5】训练自己的yolov5模型并集成到安卓应用中【上】——模型训练
  13. Mask R-CNN网络详解
  14. 十进制转换为三进制实例
  15. 自定义协议的命令解析器
  16. Linux系统磁盘大小比raid小,挂载磁盘阵列柜后,显示的大小比实际小1TB
  17. ubuntu16 安装文本对比软件
  18. 使用火车头采集器的时候往文本之中均匀的插入图片
  19. oracle 11g的安装
  20. 互联网需要70老兵-祝贺杜红超再次创业

热门文章

  1. Samba的主配置文件
  2. Run Android on Your Netbook or Desktop
  3. MOSS 2010:Visual Studio 2010开发体验(26)——工作流开发概述
  4. rsync使用sudo权限
  5. mailx(mail)配置outlook SMTP方式发送邮件
  6. DIY Ruby CPU 分析 Part III
  7. 微软职位内部推荐-Senior Software Engineer II-Search
  8. notepad++ 输入中文无响应
  9. WPF 动态模拟CPU 使用率曲线图
  10. 点击form 表单中的button导致页面刷新问题