目录
前言
1、Java的数据库编程:JDBC
2、使用JDBC(项目中导入数据库驱动包)
2.1、获取驱动包
2.2、将数据库驱动包导入Java项目中
2.3、使用JDBC编写代码
2.3.1、创建并初始化一个数据源
2.3.2、 和数据库服务器建立链接
2.3.3、构建SQL语句
2.3.4、执行SQL语句
2.3.4、释放资源
2.3.5、JDBC的方式插入数据(insert)
2.3.6、JDBC的方式查询数据(select)
前言
- 我们使用的数据库有多种多样的,有MySQL、Oracle、SQL sever等等、这些数据库在开发的时候,都会提供一组程序接口(API).
- API(Application Programming Interface):我们就举一个更简单一点的例子。软件开发员甲开发了一款软件,但是这款软件里面某些功能软件开发员乙也想使用,这个时候甲就可以把软件里面的这些功能打包成一个函数,开放给乙进行使用,乙自然也就不需要进行源码的查看,那么这个函数也就是api。我们基于api提供的功能来实现一些其他的代码。
- JDBC存在两种写法,一种是DataSource的方式来编写的(这种是现在使用比较多的,也是这个博客中介绍的方法);还有一种是DriverManager方式编写,这个是通过反射的方式加载驱动包中的类,进一步进行后续的操作。这里更建议使用第一种方法。
1、Java的数据库编程:JDBC
上面说到的MySQL、Oracle、SQL sever等等这些数据库,都会提供一个api接口,但是不同的数据库存在自己的数据库api,这样就导致程序员的学习成本太高。没使用一种数据库还要学习它的api。如果有一个东西可以规范这些接口,那么学习成本就降低了很多,这里我们就要说到JDBC。
- JDBC(Java Database Connectivity),他是一套统一的、基于Java语言的关系数据库编程接口的规范。
- 对于这些数据库的api,这些数据库的厂商需要自己提供一个封装自己数据库的原生api的程序与JDBC对齐,这个程序就叫做数据库驱动包。
对于Java程序员想要进行数据库的开发,就需要在项目中导入对应的数据库驱动包,才能进行编写代码。
这里解释一下驱动的意思:驱动这个词我们在硬件中常会听到,硬件的驱动是让操作系统认识新的硬件设备。而我们这里的数据库的驱动就是让JDBC能够认识数据库的api.
2、使用JDBC(项目中导入数据库驱动包)
2.1、获取驱动包
三种途径
- MySQL的官方网站上获取
- 因为MySQL是开源的所以可以在github中找
- maven中央仓库中获取。
maven就像我们使用手机的应用商店一样。手机上下载软件可以去官网也可以在手机的应用商店上找。maven中央仓库上面托管了各种软件程序包。进入mavem中央仓库使用链接https://mvnrepository.com
1️⃣下面这两种都可以
2️⃣ 在点击进入之后,让我们选择使用的版本,这里注意,选的版本要与我们自己装的数据库版本匹配。大版本一定要匹配,小版本可以随便选。
3️⃣ 点击选择需要的版本进入之后,点击jar下载即可。
4️⃣得到jar包
在javase的博客中说到Java程序通过.java 源文件编译成.class文件,再使用jvm来解释执行成 .class文件。我们想要发布一个程序让别人使用,我们可以将这些.class文件拷贝给对方,使用它的jvm运行就行。但是又有一个问题,当我们的程序有很多的.class 文件,这样一起拷贝给对方,总显得不太好用,这个时候我们可以使用压缩包的形式,将多个.class文件以压缩包的形式发给对方。这就是Java中最常用的发布程序的方式,形成.jar包。
2.2、将数据库驱动包导入Java项目中
❗❗❗每创建一个项目需要这样操作一次
1️⃣创建一个新的项目,并在这个项目中创建一个新的目录lib,将数据库驱动包导入
2️⃣把lib这个目录标记成项目的库
将这个目录标记成库,idea就能识别这个目录里的jar包了。我们就可以调用里面的类来写代码了。
2.3、使用JDBC编写代码
2.3.1、创建并初始化一个数据源
数据源:我们的数据从数据库中来,所以数据源就是用来描述数据库服务器在哪里的。JDBC中用DataSource这个接口来进行描述。
这里有两种写法。
1️⃣使用DataSource接口的引用接收MysqlDataSource对象
DataSource dataSource = new MysqlDataSource();//向上转型 ((MysqlDataSource)dataSource).setUrl();//向下转型,因为DataSource中没有setUrl()这个方法,而MysqlDataSource这个类中有这个方法
2️⃣或者直接使用MysqlDataSource类来写也可以
MysqlDataSource mysqlDataSource = new MysqlDataSource(); mysqlDataSource.setUrl();
setUrl()方法表示设置资源所在的位置。这里URL是计算机里的一个常见术语——唯一资源定位符,描述网络上的某个资源所在的位置。 这个方法的参数形式很特别
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/people_2?characterEncoding=utf8&useSSL=false");
对他的参数大概了解一下
jdbc是固定的。
MySQL:是看你使用什么数据库,这是一个数据库名。
MySQL数据库是一个“客户端-服务器”结构的程序,客户端和服务器之间通过网络来通信,网络上确定主机的位置就是通过IP地址来确定的,现在我们学习的时候客户端和服务器在同一台电脑上,我们使用的是环回地址。
127.0.0.1:是环回地址,表示当前主机地址
3306:是端口号,数据库服务器默认端口就是3306.端口是用来区分应用程序的。区分将数据个那个应用程序。
people_2:表示的数据库名,我们创建了很多数据库,到底想访问哪一个。
characterEncoding:表示的是参数
utf8:字符集
SSL:是一个加密协议,此处设置成false表示不加密
设置用户名和密码
((MysqlDataSource)dataSource).setUser("root");//设置用户的时候,都是root
((MysqlDataSource)dataSource).setPassword("991218zf");//设置密码的时候,安装数据库的时候密码是什么就是什么
上述这些步骤合起来就是设置数据源的基本操作,只有将这三个都设置了,才能够访问数据库服务器
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
public class JDBCInsert {
public static void main(String[] args) {
//1、创建并初始化一个数据源
DataSource dataSource = new MysqlDataSource();//向上转型
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/people_2?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("991218zf");
❗❗❗提示:上述的代码只是设置了数据源,描述数据库服务器在哪,还没有和数据库服务器真正的链接。
2.3.2、 和数据库服务器建立链接
我们使用DataSource接口的getConnection方法来实现链接。
Connection connection = dataSource.getConnection() ;
在使用connection用来接收的时候,我们要选择第一个,第一个是JDBC提供的,第二个是MySQL数据包提供的,不能使用。
但是当我们将这个写了之后,编译器会报错。
所以我们需要将这个异常进行处理,异常有受查异常和非受查异常
受查异常必须要显示处理,处理方式有两种
1️⃣在调用这个方法的方法体开始throws这个异常
2️⃣或者通过try-catch处理这个异常
非受查异常可以不用显示处理。
2.3.3、构建SQL语句
String sql = "insert into student values(1,'张三')";
PreparedStatement statement = connection.prepareStatement(sql);//进行预编译
通过第一句代码可以看见即使我们使用代码来操作数据库,还是靠sql语句,只不过是换成代码来构造sql。
❓❓❓第二句代码的作用是提前预编译sql语句,为什么要进行预编译呢?
❗❗❗数据库客户端给服务器发送一个请求时SQL字符串,服务器是可以处理的,服务器需要对SQL经行解析,理解这里的含义并执行,这对于服务器的压力就比较大了,如果是一个客户端,那没有什么问题,但是一个服务器同时可以接收很多客户端发送的请求,都是以这样的形式发送的,那么服务器的压力就非常大了。这里我们通过在客户端这里将这个SQL字符串进行预编译,转换成sql语句,这样数据库服务器的压力就非常小了。
上述构造SQL语句的这种写法存在问题。直接将代码写死了,只能插入一条数据,但是用户在使用的时候,要插入的数据肯定不止一条。我们要实现写一个插入的SQL语句,进行多条数据的插入。我们可以通过scanner类来实现让用户插入数据。
构造sql语句时存在多种写法
1️⃣比较直接的写法,通过字符串拼接的方法实现。
String sql = "insert into student values("+id+",'"+name+"')";
这种写法是下策,它存在两个问题
- name这里添加单引号和双引号的位置很容易写错,可读性很低
- 很容易被SQL注入,sql注入是网络安全中的典型攻击方式,指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,这就导致在程序员不知情的情况下,将数据库中的数据删除或者修改。
2️⃣更好的写法,借助PreparedStatement的拼装功能来实现。
String sql = "insert into student values(?,?)";//这里的?表示的意思是占位符,表示先这个位置占住,用别的东西替换。 PreparedStatement statement = connection.prepareStatement(sql);//进行预编译 statement.setInt(1,id);//表示将第一个?替换成id的值 statement.setString(2,name);//表示将第二个?替换成name的值
这个方法好处就是看起来更加直观了,并且可以自动的对sql注入的攻击的行为作为校验。
2.3.4、执行SQL语句
int ret = statement.executeUpdate();
System.out.println("ret = "+ret);
这里通过executeUpdate方法把sql语句(预编译过的)发送给数据库服务器,由服务器做出响应。
executeUpdate方法返回int类型的指用ret接收,这里ret接收到的值表示为执行sql语句后影响到的行数。与数据库中的这个表示的同一个意思
这里执行insert、delete、update这些操作的时候都使用executeUpdate这个方法。
2.3.4、释放资源
statement.close();
connection.close();
数据库的客户端和服务器之间通信的时候,是要消耗一定的系统资源(这里的资源不限于CPU、内存、硬盘、带宽)。 对客户端来说罢了,但是对服务器来说,同一时刻要处理很多个客户端,给一个客户端提供服务,需要消耗一定的资源,给1000个、一万个呢???这个时候消耗的资源就越来越多,服务器的资源就那么多,如何更好的利用这些资源?客户端就得省着点用(不用的时候就将资源释放)。
❗❗❗注意:释放的顺序和创建的顺序是相反的。在下面的代码中链接(connection)是先创建的,语句(statement)是后创建的。所以释放的时候statement先释放, connection后释放
2.3.5、JDBC的方式插入数据(insert)
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class JDBCInsert {
public static void main(String[] args) throws SQLException{
Scanner scan = new Scanner(System.in);
//1、创建并初始化一个数据源
DataSource dataSource = new MysqlDataSource();//向上转型
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/people_2?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("991218zf");
//2、和数据库服务器建立联接
Connection connection= dataSource.getConnection() ;
//3、构造SQL语句
System.out.println("请输入学生姓名:");
String name = scan.next();
System.out.println("请输入学生的学号:");
int id = scan.nextInt();
String sql = "insert into student values(?,?)";
PreparedStatement statement = connection.prepareStatement(sql);//进行预编译
statement.setInt(1,id);//表示将第一个?替换成id的值
statement.setString(2,name);//表示将第二个?替换成name的值
//这个打印需要加到拼接数据之后
System.out.println(statement);
//4、执行SQL语句
int ret = statement.executeUpdate();
System.out.println("ret = "+ret);
//5、释放必要的资源
statement.close();
connection.close();
}
}
这里修改(update)和删除(delete)这两个操作在JDBC中的代码和插入相同只需要将sql语句改变一下就行。
2.3.6、JDBC的方式查询数据(select)
对查询来说,返回结果不是单纯的int了,而是ResultSet对象,表示的就是结果集合,相当于我们使用MySQL时,在客户端查询产生结果得到的临时表。
当光标指向哪一行,就通过getXXX方法将哪一行的数据获取。
代码示例
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.*;
import java.util.logging.Logger;
public class JDBCSelect {
public static void main(String[] args) throws SQLException{
//1、创建并初始化数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/people_2?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("991218zf");
//2、建立链接
Connection connection = dataSource.getConnection();
//3、构造SQL
String sql = "select * from student";
PreparedStatement statement = connection.prepareStatement(sql);
//4、执行SQL
ResultSet resultSet = statement.executeQuery();
//5、遍历结果集合
while(resultSet.next()){
//把resultSet想象成一个表格,同时这个这个表格上方有一个光标,初始情况下光标指向表的最上面
//没调用一次next,光标往下走一行
//当光标指向某一行的时候,就可以通过 getxxx 方法来获取到当前这行里的数据
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("id = "+ id +",name = "+name);
}
//6、释放资源
statement.close();
connection.close();
}
}