Java中的数据库操作与JDBC应用

发布时间: 2023-12-24 01:49:50 阅读量: 31 订阅数: 34
# 1. 引言 ### 1.1 介绍Java中的数据库操作的重要性 在大多数应用程序中,数据库是承载数据的重要组成部分。无论是网站、移动应用还是企业级系统,都需要在后台支持数据的存储和管理。在Java开发中,我们常常需要与数据库进行交互,执行诸如插入、更新、删除和查询等操作。而为了高效地操作数据库,Java提供了一套很好的解决方案,即JDBC。 ### 1.2 JDBC的作用和特点 JDBC(Java Database Connectivity)是Java语言中用于执行与数据库之间交互的API。它提供了一种标准的方式来连接和操作各种关系型数据库。使用JDBC,我们可以在Java程序中执行SQL语句,访问和修改数据库中的数据。 与其他数据库访问技术相比,JDBC具有以下特点: - **可移植性强**:JDBC是Java自带的API,可以跨平台使用,无需额外安装或配置。 - **灵活性高**:JDBC提供了丰富的功能和方法,可以满足不同的数据操作需求。 - **安全性好**:使用JDBC可以有效地防止SQL注入等安全问题。 - **性能优化**:JDBC提供了一些性能优化的方式,如预编译SQL语句、使用连接池等。 - **可扩展性强**:JDBC支持对新的数据库驱动进行添加,并且可以通过扩展API实现更高级的数据库操作。 总之,JDBC是Java开发中不可或缺的一部分,它为我们提供了基于标准的方式来与数据库进行交互,为应用程序的数据处理提供了便捷和高效的解决方案。在接下来的章节中,我们将深入学习和探讨JDBC的各个方面。 # 2. Java的数据库操作基础 在Java中进行数据库操作是非常常见和重要的,我们可以利用Java提供的JDBC(Java Database Connectivity)来实现与数据库的连接和数据操作。在本章节中,我们将介绍Java中的数据库操作的基础知识和技术。 ### 2.1 JDBC简介和基本概念 #### 2.1.1 什么是JDBC? JDBC是Java语言中用于执行SQL语句的一套API,它提供了一种用于连接数据库的标准方法。通过JDBC,我们可以实现与多种数据库的连接和数据操作,而不用担心底层数据库的差异性。 #### 2.1.2 JDBC的基本概念 - **DriverManager(驱动管理器)**:用于管理JDBC驱动程序的类。 - **Connection(连接)**:表示与数据库的物理连接,通过它可以创建 Statement 对象。 - **Statement(语句)**:用于执行静态的 SQL 语句并返回它所生成结果的对象。 - **PreparedStatement(预编译语句)**:表示预编译的 SQL 语句的对象,可以预先编译SQL语句,提高执行效率。 - **ResultSet(结果集)**:表示数据库查询的结果集,可以对结果集进行操作。 ### 2.2 Java中连接数据库的方式 在Java中,可以通过多种方式来连接数据库,常见的方式包括使用原生JDBC连接和使用ORM框架进行数据库操作。接下来我们将分别介绍这两种方式的基本操作。 ### 2.3 数据库的创建和使用 在这一部分,我们将学习如何在Java中创建数据库以及对数据库进行基本的增删改查操作。我们将介绍如何使用JDBC连接数据库,并执行SQL语句来进行数据操作。 ### 2.4 SQL语句的执行和数据的读写操作 在这一节中,我们将学习如何使用JDBC执行SQL语句,并对数据库中的数据进行读写操作。我们将详细介绍如何创建连接、执行SQL语句以及处理数据的结果。 ### 2.5 JDBC中常用的数据类型和数据库事务处理 在JDBC中,数据类型和数据库事务处理是非常重要的部分。我们将学习JDBC中常用的数据类型,以及如何使用JDBC来实现数据库的事务处理,确保数据操作的一致性和安全性。 以上就是本章节的大纲,接下来我们将逐一展开讲解。 # 3. 连接数据库的技术和工具 ## 3.1 JDBC驱动的选择和使用 JDBC(Java Database Connectivity)是Java程序和数据库之间进行交互的标准API。在Java中连接数据库,首先需要选择合适的JDBC驱动,并进行相应的配置和使用。 常见的JDBC驱动有以下几种: - Type 1:JDBC-ODBC桥接器驱动,通过ODBC(Open Database Connectivity)连接数据库。但由于ODBC的性能问题,这种驱动已经不再推荐使用。 - Type 2:本地API驱动,直接使用本机数据库API进行连接。这种驱动需要在操作系统上安装特定的数据库客户端,性能较好,但可移植性较差。 - Type 3:网络API驱动,通过网络协议与数据库服务器通信。这种驱动需要独立的数据库中间件,支持多种数据库,但性能相对较差。 - Type 4:纯Java驱动,完全使用Java编写的驱动,不依赖其他外部库和中间件。这种驱动是目前使用最广泛的方式,拥有良好的性能和可移植性。 在使用JDBC驱动时,需要将相应的驱动jar包添加到项目的依赖中,并进行驱动的加载和注册,例如: ```java // 加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); ``` ## 3.2 连接池的使用和优化 连接数据库是一项消耗资源较大的操作,因此使用连接池可以有效地提高数据库连接的复用率和性能。 连接池是一组预先创建的数据库连接,当应用程序需要连接数据库时,可以从连接池中获取一个连接,而不是每次都重新建立连接。连接池中的连接在使用完毕后可以被释放回连接池,以供其他应用程序复用。 常见的数据库连接池有如下几种选择: - HikariCP:性能高效,轻量级的Java连接池库。 - Apache Commons DBCP:功能丰富,使用广泛的开源连接池库。 - c3p0:稳定可靠的开源连接池库。 使用连接池可以通过配置连接池的参数进行优化,例如设置最大连接数量、最小空闲连接数量、连接超时时间等,以满足应用程序的需求。 ## 3.3 SQL解析和编写工具的推荐 在进行数据库操作时,编写和优化SQL语句是非常重要的。以下是一些常用的SQL解析和编写工具的推荐: - MySQL Workbench:MySQL官方提供的数据库管理工具,支持SQL编写、执行和优化。 - Navicat:功能强大的数据库管理工具,支持多种数据库,提供了直观方便的SQL编辑器。 - DBeaver:开源的数据库管理工具,支持多种数据库,拥有完整的SQL编辑器和执行功能。 这些工具提供了一系列的辅助功能,例如语法高亮、自动完成、查询优化等,方便开发人员编写和优化SQL语句。 ## 3.4 数据库管理工具的选择和使用 除了SQL解析和编写工具外,还有一些数据库管理工具可以帮助开发人员进行数据库的管理和监控。以下是一些常用的数据库管理工具: - MySQL Workbench:MySQL官方提供的数据库管理工具,支持数据库的建模、管理和监控。 - phpMyAdmin:基于Web的MySQL数据库管理工具,提供了图形化界面,方便管理和操作数据库。 - pgAdmin:用于管理PostgreSQL数据库的开源工具,支持数据库的创建、管理和监控。 - Oracle SQL Developer:用于管理Oracle数据库的官方工具,提供了数据库开发和管理的全套解决方案。 这些工具提供了图形化界面,可以方便地进行数据库的管理和监控,提高开发效率和操作便捷性。 以上是连接数据库的技术和工具的介绍,选择合适的驱动和工具可以提高数据库操作的效率和方便性。在实际使用过程中,需要根据具体的需求和情况进行选择和配置。 # 4. JDBC的高级应用 在Java中,JDBC不仅可以用来进行基本的数据库操作,还可以通过一些高级应用来提升性能和管理数据库连接。本章将介绍一些JDBC的高级应用技术和方法。 #### 4.1 批处理和事务处理的实现 在实际的数据库操作中,我们经常需要执行一系列的SQL语句,这时可以通过批处理来提高效率。同时,数据库的事务处理也是非常重要的,可以保证数据的一致性和可靠性。 #### 4.2 使用预编译的SQL语句提升性能 预编译的SQL语句可以在执行时直接调用,而不需要多次解析,可以显著提升性能,尤其是在执行相同的SQL语句多次的情况下。 #### 4.3 数据库连接的优化和并发处理 合理管理数据库连接,并进行并发处理可以提高系统的吞吐量和响应速度,本节将介绍一些优化和并发处理的方法。 #### 4.4 数据库连接池的监控和管理 数据库连接池是连接数据库的重要方式之一,对数据库连接池的监控和管理可以提升系统的稳定性和性能。 #### 4.5 使用JDBC实现ORM(对象关系映射) ORM(Object Relational Mapping)是一种编程技术,能够在关系数据库和对象之间进行转换,本节将介绍如何使用JDBC实现ORM。 本章内容涵盖了JDBC的高级应用,在实际的Java数据库操作中,这些内容将有助于提升系统的性能和稳定性。 以上是第四章的内容,接下来,我们将继续完善其他章节的内容。 # 5. JDBC应用实例 在本章节中,我们将介绍几个具体的JDBC应用实例,帮助读者更好地理解和掌握Java中的数据库操作方法。 #### 5.1 Java项目中的数据库操作实例 我们将以一个简单的Java项目为例,演示如何使用JDBC进行数据库操作。在这个示例中,我们将创建一个用户表,并实现用户的增删改查功能。 ```java // 示例代码 import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class UserDAO { private Connection connection; public UserDAO() { try { Class.forName("com.mysql.jdbc.Driver"); connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "username", "password"); } catch (Exception e) { e.printStackTrace(); } } public void addUser(String username, String password) { try { String sql = "INSERT INTO user(username, password) VALUES(?, ?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, username); preparedStatement.setString(2, password); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } public void deleteUser(int userId) { try { String sql = "DELETE FROM user WHERE id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, userId); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } public void updateUser(int userId, String newUsername, String newPassword) { try { String sql = "UPDATE user SET username=?, password=? WHERE id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, newUsername); preparedStatement.setString(2, newPassword); preparedStatement.setInt(3, userId); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } public void getUser(int userId) { try { String sql = "SELECT * FROM user WHERE id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, userId); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println("Username: " + resultSet.getString("username")); System.out.println("Password: " + resultSet.getString("password")); } } catch (SQLException e) { e.printStackTrace(); } } } ``` 在以上示例中,我们通过JDBC实现了用户的增加、删除、更新和查询操作。 #### 5.2 数据库表设计和数据模型 在实际的数据库操作中,设计合理的数据表结构和数据模型十分重要。这里我们简单展示一下用户表的设计,以及对应的数据模型。 ```sql CREATE TABLE user ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, password VARCHAR(50) NOT NULL ); ``` #### 5.3 实现用户注册和登录功能 我们将进一步扩展示例代码,实现用户注册和登录功能。这是一个常见的应用场景,也能帮助读者更好地理解JDBC在实际项目中的应用。 ```java // 示例代码 import java.util.Scanner; public class UserApplication { public static void main(String[] args) { UserDAO userDAO = new UserDAO(); Scanner scanner = new Scanner(System.in); System.out.println("请输入用户名:"); String username = scanner.nextLine(); System.out.println("请输入密码:"); String password = scanner.nextLine(); userDAO.addUser(username, password); System.out.println("注册成功!请登录:"); System.out.println("请输入用户名:"); String loginUsername = scanner.nextLine(); System.out.println("请输入密码:"); String loginPassword = scanner.nextLine(); userDAO.getUser(1); // 这里假设登录的用户ID为1,实际应用中需要根据用户名查找对应的用户ID } } ``` 以上示例演示了如何通过JDBC实现用户注册和登录功能。 #### 5.4 数据库数据的增删改查操作 除了示例中的增加、删除、更新和查询功能外,实际项目中对数据库的操作可能会更加复杂。我们将继续演示一些常见的数据库增删改查操作,帮助读者更好地理解JDBC的应用。 ```java // 示例代码 public class UserCRUDApplication { public static void main(String[] args) { UserDAO userDAO = new UserDAO(); // 增加用户 userDAO.addUser("user1", "123456"); userDAO.addUser("user2", "abcdef"); // 删除用户 userDAO.deleteUser(1); // 更新用户信息 userDAO.updateUser(2, "newUser2", "654321"); // 查询用户信息 userDAO.getUser(2); } } ``` #### 5.5 数据库备份和恢复方法 在实际项目中,数据库的备份和恢复是非常重要的,可以帮助保障数据的安全性。我们将简单介绍一下如何通过JDBC实现数据库的备份和恢复。 ```java // 示例代码 public class DatabaseBackupAndRestore { public static void main(String[] args) { try { Process runtimeProcess = Runtime.getRuntime().exec("mysqldump -u root -p123456 test > test.sql"); int processComplete = runtimeProcess.waitFor(); if (processComplete == 0) { System.out.println("数据库备份成功!"); } else { System.out.println("数据库备份失败!"); } } catch (Exception e) { e.printStackTrace(); } } } ``` 以上为数据库备份的示例,数据库恢复类似,通过JDBC执行相应的SQL命令即可实现。 通过以上示例,希望读者能够更好地理解JDBC在实际项目中的应用,以及数据库操作的重要性和灵活性。 # 6. 总结与展望 在本章中,我们将对前面所学习的内容进行总结,并对未来的Java数据库操作技术进行展望。同时,我们也将总结JDBC的优点和不足。 ## 6.1 JDBC在Java开发中的重要作用 JDBC是Java开发中数据库操作不可或缺的技术之一。通过JDBC,我们可以连接数据库,执行SQL语句,进行数据的读写操作。JDBC提供了一种标准的数据库访问方式,使得Java程序可以与各种不同类型的数据库进行交互。在Java开发中,使用JDBC可以方便地进行数据库操作,从而提高开发效率和灵活性。 ## 6.2 JDBC的优点和不足 ### 6.2.1 优点 - 简单易用:JDBC提供了一套简单易用的API,开发人员只需要掌握基本的数据库操作知识即可进行开发。 - 跨平台性:JDBC可以在不同的操作系统上运行,不受特定平台的限制。 - 高性能:JDBC可以利用连接池和预编译语句等技术提升数据库操作的性能。 - 灵活性:JDBC支持多种数据库类型,开发人员可以根据需求选择合适的数据库进行开发。 - 高安全性:JDBC提供了对数据库进行安全访问的机制,可以确保数据的安全性。 ### 6.2.2 不足 - 代码冗余:JDBC中的一些操作代码较为冗长,需要编写大量的重复代码。 - SQL依赖:JDBC中使用的是原生的SQL语句,需要开发人员熟悉SQL语法和数据库的具体实现。 - 可维护性差:由于代码冗余和SQL依赖,JDBC代码的维护和修改较为困难。 ## 6.3 对未来Java数据库操作技术的展望 随着技术的不断发展,新的Java数据库操作技术不断涌现,给开发人员带来了更多选择和可能性。以下是对未来Java数据库操作技术的一些展望: - ORM框架的普及:ORM(对象关系映射)框架可以将对象和数据库之间进行映射,简化了数据库操作的代码,提高了开发效率和可维护性。未来的Java数据库操作技术可能更加倾向于使用ORM框架。 - NoSQL数据库的集成:由于传统关系型数据库在某些场景下的性能不足,NoSQL数据库逐渐受到关注。未来的Java数据库操作技术可能会更加注重与NoSQL数据库的集成和应用。 - 云数据库的兴起:随着云计算的普及,云数据库成为了一个重要的选择。未来的Java数据库操作技术可能会进一步优化和适配云数据库。 - 更多的自动化工具和框架:未来的Java数据库操作技术可能会出现更多的自动化工具和框架,用于简化数据库操作、提高性能和可维护性。 ## 6.4 结语 本章对Java数据库操作的重要性进行了介绍,并从多个方面总结了JDBC的作用、优点和不足。同时,对未来Java数据库操作技术进行了展望。随着技术的不断进步,我们相信Java数据库操作技术将会更加先进和易用,为开发人员带来更多便利和效率提升。
corwn 最低0.47元/天 解锁专栏
买1年送3个月
点击查看下一篇
profit 百万级 高质量VIP文章无限畅学
profit 千万级 优质资源任意下载
profit C知道 免费提问 ( 生成式Al产品 )

相关推荐

SW_孙维

开发技术专家
知名科技公司工程师,开发技术领域拥有丰富的工作经验和专业知识。曾负责设计和开发多个复杂的软件系统,涉及到大规模数据处理、分布式系统和高性能计算等方面。
专栏简介
本专栏《Java进阶:JDK常用API》深入探讨了Java编程语言中的各个重要方面,涵盖了面向对象编程、异常处理、集合框架、多线程编程、I/O操作、网络编程、并发编程模式、泛型编程等诸多主题。通过对Java 8新特性、Lambda表达式、注解、反射机制、JDBC应用、虚拟机原理与性能优化、JSON与XML数据处理技术、正则表达式、加密与安全编程、并发容器与工具类的全面学习,读者可以深刻理解JDK中常用的API,并掌握其实际应用技巧。本专栏旨在帮助读者深入学习Java编程的高级知识,提升编程水平,适合有一定Java基础的开发人员阅读学习。
最低0.47元/天 解锁专栏
买1年送3个月
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
C知道 免费提问 ( 生成式Al产品 )

最新推荐

日历事件分析:R语言与timeDate数据包的完美结合

![日历事件分析:R语言与timeDate数据包的完美结合](https://www.lecepe.fr/upload/fiches-formations/visuel-formation-246.jpg) # 1. R语言和timeDate包的基础介绍 ## 1.1 R语言概述 R语言是一种专为统计分析和图形表示而设计的编程语言。自1990年代中期开发以来,R语言凭借其强大的社区支持和丰富的数据处理能力,在学术界和工业界得到了广泛应用。它提供了广泛的统计技术,包括线性和非线性建模、经典统计测试、时间序列分析、分类、聚类等。 ## 1.2 timeDate包简介 timeDate包是R语言

R语言数据包可视化:ggplot2等库,增强数据包的可视化能力

![R语言数据包可视化:ggplot2等库,增强数据包的可视化能力](https://i2.hdslb.com/bfs/archive/c89bf6864859ad526fca520dc1af74940879559c.jpg@960w_540h_1c.webp) # 1. R语言基础与数据可视化概述 R语言凭借其强大的数据处理和图形绘制功能,在数据科学领域中独占鳌头。本章将对R语言进行基础介绍,并概述数据可视化的相关概念。 ## 1.1 R语言简介 R是一个专门用于统计分析和图形表示的编程语言,它拥有大量内置函数和第三方包,使得数据处理和可视化成为可能。R语言的开源特性使其在学术界和工业

【R语言并行计算技巧】:RQuantLib分析加速术

![【R语言并行计算技巧】:RQuantLib分析加速术](https://opengraph.githubassets.com/4c28f2e0dca0bff4b17e3e130dcd5640cf4ee6ea0c0fc135c79c64d668b1c226/piquette/quantlib) # 1. R语言并行计算简介 在当今大数据和复杂算法的背景下,单线程的计算方式已难以满足对效率和速度的需求。R语言作为一种功能强大的统计分析语言,其并行计算能力显得尤为重要。并行计算是同时使用多个计算资源解决计算问题的技术,它通过分散任务到不同的处理单元来缩短求解时间,从而提高计算性能。 ## 2

【R语言深度学习框架Keras for R全面介绍】:人工智能的R语言实现

![【R语言深度学习框架Keras for R全面介绍】:人工智能的R语言实现](https://s3.amazonaws.com/keras.io/img/keras-logo-2018-large-1200.png) # 1. Keras for R简介 ## 1.1 R语言与深度学习的结合 R语言是统计分析领域的翘楚,虽然在深度学习方面的应用相对滞后,但Keras for R的出现极大地丰富了R语言的数据科学工具箱。Keras是一个高层神经网络API,它以TensorFlow, CNTK, 或 Theano作为后端运行,由于其用户友好性和模块化特点,R语言的用户现在能够更加便捷地构建和

【R语言时间序列数据缺失处理】

![【R语言时间序列数据缺失处理】](https://statisticsglobe.com/wp-content/uploads/2022/03/How-to-Report-Missing-Values-R-Programming-Languag-TN-1024x576.png) # 1. 时间序列数据与缺失问题概述 ## 1.1 时间序列数据的定义及其重要性 时间序列数据是一组按时间顺序排列的观测值的集合,通常以固定的时间间隔采集。这类数据在经济学、气象学、金融市场分析等领域中至关重要,因为它们能够揭示变量随时间变化的规律和趋势。 ## 1.2 时间序列中的缺失数据问题 时间序列分析中

量化投资数据探索:R语言与quantmod包的分析与策略

![量化投资数据探索:R语言与quantmod包的分析与策略](https://opengraph.githubassets.com/f90416d609871ffc3fc76f0ad8b34d6ffa6ba3703bcb8a0f248684050e3fffd3/joshuaulrich/quantmod/issues/178) # 1. 量化投资与R语言基础 量化投资是一个用数学模型和计算方法来识别投资机会的领域。在这第一章中,我们将了解量化投资的基本概念以及如何使用R语言来构建基础的量化分析框架。R语言是一种开源编程语言,其强大的统计功能和图形表现能力使得它在量化投资领域中被广泛使用。

【R语言时间序列分析】:数据包中的时间序列工具箱

![【R语言时间序列分析】:数据包中的时间序列工具箱](https://yqfile.alicdn.com/5443b8987ac9e300d123f9b15d7b93581e34b875.png?x-oss-process=image/resize,s_500,m_lfit) # 1. 时间序列分析概述 时间序列分析作为一种统计工具,在金融、经济、工程、气象和生物医学等多个领域都扮演着至关重要的角色。通过对时间序列数据的分析,我们能够揭示数据在时间维度上的变化规律,预测未来的趋势和模式。本章将介绍时间序列分析的基础知识,包括其定义、重要性、以及它如何帮助我们从历史数据中提取有价值的信息。

【R语言混搭艺术】:tseries包与其他包的综合运用

![【R语言混搭艺术】:tseries包与其他包的综合运用](https://opengraph.githubassets.com/d7d8f3731cef29e784319a6132b041018896c7025105ed8ea641708fc7823f38/cran/tseries) # 1. R语言与tseries包简介 ## R语言简介 R语言是一种用于统计分析、图形表示和报告的编程语言。由于其强大的社区支持和不断增加的包库,R语言已成为数据分析领域首选的工具之一。R语言以其灵活性、可扩展性和对数据操作的精确控制而著称,尤其在时间序列分析方面表现出色。 ## tseries包概述

【缺失值处理策略】:R语言xts包中的挑战与解决方案

![【缺失值处理策略】:R语言xts包中的挑战与解决方案](https://yqfile.alicdn.com/5443b8987ac9e300d123f9b15d7b93581e34b875.png?x-oss-process=image/resize,s_500,m_lfit) # 1. 缺失值处理的基础知识 数据缺失是数据分析过程中常见的问题,它可能因为各种原因,如数据收集或记录错误、文件损坏、隐私保护等出现。这些缺失值如果不加以妥善处理,会对数据分析结果的准确性和可靠性造成负面影响。在开始任何数据分析之前,正确识别和处理缺失值是至关重要的。缺失值处理不是单一的方法,而是要结合数据特性

R语言its包自定义分析工具:创建个性化函数与包的终极指南

# 1. R语言its包概述与应用基础 R语言作为统计分析和数据科学领域的利器,其强大的包生态系统为各种数据分析提供了方便。在本章中,我们将重点介绍R语言中用于时间序列分析的`its`包。`its`包提供了一系列工具,用于创建时间序列对象、进行数据处理和分析,以及可视化结果。通过本章,读者将了解`its`包的基本功能和使用场景,为后续章节深入学习和应用`its`包打下坚实基础。 ## 1.1 its包的安装与加载 首先,要使用`its`包,你需要通过R的包管理工具`install.packages()`安装它: ```r install.packages("its") ``` 安装完