一、JDBC的概述

1.JDBC为访问不同的数据薛是供了统一的接口,为使用者屏蔽了细节问题。
2. Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。

 二。JDBC带来的好处

java程序可以直接对数据库进行调用,但是没有很好的移植性(对用于不同的数据库),所以不推荐

JDBC带来的好处:JDBC是java提供一套用于数据库操作的接口API,Java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。

JDBC API:JDBC API 是一系列的接口,它统一和规范了应用程序与数据库的连接,执行SQL语句,并得到返回结果等各类操作;

JDBC程序编写步骤

1、注册驱动 --- 加载Driver类

2、获取连接 --- 得到Connection

3、执行增删改查 --- 发送Sql给mysql执行

4、释放资源 --- 关闭相关连接

 获取数据库连接的5种方式:

方式1:使用(com.mysql.jdbc.Driver)com.mysql.cj.jdbc.Driver,属于静态加载,灵活性差,依赖性强

方式2:使用反射机制,属于静态加载

方式3:使用DriverManager替代driver进行统一管理

方式4:使用Class.forName自动完成注册驱动,简化代码

这种方式连接是使用得最多的(推荐使用)

在底层会完成注册:

提示:

(1)mysql驱动5.1.6可以无需Class.forName(“com.mysql.jdbc.Driver”);

(2)从jdk1.5以后使用了jdbc4,不再需要显示调用class.forName()注册驱动而是自动调用驱动jar包下META-INF\servicesljava .sql.Driver文本中的类名称去注册

(3)建议加上Class.forName(“com.mysql.jdbc.driver”),能够更加明确的感受到程序流程,利于掌握;

方式5:利用properties文件配置数据库需要的相关的配置

更加的灵活,可以直接通过properties配置文件修改数据库连接相关的数据

对方式5的实例:

//properties配置文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test_db?useSSL=false&characterEncoding=utf8&serverTimezone=UTC
user=root
password=123456
//连接数据库的相关操作
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; public class jdbc02 {
public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException {
//创建一个properties对象
Properties properties = new Properties();
//加载和获取创建的properties的相关数据
properties.load(new FileInputStream("src\\db.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password"); String sql = "insert into actor values (null,'王五','男','1975-11-23','110')"; //driver驱动,也可以不加,但是加上更容易读懂流程
Class.forName(driver);
//连接和执行操作
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();
statement.executeUpdate(sql);
//关闭连接
System.out.println("连接"+connection);
statement.close();
connection.close(); }
}

三、RestSet【结果集】

基本介绍:

1.表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
2. ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前

3. next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回
false,因此可以在while循环中使用循环来遍历结果集

简单测试:

 四、Statement:

基本介绍:

1.Statement对象用于执行静态SQL语句并返回其生成的结果的对象
2.在连接建立后,需要对数据库进行访问,执行命名或是SQL语句,可以通过

Statement【存在SQL注入】
PreparedStatement【预处理】
CallableStatement【存储过程】

3. Statement对象执行SQL语句,存在SQL注入风险

4.SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库。

5.要防范SQL注入,只要用 PreparedStatement(从Statement扩展而来)取
代 Statement就可以了

import java.io.*;
import java.sql.*;
import java.util.Properties; public class jdbc02 {
public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException {
//创建一个properties对象
Properties properties = new Properties();
//加载和获取创建的properties的相关数据
properties.load(new FileInputStream("src\\db.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password"); String sql = "insert into actor values (null,'三毛','男','1975-11-23','110')";
String sql1 = "select id,name from actor"; //driver驱动,也可以不加,但是加上更容易读懂流程
Class.forName(driver);
//连接和执行操作
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();
// statement.executeUpdate(sql); // String sql1 = "select id,name from actor";
ResultSet resultSet = statement.executeQuery(sql1);
while (resultSet.next()) {
int i = resultSet.getInt(1);
String string1 = resultSet.getString(2);
System.out.println(i+"=="+string1);
}
//关闭连接
resultSet.close();
System.out.println("连接"+connection);
statement.close();
connection.close(); }
}

PrepareStatement:

1. PreparedStatement 执行的SQL语句中的参数用问号(?)来表示,调用
PreparedStatement对象的setXxx()方法来设置这些参数. setXxx()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个是设置的SQL语句中的参数的值
2.调用executeQuery),返回ResultSet 对象
3.调用executeUpdate):执行更新,包括增、删、修改

预处理的好处:

1.不再使用+拼接sql语句,减少语法错误

2.有效的解决了sql注入问题!
3.大大减少了编译次数,效率较高

对preparestatement的测试代码,配置文件还是上面的配置文件

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties; public class PrepareStatement {
public static void main(String[] args) throws Exception { Properties properties = new Properties();
properties.load(new FileInputStream("src\\db.properties"));
String drive = properties.getProperty("driver");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password"); //更新操作
// String sql = "update actor set phone = ? where name = ?";
//删除操作
// String sql = "delete from actor where name = ?";
// 添加操作
// String sql = "insert into actor values(null,?,?,?,?)";
//查询操作
String sql = "select * from actor"; Class.forName(drive); Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(sql);
//更改操作
// preparedStatement.setString(1, "123456");
// preparedStatement.setString(2, "三毛");
//删除操作
// preparedStatement.setString(1, "二狗");
//添加操作
// preparedStatement.setString(1, "张三");
// preparedStatement.setString(2, "男");
// preparedStatement.setString(3, "1975-11-23 00:00:00");
// preparedStatement.setString(4,"456789");
// int i = preparedStatement.executeUpdate();
// System.out.println(i >0 ? "成功" : "失败"); //查询操作
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getString(2));
} preparedStatement.close();
connection.close(); }
}

总结:

 五、事务:将多行代码当做SQL事务来处理,主要流程需要的关键代码:

connection.setAutoCommit(false);//取消自动提交的操作,取消之后,会在提及之后完成事务
connection.commit();提交事务
connection.rollback();//用于回退事务
批处理:

基本介绍:

1、当需要成批插入或者更新记录时。可以采用Java的批量更新机制,这一机制允
许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。

2、JDBC的批量处理语句包括下面方法:
addBatch():添加需要批量处理的SQL语句或参数executeBatch(:执行批量处理语句;
clearBatch():清空批处理包的语句
3、 JDBC连接MySQL时,如果要使用批处理功能,请再url中加参
数?rewriteBatchedStatements=true
4、批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减少运行次数,效率大大提高

过程:

(1)将sql语句加入到批处理包中

preparedStatement.addBatch();
preparedStatement.addBatch(sql);

(2)执行sql和清空sql

//批量执行sql语句
preparedStatement.executeBatch();
//清除批量的sql语句
preparedStatement.clearBatch();

将 SQL加入到批处理包中源码所做的事情:

六、数据库连接池

 传统connection问题分析

1.传统的JDBC数据库连接使用 DriverManager来获取,每次向数据库建立
连接的时候都要将Connection 加载到内存中,再验证IP地址,用户名和密码(0.05s~1s时间)。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。2每一次数据库连接,使用完后都得断开,如果程序出现异常面未能关闭,将
导致数据库内存泄漏,最终将导致重启数据库。
3.传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致
内存泄漏,MySQL崩溃。
4.解决传统开发中的数据库连接问题,可以采用数据库连接池技术
(connection pool).

数据库连接池基本介绍:

1.预先在缓冲池中放入一定数量的连接,,当需
要建立数据库连接时,只需从“缓冲池”中取出一个,,使用完毕之后再放回去。
2.数据库连接池负责分配、管理和释放数据库
连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
3.当应用程序向连接池请求的连接数超过最大
连接数量时,这些请求将被加入到等待队列中

数据库连接池示意图:

数据库连接池种类:

1.JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource
只是一个接口,该接口通常由第三方提供实现
2.C3PO 数据库连接池,速度相对较慢,稳定性不错(hibernate, spring)

3.DBCP数据库连接池,速度相对c3p0较快,但不稳定
4. Proxool数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点

5.BoneCP数据库连接池,速度快
6.Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP、C3P0、Proxool
优点于身的数据库连接池

测试:C3P0连接池的连接(需要导入第三方库:c3p0的jar包)

第一个C3P0连接的配置文件还是上面的配置文件内容

第二个C3P0的连接需要有一个xml配置文件

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.jupiter.api.Test; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; public class ConDatasource {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\db.properties"));
String driver = properties.getProperty("driver");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url"); //建立comboPooledDataSource管理连接池
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password); //设置初始化连接数和最大连接数
comboPooledDataSource.setInitialPoolSize(10);
comboPooledDataSource.setMaxPoolSize(50);
//这个方法就是从DataSource接口实现的
Connection connection = comboPooledDataSource.getConnection();
System.out.println("1连接成功");
connection.close(); } @Test
public void ConDatasource02() throws SQLException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("test_C3P0"); long start = System.currentTimeMillis();
System.out.println("测试连接5000次需要的时间");
for (int i = 0; i < 5000; i++) {
Connection connection = comboPooledDataSource.getConnection();
// System.out.println("2连接成功");
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("花费时长:"+(end-start));
}
}
//第二种方式的xml文件
<c3p0-config> <named-config name="test_C3P0">
<!-- 驱动类 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<!-- url-->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test_db?useSSL=false&amp;characterEncoding=utf8&amp;serverTimezone=UTC</property>
<!-- 用户名 -->
<property name="user">root</property>
<!-- 密码 -->
<property name="password">123456</property>
<!-- 每次增长的连接数-->
<property name="acquireIncrement">5</property>
<!-- 初始的连接数 -->
<property name="initialPoolSize">10</property>
<!-- 最小连接数 -->
<property name="minPoolSize">5</property>
<!-- 最大连接数 -->
<property name="maxPoolSize">10</property> <!-- 可连接的最多的命令对象数 -->
<property name="maxStatements">5</property> <!-- 每个连接对象可连接的最多的命令对象数 -->
<property name="maxStatementsPerConnection">2</property>
</named-config>
</c3p0-config>

测试:Druid连接池的连接(需要第三方库druid的jar包)

package com.zjl.jdbc;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.util.Properties; public class Druidsource {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));//如下定义的配置文件 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
long start = System.currentTimeMillis();
for (int i = 0;i < 500000;i++ ) {
Connection connection = dataSource.getConnection();
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("Druid连接5000 次需要的时间:" + (end - start));//Druid连接500000 次需要的时间:625
}
}
//连接中需要的一个配置文件
druid.properties:放在src目录下

#key=value
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test_db?useSSL=false&characterEncoding=utf8&serverTimezone=UTC
#url=jdbc:mysql://localhost:3306/girls
username=root
password=123456
#initial connection Size初始连接数
initialSize=10
#min idle connecton size最小等待连接数
minIdle=5
#max active connection size最大连接数
maxActive=20
#max wait time (5000 mil seconds)
# 最大等待时间,时间超过就结束这次连接等待下一次的连接
maxWait=5000
 

注意:对于c3p0和Druid他们的close()是按照第三方库的连接方式,仅仅是将从连接池引用的数据库连接断开(放弃引用)

重新将连接放回到连接池中,和原生 的jdbc连接中的close方法断开连接不同;

用Druid创建一个连接和断开的工具类;

package com.zjl.jdbc;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; public class JDBCUtilsByDruid {
static DataSource ds;
static {
Properties properties = new Properties(); try {
properties.load(new FileInputStream("src\\druid.properties"));
ds = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//编写获取Connection的方法
public static Connection getConnection() throws SQLException {
return ds.getConnection();
} public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//将编译异常转成运行异常抛出
throw new RuntimeException(e);
}
}
}

七、Apache-DBUtils

1、问题引出:在使用Druid连接数据库,返回结果集之后,如果断开连接,结果集就不能够再使用。解决方法如图,将返回的结果集保存到一个泛型列表中,那么当数据库连接断开后,还是可以使用返回的结果集。

2、对Apache-DBUtils的基本介绍

1).commons-dbutils 是 Apache组织提供的一个开源 JDBC工具类库,它是对JDBC的封装,
使用dbutils能极大简化jdbc编码的工作量[真的]。
DbUtils类
(1). QueryRunner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查、批处理

(2).使用QueryRunner类实现查询
(3). ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式

对该DBUtils进行测试:需要对应的jar包(commons-dbutils-1.7.jar)可以去:http://commons.apache.org/下载

相应的JDBCUtilsByDruid类是上面的测试类:

package com.zjl.jdbc;

import com.zjl.bean.Actor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List; public class TestDBUtils {
public static void main(String[] args) throws Exception {
String sql = "select * from `actor`";
//从Druid中获取一个连接
Connection connection = JDBCUtilsByDruid.getConnection();
//引入DBUtils的jar包,并获得一个QueryRunner对象
QueryRunner queryRunner = new QueryRunner(); //利用QueryRunner对象就可以直接查询数据库,执行SQl语句,返回结果封装到ArrayList集合中
// connection是一个连接,sql是一个执行语句
//new BeanListHandler<>(Actor.class):在将resultSet中的结果以Actor对象方式封装到ArrayList
//底层使用反射机制,获取Actor类的属性,然后进行封装
//1就是给sql 语句中的?赋值,可以有多个值,因为是可变参数0bject... params
// List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);
//如果要返回单个查询数据就使用BeanHandler<>(Actor.class),返回结果就会是单个对象或者为空
List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class));
//在底层会得到resultSet并在query中关闭,也会在底层使用preparedStatement并关闭
// JDBCUtilsByDruid.close(null, null, connection);
Iterator<Actor> iterator = list.iterator();
while (iterator.hasNext()) {
Actor next = iterator.next();
System.out.println(next);
}
//进行更新操作
String updateSql = "update `actor` set name = ? where id = ?";
int update = queryRunner.update(connection, updateSql, "王无无", 8);
System.out.println((update > 0) ? "更新成功" : "更新失败");
//进行删除操作
String delSql = "delete from `actor` where id = ?";
int update1 = queryRunner.update(connection, delSql, 10);
System.out.println((update > 0) ? "删除成功" : "删除失败"); //关闭资源
JDBCUtilsByDruid.close(null, null, connection);
} }

八、BasicDao--DAO和增删改查通用方法(DAO:data access object   数据访问对象)

基本说明:

1)、 DAO:data access object数据访问对象
2)、这样的通用类,称为 BasicDao,是专门和数据库交互的,即完成对数据库(表)的crud操作。

3)、在BaiscDao的基础上,实现一张表对应一个Dao,更好的完成功能;

关系图如下:



java_JDBC,连接数据库方式,RestSet结果集,Statement,PreparedStatement,事务,批处理,数据库连接池(c3p0和Druid)、Apache-DBUtils、的更多相关文章

  1. 通过实现ServletContextListener接口创建数据库连接池(C3P0方式)

    使用Listener步骤 1. 定义Listener实现类 2. 在web.xml中配置(或使用Annotation) 使用C3P0方式创建数据库连接池需要添加的jar包 1.c3p0-0.9.5.j ...

  2. Java中数据库连接池原理机制的详细讲解以及项目连接数据库采用JDBC常用的几种连接方式

    连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...

  3. 网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

    1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2 ...

  4. java基础 JDBC & Statement & PreparedStatement

    参考文章: http://blog.csdn.net/wang379275614/article/details/23393335 概念 JDBC-数据库连接,是由一些类和接口构成的API,是J2SE ...

  5. Lucene搜索方式大合集

    package junit; import java.io.File; import java.io.IOException; import java.text.ParseException; imp ...

  6. Jmeter连接数据库方式

    关系型数据库: 1.mysql: 方式:Database URL:jdbc:mysql://localhost:port/DBname?user=**&password=**&allo ...

  7. ipv6下jdbc的连接数据库方式

    ipv6下jdbc的连接数据库方式 MySQL: ipv4 Driver URL:           jdbc:mysql://127.0.0.1:3306/database   ipv6 Driv ...

  8. 基于已有集群动态发现方式部署 Etcd 集群

    etcd提供了多种部署集群的方式,在「通过静态发现方式部署etcd集群」 一文中我们介绍了如何通过静态发现方式部署集群. 不过很多时候,你只知道你要搭建一个多大(包含多少节点)的集群,但是并不能事先知 ...

  9. 基于 DNS 动态发现方式部署 Etcd 集群

    使用discovery的方式来搭建etcd集群方式有两种:etcd discovery和DNS discovery.在 「基于已有集群动态发现方式部署etcd集群」一文中讲解了etcd discove ...

随机推荐

  1. 深入 Laravel 内核之观察者模式

    装饰模式核心内容: 观察者模式又称为发布订阅模式,定义了对象间的一对多依赖关系,当一个对象状态发生改变时,其相关依赖的其他对象都能接收到通知: 观察者模式的核心在于目标(Subject)和观察者(Ob ...

  2. Android 摄像头预览悬浮窗,可拖动,可显示在其他app上方

    市面上常见的摄像头悬浮窗,如微信.手机QQ的视频通话功能,有如下特点: 整屏页面能切换到一个小的悬浮窗 悬浮窗能运行在其他app上方 悬浮窗能跳回整屏页面,并且悬浮窗消失 我们探讨过用CameraX打 ...

  3. Pytest_常用执行参数详解(3)

    前面讲了测试用例的执行方式,也认识了 -v  -s 这些参数,那么还有没有其它参数呢?答案肯定是有的,我们可以通过 pytest -h来查看所有可用参数. 从图中可以看出,pytest的参数有很多,但 ...

  4. antd中的form表单 initialValue导致数据不更新问题

    初步理解 : initialValue就是所谓的defaultValue,只会在第一次赋值的时候改变,却又有一些不同,因为 initialValue又会因其他改动而改变. 然而当获取的数据重新上来要渲 ...

  5. 经典定长指令-修改EIP

    1.0x70~0x7F EIP无法像通用寄存器那样用mov来修改,只能通过类似于jz,JNB,JNE JBE,call等的跳转指令来进行修改 条件跳转,后跟一个字节立即数的偏移(有符号),共两个字节. ...

  6. testng.xml 执行多个测试用例

    1.在工程名字上点击右键,点击[New]-->[File] 2.在弹出的[New File]对话框中的[File name]输入[testng.xml],点击[Finish]即创建了一个test ...

  7. python 读取配置文件ini ---ConfigParser

    Python读取ini文件需要用到 ConfigParser 模块 关于ConfigParser模块的介绍详情请参照官网解释:https://docs.python.org/2.7/library/c ...

  8. 解决twrp中内部存储为0MB的情况

    本来打算给备用机红米4a刷个dotos的系统,结果忘记双清就刷了,然后进去系统也是直接黑屏,很神奇的是长按电源键能弹出dotos的关机选项.然后进去twrp准备双清在刷时,发现内部存储变成了0MB,然 ...

  9. Spark基础知识详解

    Apache Spark是一种快速通用的集群计算系统. 它提供Java,Scala,Python和R中的高级API,以及支持通用执行图的优化引擎. 它还支持一组丰富的高级工具,包括用于SQL和结构化数 ...

  10. 【刷题-PAT】A1101 Quick Sort (25 分)

    1101 Quick Sort (25 分) There is a classical process named partition in the famous quick sort algorit ...