MySQL数据库的安装、创建库、创建表、向数据库添加测试数据及连接取数
MySQL数据库简介
此处先给出MySQL官网?
Java对于数据库常用操作的封装
Java通过提供统一API定义的方式来实现对各种数据库进行操作时Java代码编码层面的统一,有效减少了Java代码在跨数据库时——Java项目在数据库需要变更时需要修改代码的问题。这样做的好处是显而易见的,①使操作不同的数据库在Java层面得到了统一,有利于Java项目实现跨数据库,当然变更数据库时,项目中要导入对应数据库的jar包②淡化不同数据库版本在Java代码中的差异,从而进一步突出Java项目中的业务逻辑。在使用Java的时候,不用关心底层使用什么数据库,只需要关心业务逻辑即可。API的具体实现由各数据库厂商自己提供(jar包,以驱动的形式)。在使用的时候,只需在自己的项目中导入对应数据库驱动的jar包即可,示意图如下所示。
目前常用的数据库种类很多,比如常见的MySQL、Oracle、SqlServer、Sqlite… 这些数据库都有自己的特性,如果Java为每一种数据库开发一套API,进行数据库操作,那么将是很头疼的,原因如下:
1、每一种数据库都有差异,那么就代表每一套API的使用方法可能都不同;
2、不便于数据库迁移,比如,前期使用MySQL,到后期发现Oracle更加适合项目,于是将数据从MySQL迁移到Oracle中了,因为API不同,所以需要重新修改所有的SQL操作。
3、除此之外,这么多套API,维护起来也是很麻烦的;
安装MySQL数据库
下载MySQL安装包
MySQL数据库的安装包 选择MySQL Community Server
(网上说是“免费版”,Community社区版,Server服务端/后端) 如下图红框所示。可直接点击此链接进入MySQL数据库的安装包的下载界面即可。
Linux
在进入的MySQL数据库的安装包的下载界面中,Operating System
选择对应版本的Linux系统,比如Ubuntu Linux
,如下图所示。
MySQL在ubuntu Linux下的多版本选择
MySQL在ubuntu Linux下的版本分为DEB Bundle
和DEB Package
两种,如下图所示。
DEB Bundle与DEB Package
DEB
Debian(DEB)包是Unixar的标准归档,将包文件信息以及包内容,经过tar打包和gzip压缩而成。处理这些包的经典程序是dpkg,经常是通过Debian的apt-get来运作。通过Alien工具,可以将deb包转换成rpm、tar.gz格式。deb包在Linux操作系统中类似于windows中的软件包(msi),几乎不需要什么复杂的编译即可通过鼠标点击安装使用。
deb 格式是 Debian 系统(包含 Debian 和 Ubuntu )专属安装包格式。
deb 本身可以使用不同的压缩方式。tar 格式并不是一种压缩格式,而是直接把分散的文件和目录集合在一起,并记录其权限等数据信息。之前提到过的 data.tar.XXX,这里 XXX 就是经过压缩后的后缀名。deb 默认使用的压缩格式为 gzip 格式,所以最常见的就是 data.tar.gz。常有的压缩格式还有 bzip2 和 lzma,其中 lzma 压缩率最高,但压缩需要的 CPU 资源和时间都比较长。
data.tar.gz包含的是实际安装的程序数据,而在安装过程中,该包里的数据会被直接(即压缩包里什么目录结构,解压后就是什么结构)解压到根目录(即 / ),因此在打包之前需要根据文件所在位置设置好相应的文件/目录树。
通过Alien工具,可以将deb包转换成rpm、tar.gz格式。
deb 包本身有三部分组成:
- 数据包,包含实际安装的程序数据,文件名为 data.tar.XXX;
- 安装信息及控制脚本包,包含 deb 的安装说明,标识,脚本等,文件名为 control.tar.gz;
- deb 文件的一些二进制数据,包括文件头等信息,一般看不到,在某些软件中打开可以看到。
Bundle 与 Package
- DEB Bundle:是离线deb安装包,将所有软件的deb文件全部打包成一个压缩包,解压出来全部都是deb文件,通过dkg命令进行安装即可。是一个目录,有标准的层次结构,包含了可执行文件、必需的资源以及【代码和资源是怎么与应用联系的】,看起来像一个文件。
- DEB Package:本身就是deb文件,下载回来之后直接用dkg命令安装,是在线安装的形式(所以文件很小)。其看起来像一个文件的目录,包含了一个应用所需要的所有,包括可执行代码和资源。
Windows
在进入的MySQL数据库的安装包的下载界面中,Operating System
选择Microsoft Windows系统,如下图所示。
本次选择了ZIP Archive
版本,如下图红框所示。
使用命令行操作MySQL
Linux
待按照此博客的内容安装验证无误后,再将其中的内容(诸如“编译安装的指令”、“使用三核编译的指令”、“安装过程”、“配置成系统服务(开机自启)”)补入此处。
Windows
- 将下载的安装包
mysql-8.0.30-winx64.zip
解压后,将mysql的根目录——比如D:\mysql-8.0.30-winx64\bin
——配置到环境变量path中。
- 使用
PowerShell
进行安装,首先以管理员身份运行PowerShell
。在PowerShell
中先进入到MySQL的根目录的bin目录下,再执行mysqld --install
命令,如下图所示。
-
mysqld --initialize-insecure --user=mysql
,运行结果如下图所示。
-
net start mysql
,显示“MySQL服务正在启动 …” “MySQL服务已经启动成功。”,如下图所示。
- ①(连接本地MySQL数据库)使用指令
mysql -u root -p
登陆,这是因为安装完成、启动mysql后,要先使用root账户登陆数据库,如下图所示;②(连接远程MySQL数据库)使用指令mysql -h 远程MySQL数据库所在的IP地址 -u root -p
,即在指令中增加参数-h 远程MySQL数据库所在的IP地址
,比如mysql -h 10.0.1.99 -u root -p
。
安装完成后的root用户的初始密码是空——即Enter password:
处不需输入任何字符、直接回车即可,如下图所示。数据库登陆成功后,输入指令处的路径显示为mysql>
,如下图红框所示。
若需退出mysql>
,直接输入exit
即可;若已进入->
,输入\q
即可,如下两图所示。
若需关闭MySQL,需以管理员身份启动命令行(否则输入关闭指令后会提示拒绝访问),在操作系统的任意路径下,命令输入net stop mysql
即可,如下图所示。
此处也给出未以管理员身份启动命令行时,启动数据的情形
MySQL创建一个新的数据库,并在其中创建新的数据表,填充测试数据并查看
-
首先,必须要在一个数据库里面工作,所以你必须创建一个数据库。利用
create database【数据库名称,比如test】;
,来出创建数据库注意,语句结尾必须要有;号,否则如下图第一行所示,提示SQL语法错误,进而创建失败。
- 查看已创建的数据库,在
mysql>
下输入show databases;
,如下图所示。
此时,数据库安装目录下的data文件夹下的目录,如下所示。下图红框内的四个文件夹对应上方显示的五个数据库的四个,上方第一个数据库information_schema
不知道在何处 = =。
-
如上所述,因为必须要在一个数据库里面工作,所以使用
use 【要切换到的数据库名称,比如test】 ;
来使用上一步创建好的数据库test,如下图所示,提示数据库切换成功Database changed
。
使用show tables;
来查看当前数据库test
中的表Tables_in_test
有哪些,如下图所示。
- 在当前选择的数据库中创建表创建①要将原语句
create table 【表名,比如此处的testTable1】 (id int,name varchar(100));
分为四行来依次输入,以;结尾表示一条语句结束,如下所示。注意第一行语句的create table testTable1(
结尾的(
不要遗漏!;当提示Query OK, 0 rows affected (0.10 sec)
表示创建成功。
②还可创建复杂的表,使用如下语句:
CREATE TABLE hogwarts_user (id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',name varchar(20) DEFAULT NULL,age int(10) DEFAULT NULL COMMENT '年龄',primary key (id) USING BTREE)ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='霍格沃兹学生';
还可以在建表时对指定属性添加unique
标识,使该属性的每个值唯一,用法如下所示。
create table wx_student(
sno int(6) primary key ,
sname varchar(20) not null ,
sphone char(11) unique ,/*唯一,可以为空,不能重复*/
sage tinyint unsigned default 18,
saddr varchar(25),
uid int
);
提示“Query OK”,创建成功,如下图所示。请注意,在创建新表之前,需先选好数据库,如下图红框所示。
有博客提到“注意创建表格过程中必须是英文输入法,中文和英文的逗号,括号和引号都必须是英文的”,待确认。
-
①向上一步创建的表testTable1
插入数据,insert into testTable1(id,name) values(0,'0');
。第一处testTable1(id,name)
要给出要插入的表名和要插入的单条数据涉及到的列名,第二处values(0,'0')
要针对第一处给出的【要插入数据涉及到的每个列名】的值。若插入成功,会提示Query OK
,如下图所示。若要一条sql语句插入多条数据,可使用insert into testTable1(id,name) values(0,'0'),(1,'1'),(2,'2');
。
②若向上一步创建复杂的表hogwarts_user
插入数据insert into hogwarts_user(name, age) values('霍格沃兹测试学院',1)
,通常不要手动设置id的值。因为在创建hogwarts_user表时,将id设置为了自增AUTO_INCREMENT
,所以一般不在插入新数据时设置id,交由数据库自增,防止自己设定的id与数据库自增的id冲突。若非要设置id,语法上可行。另外,在创建表hogwarts_user
时,如果有设置某列名不能为空(NOT NULL)时,则向该表插入数据时该列的属性必须有值,否则会报错。
-
使用select * from 【表名,比如此处的testTable1】;
查看刚才插入的那一条数据,如下图所示。
查看上一步②中创建的数据,如下图所示。
-
mysql>exit
退出数据库——即退出mysql命令行模式mysql>
,如下图所示。
-
若要关闭MySQL(需先退出数据库——即mysql>
模式),在操作系统的任意路径下输入net stop mysql
即可,如下图所示。提示服务已成功停止
表示MySQL数据库已关闭。
mysql>
模式下输入的每句sql语句都要以;
结尾;若多行语句无;
,则被默认为一条语句未输入完成;若多条语句无;
,直到最后一条语句有;
,则被认为是一条语句。
如下图所示,因为第一个红框处前几句语句都没有;
分号,所以直到最后一句才被认为是sql语句结束,所以被当作前几行语句是一句sql语句,从而报错。
连接、操作MySQL数据库
连接操作数据库过程中会用到的类,如下图所示。
Java工程连接、操作数据库
下面每一行代码的含义补入本文 三、
补入本文,好好看!
- 首先将jar包
mysql-connector-java-8.0.30.jar
导入Java工程的正确位置,通常在lib目录下。Java工程导入jar包的方法详见这篇博客。
- 设置JDBC驱动名和数据库URL,JDBC连接mysql数据库时默认使用IP地址
127.0.0.1
和端口号3306
,所以当连接数据库与此一致时,可省略数据库地址和端口为jdbc:mysql:///test
。
①MySQL 8.0 以下版本 - JDBC 驱动名(即jar包中的名称),注册JDBC驱动及数据库 URL
static final String JDBC_DRIVER = “com.mysql.jdbc.Driver”;
static final String DB_URL = “jdbc:mysql://localhost:3306/test”;
②// MySQL 8.0 以上版本 - JDBC 驱动名(即jar包中的名称),注册JDBC驱动及数据库 URL
static final String JDBC_DRIVER = “com.mysql.cj.jdbc.Driver”;
static final String DB_URL = “jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC”;
因为本次使用的是mysql-connector-java-8.0.30.jar
,如第一步中所述。若使用①中配置url,在第3步使用JDBC_DRIVER注册JDBC驱动时,会报如下错误Loading class 'com.mysql.jdbc.Driver'. This is deprecated. The new driver class is 'com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
。
- 加载数据库驱动(即jar包中的名称),注册JDBC驱动:
Class.forName(JDBC_DRIVER);
。
Class.forName(JDBC_DRIVER);来注册加载驱动的原因
Class.forName(类名)
是让JVM查找并加载该类名对应的类中的静态代码块,而本文示例中使用的是MySQL数据库,所以选择com.mysql.jdbc.Driver
类(MySQL数据库厂商提供的 JDBC 驱动,并借助于这些驱动连接数据库)中正好只有一段静态代码——使用Jdbc程序中的DriverManager来加载驱动,由此创建与数据库的链接,如下所示。
所以删除本句话及catch中本句,可能抛出的异常。
在实际开发中之所以推荐使用Class.forName(“com.mysql.jdbc.Driver”);
,而非registerDriver方法,来注册驱动,这是因为:
如果代码中直接使用mysql的jar包中的DriverManager类中的方法,会使程序依赖mysql jar包的api并与所使用的数据库产生耦合,当项目程序要更换底层数据库时,因为脱离mysql的jar包导致程序无法编译等非常麻烦的问题。
但此方式有问题,因为若更换数据库了,Class.forName(“com.mysql.jdbc.Driver”);
中的参数“com.mysql.jdbc.Driver”
不需要变更吗???自认待确认
Class.forName(“com.mysql.jdbc.Driver”);
的内容详见此博客。
- 创建【并打开?(有博客提到,待确认)】到数据库的链接会用到的Connection对象,(其实就是创建了一个和数据库服务器进行连接的Socket(传输层,使用TCP)。当Java项目和数据库不在同一台机器上,还涉及到了网络IO,网络IO的速度并不快:
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC", "root", "");
“jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC”:是mySql数据库的url,其中的test
是数据库的名称,可通过net start mysql
启动数据库、mysql -u root -p
登录数据库后,在mysql>
下(自认,即数据库内)使用show databases;
查看当前电脑上现有数据库的所有名称。
- 创建【执行sql语句、负责对数据库进行操作】的对象:
statement = connection.生成各类statement方法();
,如下方备注所示。
statement = connection.createStatement();
//返回Statement接口对象。此时查询结果java.sql.resultset只能一条条向下读,如果在代码中使用resultSet.beforeFirst();
试图回滚到resultSet第一条时,会报错java.sql.resultset is type_forward_only
。此时就需要使用带参数的构造方法,statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
以设置ResultSet回滚查询,但是sqlite数据库不支持回退模式,会报错提示。
//
statement = connection.prepareStatement(...);
//返回PreparedStatement接口对象,PreparedStatement继承自Statement。
statement = connection.prepareCall(...);
//返回CallableStatement接口对象,CallableStatement继承自PreparedStatement。
Statement接口有两个子类,分别是PreparedStatement和CallableStatement:connection.prepareStatement(...)
返回PreparedStatement对象和connection.prepareCall(...);
返回CallableStatement对象。
- 编写要执行的sql语句,比如查询,请注意sql语句要以分号结尾:
String sqlString = "select * from hogwarts_user;";
。
使用show tables;
来查看当前数据库test
中的表(Tables_in_test
)有哪些,如下图所示。
- 使用第5步中创建的“执行sql语句的对象”statement的对应方法来执行对应sql操作:比如本次选择使用
statement.executeQuery(sqlString)
来执行第6步中编写的SQL语句。
- execute(String sql):方法声明为
boolean java.sql.Statement.execute(String sql)
。本方法可用来执行所有的SQL语句,本方法的返回值表示方法执行的SQL语句的类型——执行DML的SQL语句则返回false,执行DQL的SQL语句则返回true。
- executeQuery(sqlString):方法声明为
ResultSet executeQuery(String sql) throws SQLException;
。本方法用来执行DQL的SQL语句,本方法的返回值是执行DQL的SQL查询的结果集。查询结果返回给“java.sql.ResultSet”:ResultSet resultSet = statement.executeQuery(sqlString);
。
- executeUpdate(sqlString):方法声明为
int executeUpdate(String sql) throws SQLException;
。本方法用来执行DML的SQL语句,本方法的返回值是本次SQL操作中受影响的记录条数。
- 输出resultSet中的查询结果:如下所示。需要注意的是,
java.sql.ResultSet
也需要close()关闭。
//输出查询结果
while (resultSet.next()) {
int id = resultSet.getInt("id");//resultSet.getInt用于获取int类型的结果
String nameString = resultSet.getString("name");//resultSet.getString用于获取String类型的结果
String ageString = resultSet.getString("age");
System.out.print("id是"+id);
System.out.print(",name是"+nameString);
System.out.println(",age是"+ageString);
System.out.println("---------------");
}
遍历输出MySQL查询结果java.sql.ResultSet
方法详见此博客。
完整代码示例
完整代码,如下所示。
import java.sql.*;
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;//java.sql.ResultSet也需要close关闭!
// MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
// static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
// static final String DB_URL = "jdbc:mysql://localhost:3306/test";
// MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
try{
//通过Class.forName加载“com.mysql.cj.jdbc.Driver”类中的静态代码,来使用mysql数据库jar包中代码的方式,加载数据库驱动(即jar包中的名称),注册JDBC驱动。
Class.forName(JDBC_DRIVER);
//打开链接
connection = DriverManager.getConnection(DB_URL, "root", "");
//创建sql查询
statement = connection.createStatement();
//sql语句
String sqlString = "select * from hogwarts_user;";
//执行查询,获取sql查询结果
resultSet = statement.executeQuery(sqlString);
//输出查询结果
while (resultSet.next()) {//此循环条件自测无误,不会导致错过一条
int id = resultSet.getInt("id");
String nameString = resultSet.getString("name");
String ageString = resultSet.getString("age");
System.out.print("id是"+id);
System.out.print(",name是"+nameString);
System.out.println(",age是"+ageString);
System.out.println("---------------");
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//此部分虽然保证了数据库的安全开启、关闭,但造成了大量时间开销,所以建议使用连接池实现对数据库的连接和操作
if (resultSet!=null) {//java.sql.ResultSet也需要close!
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (statement!=null) {
try {
statement.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();
}
}
}
Java工程通过连接池实现连接、操作数据库
JDBC中使用连接时都要创建一个Connection对象,使用完毕后将其销毁,这种重复创建、销毁、创建、销毁…的过程是特别耗费计算机性能以及计算时间的,而数据库如果使用了数据库连接池,就能达到Connection对象的复用效果。
Java工程使用连接池实现连接、操作数据库详见此博客。
SpringMVC工程连接、操作数据库